///////////////////////////////////////////////////////////////////////////////
/// @file de2D.hpp
///
/// @brief 2D Overlays and other 2D drawing
///
/// @author Assassin
///
/// This file is the intellectual property of Novus Delta, LLC.. Usage of the
/// contents of this file is subject to the Destiny3D Member License which
/// can be found at http://www.destiny3d.com.  Any other usage is prohibited.
///
/// This file is distributed "AS IS" without warranty of any kind.  Novus
/// Delta, LLC. does not guarantee the fitness of the contents of this file
/// for any particular purpose.
///
/// Copyright (C) 2001-2003 Novus Delta, LLC. All Rights Reserved.
///
/// <hr>
///                                 Change History
/// <hr>
///
/// @date Mar 2002
/// @author Assassin
/// @remarks Creation
///
/// @date May 2002
/// @author Assassin
/// @remarks Interface implementation
///
///////////////////////////////////////////////////////////////////////////////

#ifndef DE2D_HPP
#define DE2D_HPP

#include "deGlobalTypes.hpp"
#include "deRender.hpp"
#include "deMath.hpp"

#if defined(DE2D_DLL_EXPORTS) || defined(DESTINY3D_EXPORT_ALL)
#	define DE2D_API extern "C" DEDLL_EXPORT
#elif defined(DESTINY3D_STATIC_LINK)
#	define DE2D_API extern "C"
#else
#	define DE2D_API extern "C" DEDLL_IMPORT
#endif

#ifdef USING_DESTINY3D
#ifdef _DEBUG
#	ifdef DESTINY3D_STATIC_LINK
#		pragma comment(lib, "de2D_sd")
#	else
#		pragma comment(lib, "de2Dd")
#	endif //DESTINY3D_STATIC_LINK
#else
#	ifdef DESTINY3D_STATIC_LINK
#		pragma comment(lib, "de2D_s")
#	else
#		pragma comment(lib, "de2D")
#	endif //DESTINY3D_STATIC_LINK
#endif //_DEBUG
#endif //USING_DESTINY3D

class Ide2DObject;
class Ide2DCollection;
class IdeRenderTexture;
class IdeVertexBuffer;
class IdeCamera;
class IdeDriver;

// factory functions
/// create an instance of Ide2DCollection
DE2D_API Ide2DCollection* Ide2DObject_Create2DCollection();
/// create an instance of Ide2DObject using a vertex buffer
DE2D_API Ide2DObject* Ide2DObject_Create2DObject(	IdeVertexBuffer * VBuffer, 
							IdeRenderTexture * Texture, deFloat Depth = 10.0f, 
							deBoolean ExpireNow = deFALSE);
/// create an instance of Ide2DObject using a rectangle to form an overlay
DE2D_API Ide2DObject* Ide2DObject_Create2DOverlay(	deRect *ScreenRect, 
							deFloatRect *TexCoords, IdeRenderTexture * Texture, 
							deFloat Depth = 10.0f, deARGB color = 0xFFFFFFFF, 
							deDouble FadePerSecond = 0.0);
/// create an instance of Ide2DObject to act as a corona
DE2D_API Ide2DObject* Ide2DObject_Create2DCorona(	deRect *SizeRect, 
							deFloatRect *TexCoords, IdeRenderTexture * Texture, 
							IdeCamera * ScreenCamera, deFloat Depth = 10.0f, 
							deARGB color = 0xFFFFFFFF);
/// create an instance of Ide2DObject using a line segment
DE2D_API Ide2DObject* Ide2DObject_Create2DLine(	deVec3d Start, deVec3d End, 
							deARGB color = 0xFFFFFFFF, deDouble FadePerSecond = 0.0, 
							deFloat Depth = 10.0f);
/// create an instance of Ide2DObject using several line segments
DE2D_API Ide2DObject* Ide2DObject_Create2DLineList(	deVec3d PointList[], 
							long NumPoints, deARGB color = 0xFFFFFFFF,
							deDouble FadePerSecond = 0.0, deFloat Depth = 10.0f);
/// create an instance of Ide2DObject using a rectangle to form lines
DE2D_API Ide2DObject* Ide2DObject_Create2DLineRect(	deRect & LineRect, 
							deARGB color = 0xFFFFFFFF, deDouble FadePerSecond = 0.0, 
							deFloat Depth = 10.0f);

