/* -----------------------------------------------------------------------------
	GSFramework
	Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */


#ifndef	__NRENDERDATA__
#define	__NRENDERDATA__


		#include "core/material.h"
		#include "core/texture_parm.h"
		#include "geometry/bounding_box.h"
		#include "memory/bit_field.h"


namespace GS {
	class Picture;

	namespace Core {
		class Geometry;
		struct Material;
		struct Shader;
	}

	namespace Render {
		class Renderer;
		struct ResourceFactory;

//------------------------------------------------------------------------------
struct	Material;
typedef	SharedPtr <Material> sMaterial;
struct	Geometry;
typedef	SharedPtr <Geometry> sGeometry;
struct	Texture;
typedef	SharedPtr <Texture> sTexture;
struct	Shader;
typedef	SharedPtr <Shader> sShader;
//------------------------------------------------------------------------------

/*!
	@short	The renderer base data container.

	This is the base structure holding all of a renderer's specific data for
	an entity to be setup. This structure is to be derived for each functional
	renderer implementation.

	@see	nRenderGeometry, nRenderMaterial, nRenderTexture, nLight.
*/
struct	Data : public SharedObject
{
		NPLACEMENT_NEW(Renderer)

		String		name;

		/// Load from cooked resource.
virtual	bool		LoadCooked(const char *uri)
		{	return false;	}
virtual	bool		ShouldReloadOnDependencyChange(const char *n) const
		{	return name == n;	}

		Data(const char *_name = 0) : name(_name) {}
};

//------------------------------------------------------------------------------
struct	Geometry : public Data
{
		Array <sMaterial> material_table;

		BitField	flag;
		Vector4		hotspot;

		MinMax		minmax;

		/// Change a material in the material table.
virtual	bool		SetMaterial(uint nUnused(index), Material *) { return false; }

		/// Create from geometry.
virtual	bool		Create(ResourceFactory &, const Core::Geometry &) = 0;

		sGeometry	lod_proxy;
		float		lod_distance;

		sGeometry shadow_proxy;

		Array <Matrix4> bone_bind_matrix;
		Array <MinMax> bone_minmax;

		Geometry(const char *_name = 0) : Data(_name) {}
};
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
struct	MaterialShader : public Data
{
virtual	bool		SetUserUniformValue(const char *name, const Vector4 &) = 0;
virtual	bool		SetUserUniformValue(const char *name, Texture *) = 0;
};
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
struct	Material : public Core::BasicMaterial, public Data
{
		sTexture	 texture_table[Core::Material::max_texture_stage];

		/// Get the material shader.
virtual	MaterialShader *GetShader() const { return 0; }

		/// Create from material.
virtual	bool		Create(ResourceFactory &, const Core::Material &) = 0;

		/// Clone this material (create an independent copy).
virtual	Material	*Clone() const { return NULL; }

		Material(const char *_name = 0) : Data(_name) {}
};
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
struct	Texture : public Data
{
enum	Format
{
		FormatRGBA8			=	0,
		FormatBGRA8,
		FormatRGBA16,
		FormatRGBAF,
		FormatDepth,
		FormatDepthF,
		FormatDepthOculus,

		FormatInvalid
};
enum	AA
{
		NoAA			=	0,

		MSAA2x,
		MSAA4x,
		MSAA8x,
		MSAA16x,

		AALast
};
enum	Usage
{
		IsRenderTarget		=	(1 << 0),	///< used as a render-target
		IsShaderResource	=	(1 << 1),	///< used as a shader resource

		UsageDefault		=	IsShaderResource
};

		TextureParm	parm;

		Format		format;
		AA			aa;

		bool		is_rtt;

		/// Configure texture as a shadow map.
virtual	void		ConfigureAsShadowMap() = 0;

		bool		Create(const Picture &, Usage = UsageDefault);

		/// Create from raw picture data.
virtual	bool		Create(const char *data, int width, int height, Format = FormatRGBA8, AA = NoAA, Usage = UsageDefault) = 0;
virtual	void		Free() = 0;

virtual	uint		GetWidth() const = 0;
virtual	uint		GetHeight() const = 0;

		/// Blit CPU data to texture.
virtual	void		Blit(const char *data, uint w, uint h, uint x = 0, uint y = 0, Format = Texture::FormatRGBA8) = 0;
		/// Resize texture, does not preserve content.
virtual	void		Resize(uint w, uint h) = 0;

virtual	void		SetAnisotropy(TextureParm::Anisotropy) = 0;
virtual	void		SetFiltering(TextureParm::Filtering) = 0;
virtual	void		SetWrapping(TextureParm::Wrap u, TextureParm::Wrap v) = 0;

		Texture(const char *_name = 0) : Data(_name)
		{
			format = FormatInvalid;
			aa = NoAA;

			is_rtt = false;
		}
};
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
struct	Shader : public Data
{
		/// Create from shader.
virtual	bool		Create(ResourceFactory &, const Core::Shader &) = 0;

		Shader(const char *_name = 0) : Data(_name) {}
};
//------------------------------------------------------------------------------

	} // Render
} // GS


#endif	// __NRENDERDATA__
