extern "C" 
{

//------------------------------------------------------------------------------------
// irr::video::IVideoDriver wrappers
// use irr:IrrlichtDevice.getVideoDriver() to get a pointer for this
//------------------------------------------------------------------------------------
	
	bool IrrVideo_IVideoDriver_beginScene(IVideoDriver* driver,bool backBuffer = true, bool zBuffer = true,SColor* color=0, SExposedVideoData* videoData = 0, rect<s32>* sourceRect=0)
	{
		bool lRetVal=false;
	
		if (driver>0) {			
			lRetVal=driver->beginScene(backBuffer,zBuffer,((color==0) ? 0 : *color), (videoData==0 ? SExposedVideoData() : *videoData), sourceRect);
		}
	
		return lRetVal;
	}
	
	bool IrrVideo_IVideoDriver_endScene(IVideoDriver* driver)
	{
		bool lRetVal=false;
	
		if (driver>0)
			lRetVal=driver->endScene();
	
		return lRetVal;
	}
	
	bool IrrVideo_IVideoDriver_queryFeature(IVideoDriver* driver,E_VIDEO_DRIVER_FEATURE feature)
	{
		if (driver)
			return driver->queryFeature(feature);
		else
			return false;
	}
	
	void IrrVideo_IVideoDriver_setTransform(IVideoDriver* driver,E_TRANSFORMATION_STATE state,matrix4* mat)
	{
		if (driver)
			driver->setTransform(state,*mat);
	}
	
	// do not delete ptr
	IGPUProgrammingServices* IrrVideo_IVideoDriver_getGPUProgrammingServices(IVideoDriver* driver)
	{
		if (driver)
			return driver->getGPUProgrammingServices();
		else	return 0;
	}
	
	matrix4* IrrVideo_IVideoDriver_getTransform(IVideoDriver* driver,E_TRANSFORMATION_STATE state)
	{
		if (driver)
			return new matrix4(driver->getTransform(state));
		else
			return 0;
	}
	
	void IrrVideo_IVideoDriver_setMaterial(IVideoDriver* driver,SMaterial* material)
	{
		if (driver)
			driver->setMaterial(*material);
	}
	
	ITexture* IrrVideo_IVideoDriver_getTexture(IVideoDriver* driver,const c8 *filename)
	{
		if (driver)
			return driver->getTexture(path(filename));
		else
			return 0;
	}
	
	ITexture* IrrVideo_IVideoDriver_getTextureFromStream(IVideoDriver* driver,IReadFile* file)
	{
		if (driver)
			return driver->getTexture(file);
		else
			return 0;
	}
	
	ITexture* IrrVideo_IVideoDriver_addTexture(IVideoDriver* driver,dimension2d<s32>* size,const c8 *name, ECOLOR_FORMAT format=ECF_A8R8G8B8)
	{
		if (driver)
			return driver->addTexture(dimension2du(*size), path(name), format);
		else
			return 0;
	}
	
	ITexture* IrrVideo_IVideoDriver_addTextureFromImage(IVideoDriver* driver,const c8 *name,IImage* image, void* mipmapData = 0)
	{
		if (driver)
			return driver->addTexture(path(name), image, mipmapData);
		else
			return 0;
	}
	
	void IrrVideo_IVideoDriver_removeTexture(IVideoDriver* driver,ITexture *texture)
	{
		if (driver)
			driver->removeTexture(texture);
	}
	
	void IrrVideo_IVideoDriver_removeAllTextures(IVideoDriver* driver)
	{
		if (driver)
			driver->removeAllTextures();
	}
	
	void IrrVideo_IVideoDriver_makeColorKeyTexture(IVideoDriver* driver,ITexture* texture,SColor* color, bool zeroTexels = false)
	{
		if (driver)
			driver->makeColorKeyTexture(texture, *color, zeroTexels);
	}
	
	void IrrVideo_IVideoDriver_makeColorKeyTextureFromPixel(IVideoDriver* driver,ITexture* texture,position2d<s32>* colorKeyPixelPos, bool zeroTexels = false)
	{
		if (driver)
			driver->makeColorKeyTexture(texture, *colorKeyPixelPos, zeroTexels);
	}
	
	void IrrVideo_IVideoDriver_makeNormalMapTexture(IVideoDriver* driver,ITexture* texture,f32 amplitude=1.0f)
	{
		if (driver)
			driver->makeNormalMapTexture(texture,amplitude);
	}
	
	bool IrrVideo_IVideoDriver_setRenderTarget(IVideoDriver* driver,ITexture* texture,bool clearBackBuffer=true,bool clearZBuffer=true,SColor* color=0)
	{
		if (driver) 
			return driver->setRenderTarget(texture,clearBackBuffer,clearZBuffer, (color ? *color : SColor(0,0,0,0)));
		else return false;
	}
	
	bool IrrVideo_IVideoDriver_setRenderTargetByEnum(IVideoDriver* driver,E_RENDER_TARGET target,bool clearBackBuffer=true,bool clearZBuffer=true,SColor* color=0)
	{
		if (driver) 	
			return driver->setRenderTarget(target,clearBackBuffer,clearZBuffer, (color ? *color : SColor(0,0,0,0)));
		else return false;
	}

	bool IrrVideo_IVideoDriver_setRenderTargetByRenderTarget(IVideoDriver* driver,IRenderTarget** target, u32 numTargets, bool clearBackBuffer=true,bool clearZBuffer=true,SColor* color=0)
	{
		if (driver) {
			array<IRenderTarget> target_array;
			for (int i=0; i<numTargets; i++) {	
				target_array.push_back(*target[i]);
			}
			return driver->setRenderTarget(target_array, clearBackBuffer, clearZBuffer, (color ? *color : SColor(0,0,0,0)));
		} else return false;
	}

	void IrrVideo_IVideoDriver_setViewPort(IVideoDriver* driver,rect<s32>* area)
	{
		if (driver)
			driver->setViewPort(*area);
	}
	
	rect<s32>* IrrVideo_IVideoDriver_getViewPort(IVideoDriver* driver)
	{
		if (driver)
			return new rect<s32>(driver->getViewPort());
		else
			return 0;
	}

	void IrrVideo_IVideoDriver_drawVertexPrimitiveList(IVideoDriver* driver,const void* vertices, u32 vertexCount, const void* indexList, u32 primCount, E_VERTEX_TYPE vType = EVT_STANDARD, E_PRIMITIVE_TYPE pType = EPT_TRIANGLES, E_INDEX_TYPE iType = EIT_16BIT)
	{
		if (driver)
			driver->drawVertexPrimitiveList(vertices, vertexCount, indexList, primCount, vType, pType, iType);
	}
	
	void IrrVideo_IVideoDriver_draw2DVertexPrimitiveList(IVideoDriver* driver,const void* vertices, u32 vertexCount, const void* indexList, u32 primCount, E_VERTEX_TYPE vType = EVT_STANDARD, E_PRIMITIVE_TYPE pType = EPT_TRIANGLES, E_INDEX_TYPE iType = EIT_16BIT)
	{
		if (driver)
			driver->draw2DVertexPrimitiveList(vertices, vertexCount, indexList, primCount, vType, pType, iType);
	}

	void IrrVideo_IVideoDriver_draw3DLine(IVideoDriver* driver,vector3df* start,vector3df* end,SColor* color=0)
	{
		if (driver) {
			bool delC=false;
			if (!color) {
				color=new SColor(255,255,255,255);
				delC=true;
			}
			driver->draw3DLine(*start,*end,*color);
			if (delC) delete color;
		}
	}
	
	void IrrVideo_IVideoDriver_draw3DTriangle(IVideoDriver* driver,triangle3df* triangle,SColor* color=0)
	{
		if (driver) {
			bool delC=false;
			if (!color) {
				color=new SColor(255,255,255,255);
				delC=true;
			}
			driver->draw3DTriangle(*triangle,*color);
			if (delC) delete color;
		}
	}
	
	void IrrVideo_IVideoDriver_draw3DBox(IVideoDriver* driver,aabbox3df* box,SColor* color=0)
	{
		if (driver) {
			bool delC=false;
			if (!color) {
				color=new SColor(255,255,255,255);
				delC=true;
			}
			driver->draw3DBox(*box,*color);
			if (delC) delete color;
		}
	}
	
	void IrrVideo_IVideoDriver_draw2DImage(IVideoDriver* driver,ITexture* texture,position2d<s32>* destPos)
	{
		if (driver)
			driver->draw2DImage(texture,*destPos);
	}
	
	void IrrVideo_IVideoDriver_draw2DImageSegment(
		IVideoDriver* driver,
		ITexture* texture,position2d<s32>* destPos, 
		rect<s32>* sourceRect, 
		rect<s32>* clipRect=0,
		SColor* color=0,
		bool useAlphaChannelOfTexture=false)	
	{
		if (driver) {
	
			bool delC=false;
			if (!color) {
				color=new SColor(255,255,255,255);
				delC=true;
			}
			driver->draw2DImage(texture,*destPos,*sourceRect,clipRect,*color,useAlphaChannelOfTexture);
			if (delC) delete color;
		}
	}
			
	// cliprect=0, color=0, useAlpha=false
	void IrrVideo_IVideoDriver_draw2DImageSegmentToRect(
		IVideoDriver* driver,
		ITexture* texture,
		rect<s32>* destRect, 
		rect<s32>* sourceRect, 
		rect<s32>* clipRect=0,
		SColor** colorArr=0,
		s32 colorArrSize=0,
		bool useAlphaChannelOfTexture=false)	
	{
		if (driver) {
		
			array<SColor> color;
			for (int i=0; i<colorArrSize; i++) {	
				color.push_back(*colorArr[i]);
			}
		
			driver->draw2DImage(texture,*destRect,*sourceRect,clipRect,color.pointer(),useAlphaChannelOfTexture);
		}
	}
	
	void IrrVideo_IVideoDriver_draw2DRectangle(IVideoDriver* driver,SColor* color,rect<s32>* pos,rect<s32>* clip=0)
	{
		if (driver)
			driver->draw2DRectangle(*color,*pos,clip);
	}
		
	void IrrVideo_IVideoDriver_draw2DRectangleWithGradient(IVideoDriver* driver,rect<s32>* pos,SColor* colorLeftUp,SColor* colorRightUp,SColor* colorLeftDown,SColor* colorRightDown,rect<s32>* clip=0)
	{
		if (driver)
			driver->draw2DRectangle(*pos,*colorLeftUp,*colorRightUp,*colorLeftDown,*colorRightDown,clip);
	}
	
	void IrrVideo_IVideoDriver_draw2DRectangleOutline(IVideoDriver* driver, recti* pos, SColor* color = 0) {
		if (driver)
			driver->draw2DRectangleOutline(*pos, (color ? *color : SColor(255,255,255,255)));
	}

	void IrrVideo_IVideoDriver_draw2DLine(IVideoDriver* driver,position2d<s32>* start,position2d<s32>* end,SColor* color=0)
	{
		if (driver) {
			bool delC=false;
			if (!color) {
				color=new SColor(255,255,255,255);
				delC=true;
			}
			driver->draw2DLine(*start,*end,*color);
			if (delC) delete color;
		}
	}

	void IrrVideo_IVideoDriver_draw2DPolygon(IVideoDriver* driver,position2d<s32>* center,f32 radius, SColor* color=0, s32 vertexCount=10) 
	{
		if (driver) {
			bool delC=false;
			if (!color) {
				color=new SColor(100,255,255,255);
				delC=true;
			}
			driver->draw2DPolygon(*center,radius,*color,vertexCount);
			if (delC) delete color;
		}
	}
	
	void IrrVideo_IVideoDriver_drawStencilShadowVolume(IVideoDriver* driver,vector3df triangles[],s32 count,bool zfail=true)
	{
		if (driver)
			driver->drawStencilShadowVolume(triangles,count,zfail);
	}
	
	void IrrVideo_IVideoDriver_drawStencilShadow(IVideoDriver* driver,bool clearStencilBuffer=false,SColor* leftUpEdge=0,SColor* rightUpEdge=0,SColor* leftDownEdge=0,SColor* rightDownEdge=0)
	{
		if (driver) {
			bool delLU=false,delRU=false,delLD=false,delRD=false;
	
			// default the colors if needed
			if (!leftUpEdge) {
				leftUpEdge=new SColor(255,0,0,0);
				delLU=true;
			}
			if (!rightUpEdge) {
				rightUpEdge=new SColor(255,0,0,0);
				delRU=true;
			}
			if (!leftDownEdge) {
				leftDownEdge=new SColor(255,0,0,0);
				delLD=true;
			}
			if (!rightDownEdge) {
				rightDownEdge=new SColor(255,0,0,0);
				delRD=true;
			}
	
			driver->drawStencilShadow(clearStencilBuffer,*leftUpEdge,*rightUpEdge,*leftDownEdge,*rightDownEdge);
	
			// clean up any created defaults
			if (delLU) delete leftUpEdge;
			if (delRU) delete rightUpEdge;
			if (delLD) delete leftDownEdge;
			if (delRD) delete rightDownEdge;
		}
	}
	
	void IrrVideo_IVideoDriver_drawMeshBuffer(IVideoDriver* driver,IMeshBuffer* mb)
	{
		if (driver)
			driver->drawMeshBuffer(mb);
	}
	
	void IrrVideo_IVideoDriver_setFog(IVideoDriver* driver,SColor* color=0, E_FOG_TYPE fogType=EFT_FOG_LINEAR, f32 start=50.0f,f32 end=100.0f,f32 density=0.01f,bool pixelFog=false,bool rangeFog=false)
	{
		if (driver) {
			// check to see if need to default color
			bool delColor=false;
			if (!color) {
				color=new SColor(0,255,255,255);
				delColor=true;
			}
	
			driver->setFog(*color,fogType,start,end,density,pixelFog,rangeFog);
	
			// clean up if defaulted
			if (delColor) delete color;
		}
	
	}
	
	dimension2d<s32>* IrrVideo_IVideoDriver_getScreenSize(IVideoDriver* driver)
	{
		if (driver)
			return new dimension2d<s32>(driver->getScreenSize());
		else
			return 0;
	}

	dimension2d<s32>* IrrVideo_IVideoDriver_getCurrentRenderTargetSize(IVideoDriver* driver)
	{
		if (driver)
			return new dimension2d<s32>(driver->getCurrentRenderTargetSize());
		else return 0;
	}
	
	s32 IrrVideo_IVideoDriver_getFPS(IVideoDriver* driver)
	{
		if (driver)
			return driver->getFPS();
		else
			return -1;
	}
	
	u32 IrrVideo_IVideoDriver_getPrimitiveCountDrawn(IVideoDriver* driver,u32 param = 0)
	{
		if (driver)
			return driver->getPrimitiveCountDrawn(param);
		else
			return 0;
	}
	
	void IrrVideo_IVideoDriver_deleteAllDynamicLights(IVideoDriver* driver)
	{
		if (driver)
			driver->deleteAllDynamicLights();
	}
	
	void IrrVideo_IVideoDriver_addDynamicLight(IVideoDriver* driver,SLight* light)
	{
		if (driver)
			driver->addDynamicLight(*light);
	}
	
	void IrrVideo_IVideoDriver_setAmbientLight(IVideoDriver* driver,SColorf* color)
	{
		if (driver)
			driver->setAmbientLight(*color);
	}
	
	u32 IrrVideo_IVideoDriver_getMaximalDynamicLightAmount(IVideoDriver* driver)
	{
		if (driver)
			return driver->getMaximalDynamicLightAmount();
		else
			return -1;
	}
	
	u32 IrrVideo_IVideoDriver_getDynamicLightCount(IVideoDriver* driver)
	{
		if (driver)
			return driver->getDynamicLightCount();
		else
			return -1;
	}
	
	SLight* IrrVideo_IVideoDriver_getDynamicLight(IVideoDriver* driver,u32 idx)
	{
		if (driver)
			return new SLight(driver->getDynamicLight(idx));
		else
			return 0;
	}
	
	const c8* IrrVideo_IVideoDriver_getName(IVideoDriver* driver)
	{
		if (driver) {
			stringc* name=new stringc(driver->getName());
			return name->c_str();
		} else return 0;
	}
	
	u32 IrrVideo_IVideoDriver_getMaximalPrimitiveCount(IVideoDriver* driver)
	{
		if (driver)
			return driver->getMaximalPrimitiveCount();
		else
			return -1;
	}
	
	void IrrVideo_IVideoDriver_setTextureCreationFlag(IVideoDriver* driver,E_TEXTURE_CREATION_FLAG flag,bool enabled = true)
	{
		if (driver)
			driver->setTextureCreationFlag(flag,enabled);
	}
	
	bool IrrVideo_IVideoDriver_getTextureCreationFlag(IVideoDriver* driver,E_TEXTURE_CREATION_FLAG flag)
	{
		if (driver)
			return driver->getTextureCreationFlag(flag);
		else
			return false;
	}
	
	IImage* IrrVideo_IVideoDriver_createImageFromFile(IVideoDriver* driver,const c8 *filename)
	{
		if (driver)
			return driver->createImageFromFile(path(filename));
		else
			return 0;
	}
	
	IImage* IrrVideo_IVideoDriver_createImageFromStream(IVideoDriver* driver,IReadFile* file)
	{
		if (driver)
			return driver->createImageFromFile(file);
		else
			return 0;
	}
	
	IImage* IrrVideo_IVideoDriver_createImageFromData(IVideoDriver* driver,ECOLOR_FORMAT format,dimension2d<s32>* size,void *data,bool ownForeignMemory=false,bool deleteMemory = true)
	{
		if (driver)
			return driver->createImageFromData(format,dimension2du(*size),data,ownForeignMemory,deleteMemory);
		else
			return 0;
	}

	IImage* IrrVideo_IVideoDriver_createImageEmpty(IVideoDriver* driver,ECOLOR_FORMAT format, core::dimension2d<s32>* size)
	{
		if (driver)
			return driver->createImage(format, dimension2du(*size));
		else return 0;
	}

	IImage* IrrVideo_IVideoDriver_createImageFromImage(IVideoDriver* driver,ECOLOR_FORMAT format, IImage *imageToCopy)
	{
		if (driver)
			return driver->createImage(format, imageToCopy);
		else return 0;
	}

	IImage* IrrVideo_IVideoDriver_createImageFromImagePart(IVideoDriver* driver,IImage* imageToCopy, core::position2d<s32>* pos, core::dimension2d<s32>* size)
	{
		if (driver)
			return driver->createImage(imageToCopy, *pos, dimension2du(*size));
		else return 0;
	}

    void IrrVideo_IVideoDriver_OnResize(IVideoDriver* driver, dimension2d<s32>* size)
    {
        if (driver)
            driver->OnResize(dimension2du(*size));
    }    		
	
	u32 IrrVideo_IVideoDriver_getMaterialRendererCount(IVideoDriver* driver)
	{
		if (driver)
			return driver->getMaterialRendererCount();
		else
			return -1;
	}
	
	// dont delete reference
	IMaterialRenderer* IrrVideo_IVideoDriver_getMaterialRenderer(IVideoDriver* driver,u32 idx)
	{
		if (driver)
			return driver->getMaterialRenderer(idx);
		else
			return 0;
	}
	
	SExposedVideoData* IrrVideo_IVideoDriver_getExposedVideoData(IVideoDriver* driver)
	{
		if (driver)
			return new SExposedVideoData(driver->getExposedVideoData());
		else
			return 0;
	}
	
	s32 IrrVideo_IVideoDriver_getDriverType(IVideoDriver* driver)
	{
		if (driver)
			return driver->getDriverType();
		else
			return -1;
	}
	
	void IrrVideo_IVideoDriver_drawIndexedTriangleList(IVideoDriver* driver,array<S3DVertex>* vertices,array<u16>* indexList)
	{
		if (driver)
			driver->drawIndexedTriangleList(vertices->const_pointer(),vertices->size(),indexList->const_pointer(),(indexList->size()>0 ? indexList->size()/3 : 0));
	}
	
	void IrrVideo_IVideoDriver_drawIndexedTriangleListFromCoords(IVideoDriver* driver,array<S3DVertex2TCoords>* vertices,array<u16>* indexList)
	{
		if (driver)
			driver->drawIndexedTriangleList(vertices->const_pointer(),vertices->size(),indexList->const_pointer(),(indexList->size()>0 ? indexList->size()/3 : 0));
	}
	
	void IrrVideo_IVideoDriver_drawIndexedTriangleListTangents(IVideoDriver* driver,array<S3DVertexTangents>* vertices,array<u16>* indexList)
	{
		if (driver)
			driver->drawIndexedTriangleList(vertices->const_pointer(),vertices->size(),indexList->const_pointer(),(indexList->size()>0 ? indexList->size()/3 : 0));
	}
	
	void IrrVideo_IVideoDriver_drawIndexedTriangleFan(IVideoDriver* driver,array<S3DVertex>* vertices,array<u16>* indexList)
	{
		if (driver)
			driver->drawIndexedTriangleFan(vertices->const_pointer(),vertices->size(),indexList->const_pointer(),(indexList->size()>0 ? indexList->size()/3 : 0));
	}
	
	void IrrVideo_IVideoDriver_drawIndexedTriangleFanFromCoords(IVideoDriver* driver,array<S3DVertex2TCoords>* vertices,array<u16>* indexList)
	{
		if (driver)
			driver->drawIndexedTriangleFan(vertices->const_pointer(),vertices->size(),indexList->const_pointer(),(indexList->size()>0 ? indexList->size()/3 : 0));
	}
	
	void IrrVideo_IVideoDriver_clearZBuffer(IVideoDriver* driver)
	{
		if (driver)
			driver->clearZBuffer();
	}

	IMeshManipulator* IrrVideo_IVideoDriver_getMeshManipulator(IVideoDriver* driver)
	{
		if (driver)
			return driver->getMeshManipulator();
		else return 0;
	}
	
	// do not delete
	ITexture* IrrVideo_IVideoDriver_getTextureByIndex(IVideoDriver* driver,u32 index)
	{
		if (driver)
			return driver->getTextureByIndex(index);
		else return 0;
	}
	
	u32 IrrVideo_IVideoDriver_getTextureCount(IVideoDriver* driver)
	{
		if (driver)
			return driver->getTextureCount();
		else return -1;
	}
	
	s32  IrrVideo_IVideoDriver_addMaterialRenderer(IVideoDriver* driver,IMaterialRenderer* renderer,const char* name = 0)
	{
		if (driver)
			return driver->addMaterialRenderer(renderer,name);
		else return -1;
	}
	
	void IrrVideo_IVideoDriver_addExternalImageLoader(IVideoDriver* driver,IImageLoader* loader)
	{
		if (driver)
			driver->addExternalImageLoader(loader);
	}
	
	void IrrVideo_IVideoDriver_addExternalImageWriter(IVideoDriver* driver,IImageWriter* writer)
	{
		if (driver)
			driver->addExternalImageWriter(writer);
	}
	
	bool IrrVideo_IVideoDriver_writeImageToFile(IVideoDriver* driver, IImage* image, const char* filename, u32 param = 0)
	{
		if (driver)
			return driver->writeImageToFile(image,path(filename),param);
		else return false;
	}
	
	const char* IrrVideo_IVideoDriver_getMaterialRendererName(IVideoDriver* driver,u32 idx)
	{
		if (driver)
			return driver->getMaterialRendererName(idx);
		else return 0;
	}
	
	void IrrVideo_IVideoDriver_setMaterialRendererName(IVideoDriver* driver,s32 idx, const char* name)
	{
		if (driver)
			driver->setMaterialRendererName(idx,name);
	}
	
	io::IAttributes* IrrVideo_IVideoDriver_createAttributesFromMaterial(IVideoDriver* driver,SMaterial* material)
	{
		if (driver)
			return driver->createAttributesFromMaterial(*material);
		else return 0;
	}
	
	void IrrVideo_IVideoDriver_fillMaterialStructureFromAttributes(IVideoDriver* driver,SMaterial* outMaterial, IAttributes* attributes)
	{
		if (driver)
			driver->fillMaterialStructureFromAttributes(*outMaterial,attributes);
	}
	
	IImage* IrrVideo_IVideoDriver_createScreenShot(IVideoDriver* driver)
	{
		if (driver)
			return driver->createScreenShot();
		else return 0;
	}

	bool IrrVideo_IVideoDriver_drop(IVideoDriver* unk)
	{
		if (unk)
			return unk->drop();
		else return 0;
	}
	
	const c8* IrrVideo_IVideoDriver_getDebugName(IVideoDriver* unk)
	{
		if (unk)
			return unk->getDebugName();
		else return "";
	}
	
	void IrrVideo_IVideoDriver_grab(IVideoDriver* unk)
	{
		if (unk)
			unk->grab();
	}	

	void IrrVideo_IVideoDriver_renameTexture(IVideoDriver* driver,ITexture* texture, const c8* newName)
	{
		if (driver)
			driver->renameTexture(texture, path(newName));
	}

	// do not delete
	ITexture* IrrVideo_IVideoDriver_findTexture(IVideoDriver* driver, const c8* filename)
	{
		if (driver) {
			return driver->findTexture(path(filename));
		} else return 0;
	}
	
	bool IrrVideo_IVideoDriver_setClipPlane(IVideoDriver* driver, u32 index, plane3df* plane, bool enable=false)
	{
		if (driver) {
			return driver->setClipPlane(index, *plane, enable);
		} else return false;
	}

	void IrrVideo_IVideoDriver_enableClipPlane(IVideoDriver* driver, u32 index, bool enable)
	{
		if (driver) {
			driver->enableClipPlane(index, enable);
		}
	}
	
	void IrrVideo_IVideoDriver_setAllowZWriteOnTransparent(IVideoDriver* driver, bool flag)
	{
		if (driver)
			driver->setAllowZWriteOnTransparent(flag);
	}

	void IrrVideo_IVideoDriver_disableFeature(IVideoDriver* driver, E_VIDEO_DRIVER_FEATURE feature, bool flag = true)
	{
		if (driver)
			driver->disableFeature(feature, flag);
	}

	bool IrrVideo_IVideoDriver_checkDriverReset(IVideoDriver* driver)
	{
		if (driver)
			return driver->checkDriverReset();
		else return false;
	}

	// do not delete
	ITexture* IrrVideo_IVideoDriver_addRenderTargetTexture(IVideoDriver* driver, dimension2d<s32>* size, const c8* name = "rt", const ECOLOR_FORMAT format = ECF_UNKNOWN)
	{
		if (driver)
			return driver->addRenderTargetTexture(dimension2du(*size), path(name), format);
		else return 0;
	}
		
	void IrrVideo_IVideoDriver_removeHardwareBuffer(IVideoDriver* driver, const scene::IMeshBuffer* mb)
	{
		if (driver)
			driver->removeHardwareBuffer(mb);
	}
	
	void IrrVideo_IVideoDriver_removeAllHardwareBuffers(IVideoDriver* driver)
	{
		if (driver)
			driver->removeAllHardwareBuffers();
	}
	
	void IrrVideo_IVideoDriver_drawPixel(IVideoDriver* driver, u32 x, u32 y, const SColor* color)
	{
		if (driver)
			driver->drawPixel(x, y, *color);
	}
	
	s32 IrrVideo_IVideoDriver_getColorFormat(IVideoDriver* driver) // returns ECOLOR_FORMAT
	{
		if (driver)
			return driver->getColorFormat();
		else return -1;
	}
	
	const c8* IrrVideo_IVideoDriver_getVendorInfo(IVideoDriver* driver) 
	{
		if (driver)
			return driver->getVendorInfo().c_str();
		else return "";
	}

	// do not delete
	SOverrideMaterial* IrrVideo_IVideoDriver_getOverrideMaterial(IVideoDriver* driver)
	{
		if (driver)
			return &driver->getOverrideMaterial();
		else return 0;
	}


	void IrrVideo_IVideoDriver_setMinHardwareBufferVertexCount(IVideoDriver* driver, u32 count)
	{
		if (driver)
			driver->setMinHardwareBufferVertexCount(count);
	}

	IImage* IrrVideo_IVideoDriver_createImageFromTexturePart(IVideoDriver* driver, ITexture* texture, position2di* pos, dimension2di* size)
	{
		if (driver)
			return driver->createImage(texture, *pos, dimension2du(*size));
		else return 0;
	}

	bool IrrVideo_IVideoDriver_writeImageToFileIO(IVideoDriver* driver, IImage* image, IWriteFile* file, u32 param =0)
	{
		if (driver)
			return driver->writeImageToFile(image, file, param);
		else return false;
	}

	void IrrVideo_IVideoDriver_turnLightOn(IVideoDriver* driver, s32 lightIndex, bool turnOn)
	{
		if (driver)
			driver->turnLightOn(lightIndex, turnOn);
	}

	u32 IrrVideo_IVideoDriver_getImageLoaderCount(IVideoDriver* driver)
	{
		if (driver)
			return driver->getImageLoaderCount();
		else return 0;
	}
	
	// do not delete
	IImageLoader* IrrVideo_IVideoDriver_getImageLoader(IVideoDriver* driver, u32 n)
	{
		if (driver)
			return driver->getImageLoader(n);
		else return 0;
	}
	
	u32 IrrVideo_IVideoDriver_getImageWriterCount(IVideoDriver* driver)
	{
		if (driver)
			return driver->getImageWriterCount();
		else return 0;
	}
	
	// do not delete
	IImageWriter* IrrVideo_IVideoDriver_getImageWriter(IVideoDriver* driver, u32 n)
	{
		if (driver) 
			return driver->getImageWriter(n);
		else return 0;
	}

	void IrrVideo_IVideoDriver_draw2DImageBatch(IVideoDriver* driver, 
		const video::ITexture* texture,
		const core::position2d<s32>* pos, 
		rect<s32>** sourceRects_array, s32 sourceRects_size, 
		s32* indices_array, s32 indices_size, 
		s32 kerningWidth=0,
		const core::rect<s32>* clipRect=0,
		SColor* color=0,
		bool useAlphaChannelOfTexture=false)
	{
		if (driver) {
			array<recti> sourceRects;
			for (int i=0; i<sourceRects_size; i++) {	
				sourceRects.push_back(*sourceRects_array[i]);
			}
			
			array<s32> indices;
			for (int i=0; i<indices_size; i++) {	
				indices.push_back(indices_array[i]);
			}
						
			driver->draw2DImageBatch(texture, *pos, sourceRects, indices, kerningWidth, clipRect, (color ? *color: SColor(255,255,255,255)), useAlphaChannelOfTexture);
		}		
	}
	
	void IrrVideo_IVideoDriver_draw2DImageBatchAtPositions(IVideoDriver* driver,
		const video::ITexture* texture,
		position2d<s32>** pos_array, s32 pos_size, 
		rect<s32>** sourceRects_array, s32 sourceRects_size, 
		const core::rect<s32>* clipRect=0,
		SColor* color=0,
		bool useAlphaChannelOfTexture=false) 
	{
		if (driver) {
		
			array<position2di> pos;
			for (int i=0; i<pos_size; i++) {	
				pos.push_back(*pos_array[i]);
			}
			array<recti> sourceRects;
			for (int i=0; i<sourceRects_size; i++) {	
				sourceRects.push_back(*sourceRects_array[i]);
			}
		
			driver->draw2DImageBatch(texture, pos, sourceRects, clipRect, (color ? *color: SColor(255,255,255,255)), useAlphaChannelOfTexture);
		}		
	}

	SMaterial* IrrVideo_IVideoDriver_getMaterial2D(IVideoDriver* driver)
	{
		if (driver) {
			return &(driver->getMaterial2D());
		} else return 0;
	}
	
	void IrrVideo_IVideoDriver_enableMaterial2D(IVideoDriver* driver, bool enable = true) 
	{
		if (driver)
			driver->enableMaterial2D(enable);
	}
	
	// must delete
	dimension2di* IrrVideo_IVideoDriver_getMaxTextureSize(IVideoDriver* driver)
	{
		if (driver)
			return new dimension2di(driver->getMaxTextureSize());
		else return 0;
	}
	
	void IrrVideo_IVideoDriver_getFog(IVideoDriver* driver, SColor& color, E_FOG_TYPE& fogType, f32& start, f32& end, f32& density, bool& pixelFog, bool& rangeFog)
	{
		if (driver)
			driver->getFog(color, fogType, start, end, density, pixelFog, rangeFog);
	}
			
	//------------------------------------------------------------------------------------
	// struct SOverrideMaterial
	//------------------------------------------------------------------------------------

	void IrrVideo_SOverrideMaterial_setMaterial(SOverrideMaterial* mat, SMaterial* material)
	{
		if (mat)
			mat->Material = *material;
	}
	
	// do not delete
	SMaterial* IrrVideo_SOverrideMaterial_getMaterial(SOverrideMaterial* mat) 
	{
		if (mat)
			return &(mat->Material);
		else return 0;
	}

	u32 IrrVideo_SOverrideMaterial_getEnableFlags(SOverrideMaterial* mat)
	{
		if (mat)
			return mat->EnableFlags;
		else return 0;
	}
	
	void IrrVideo_SOverrideMaterial_setEnableFlags(SOverrideMaterial* mat, u32 enable_flags)
	{
		if (mat)
			mat->EnableFlags = enable_flags;
	}
	
	u16 IrrVideo_SOverrideMaterial_getEnablePasses(SOverrideMaterial* mat)
	{
		if (mat)
			return mat->EnablePasses;
		else return 0;
	}
	
	void IrrVideo_SOverrideMaterial_setEnablePasses(SOverrideMaterial* mat, u16 passes)
	{
		if (mat)
			mat->EnablePasses = passes;
	}
	
	bool IrrVideo_SOverrideMaterial_getEnabled(SOverrideMaterial* mat)
	{
		if (mat)
			return mat->Enabled;
		else return false;
	}
	
	void IrrVideo_SOverrideMaterial_setEnabled(SOverrideMaterial* mat, bool enabled)
	{
		if (mat)
			mat->Enabled = enabled;
	}

	//------------------------------------------------------------------------------------
	// struct IRenderTarget
	//------------------------------------------------------------------------------------

	IRenderTarget* IrrVideo_IRenderTarget_newFromTexture(
				ITexture* texture,
				E_COLOR_PLANE colorMask=ECP_ALL,
				E_BLEND_FACTOR blendFuncSrc=EBF_ONE,
				E_BLEND_FACTOR blendFuncDst=EBF_ONE_MINUS_SRC_ALPHA,
				bool blendEnable=false)
	{
		return new IRenderTarget(texture, colorMask, blendFuncSrc, blendFuncDst, blendEnable);
	}
	
	IRenderTarget* IrrVideo_IRenderTarget_newFromEnum(
				E_RENDER_TARGET target,
				E_COLOR_PLANE colorMask=ECP_ALL,
				E_BLEND_FACTOR blendFuncSrc=EBF_ONE,
				E_BLEND_FACTOR blendFuncDst=EBF_ONE_MINUS_SRC_ALPHA,
				bool blendEnable=false)
	{
		return new IRenderTarget(target, colorMask, blendFuncSrc, blendFuncDst, blendEnable);
	}
	
	void IrrVideo_IRenderTarget_del(IRenderTarget* del)
	{
		if (del)
			delete del;
			
		del=0;
	}
	
	ITexture* IrrVideo_IRenderTarget_getRenderTexture(IRenderTarget* target)
	{
		if (target)
			return target->RenderTexture;
		else return 0;
	}
	
	void IrrVideo_IRenderTarget_setRenderTexture(IRenderTarget* target, ITexture* texture)
	{
		if (target)
			target->RenderTexture = texture;
	}

	s32 IrrVideo_IRenderTarget_getTargetType(IRenderTarget* target) 
	{
		if (target)
			return target->TargetType;
		else return -1;
	}
	
	void IrrVideo_IRenderTarget_setTargetType(IRenderTarget* target, E_RENDER_TARGET TargetType)
	{
		if (target)
			target->TargetType = TargetType;
	}

	s32 IrrVideo_IRenderTarget_getColorMask(IRenderTarget* target) 
	{
		if (target)
			return target->ColorMask;
		else return -1;
	}
	
	void IrrVideo_IRenderTarget_setColorMask(IRenderTarget* target, E_COLOR_PLANE ColorMask)
	{
		if (target)
			target->ColorMask = ColorMask;
	}

	s32 IrrVideo_IRenderTarget_getBlendFuncSrc(IRenderTarget* target) 
	{
		if (target)
			return target->BlendFuncSrc;
		else return -1;
	}
	
	void IrrVideo_IRenderTarget_setBlendFuncSrc(IRenderTarget* target, E_BLEND_FACTOR BlendFuncSrc)
	{
		if (target)
			target->BlendFuncSrc = BlendFuncSrc;
	}

	s32 IrrVideo_IRenderTarget_getBlendFuncDst(IRenderTarget* target) 
	{
		if (target)
			return target->BlendFuncDst;
		else return -1;
	}
	
	void IrrVideo_IRenderTarget_setBlendFuncDst(IRenderTarget* target, E_BLEND_FACTOR BlendFuncDst)
	{
		if (target)
			target->BlendFuncDst = BlendFuncDst;
	}

	bool IrrVideo_IRenderTarget_getBlendEnable(IRenderTarget* target)
	{
		if (target)
			return target->BlendEnable;
		else return false;
	}
	
	void IrrVideo_IRenderTarget_setBlendEnable(IRenderTarget* target, bool BlendEnable)
	{
		if (target)
			target->BlendEnable = BlendEnable;
	}
	
}