/// base class for handling objects rendered in 2D.
/// Related functions: Ide2DObject_Create2DObject, Ide2DObject_Create2DOverlay, Ide2DObject_Create2DCorona
/// Ide2DObject_Create2DLine, Ide2DObject_Create2DLineList, Ide2DObject_Create2DLineRect.
/// Related classes: Ide2DCollection.
//class Ide2DObject : virtual public IdeRefCountBase
DE3D_INTERFACE(Ide2DObject, IdeRefCountBase)
{
protected:
	// cannot instantiate this class on stack or with new
	virtual ~Ide2DObject() {}
public:
	/// Get the internal vertex buffer for this object
	virtual IdeVertexBuffer * GetVBuffer() const = 0;
	/// Get the texture-state used to render this object
	virtual IdeRenderTexture* GetTexture() const = 0;
	// used internally
	virtual deBoolean HasExpired() const = 0;
	/// Get the depth value used for sorting this object into the render order.
	/// Note that the depth value is only relative to other objects and collections inside the same collection.
	virtual deFloat GetDepth() const = 0;

	/// Cause this object to be deleted after it is next rendered
	virtual void MakeExpire() = 0;
	/// Set the depth value used for sorting this object into the render order.
	/// Note that the depth value is only relative to other objects and collections inside the same collection.
	/// Calling this method on an object already in a collection will not change its rendering order.
	/// Instead, call Ide2DCollection::AdjustObjectDepth which will invoke this method on the 2d object.
	virtual deBoolean SetDepth(deFloat Depth) = 0;

	/// Manually transform the position values in the internal vertex buffer, to move the object.
	virtual deBoolean Move(deVertex DeltaXY) = 0;
	virtual deBoolean Update(deDouble DeltaTime) = 0;
};

/// Used to collect 2D objects together and render them to the screen.
/// Related functions: Ide2DObject_Create2DCollection.
/// Related classes: Ide2DObject.
//class Ide2DCollection : virtual public IdeRefCountBase
DE3D_INTERFACE(Ide2DCollection, IdeRefCountBase)
{
protected:
	// cannot instantiate this class on stack or with new
	virtual ~Ide2DCollection() {}
	virtual void SetParent(Ide2DCollection* ParentCollection) = 0;
public:
	/// Get the rect used for clipping objects
	virtual const deRect&	GetRect() const = 0;
	/// Set the rect used for clipping objects
	virtual void		SetRect(deRect &rect) = 0;

	/// Set the background color for this collection. You may specify alpha (0xff = opaque).
	virtual void		SetBGColor(deARGB color) = 0;
	/// Get the background color for this collection
	virtual deARGB		GetBGColor() = 0;

	/// Enable or disable a collection from rendering.
	/// Can be used in windowing systems to "minimize" the collection.
	virtual void		SetEnabled(deBoolean Enable) = 0;
	/// Get the rendering-enabled status of the collection
	virtual deBoolean	IsEnabled() const = 0;

	/// Get the X & Y scroll offsets currently being used for this collection
	virtual void		GetScrollValue(deVec3d & scroll) const = 0;
	/// Set the X & Y scroll offsets for this collection
	virtual void		SetScrollValue(const deVec3d & scroll) = 0;

	/// Add a 2D object to this collection, so it may be rendered.
	/// This method invokes object->Claim() to increment the object's reference count.
	virtual deBoolean	AddObject(Ide2DObject * object) = 0;
	/// Remove a 2D object from this collection.
	/// This method invokes object->Release() to decrement the object's reference count, 
	/// possibly causing destruction.
	virtual deBoolean	RemoveObject(Ide2DObject * object) = 0;
	/// Adjust the depth value of a 2D object.
	/// This method invokes object->SetDepth(Depth).
	virtual deBoolean	AdjustObjectDepth(Ide2DObject * object, deFloat Depth) = 0;

	/// Add a subordinate 2D collection to this one, so that its contents be rendered
	/// inside the extents of this one.
	/// This method invokes collection->Claim().
	virtual deBoolean	AddSubCollection(Ide2DCollection * collection) = 0;
	/// Remove a subordinate 2D collection.
	/// This method invokes collection->Release().
	virtual deBoolean	RemoveSubCollection(Ide2DCollection * collection) = 0;
	/// Get the depth value used for sorting this collection into the render order.
	/// Note that the depth value is only relative to other objects and collections inside the same collection.
	virtual deFloat		GetDepth() const = 0;
	/// Set the depth value used for sorting this collection into the render order.
	/// Note that the depth value is only relative to other objects and collections inside the same collection.
	/// This method, unlike Ide2DObject::SetDepth, will adjust the rendering order of this collection.
	virtual deBoolean	SetDepth(deFloat Depth) = 0;

	/// Render all the objects and sub-collections contained by this collection.
	/// It is recommended that a user not call this explicitly, instead letting IdeRender handle this task.
	/// IdeRender::EndFrame invokes Ide2DCollection::Render for its attached 2d collection.
	virtual deBoolean	Render(	IdeDriver * Driver, deDouble DeltaTime, 
								IdeRenderTexture *NullTex, IdeRender::deRenderStats * RenderStats,
								deBoolean DoOcclusion = deFALSE) = 0;

	/// Destroy all the objects, and optionally all the sub-collections, contained by this collection.
	/// All destroyed sub-collections will also destroy their own sub-collections.
	virtual void		DestroyAllObjects(deBoolean SubCollectionsAlso = deTRUE) = 0;
};

#endif

