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


#ifndef	__NOBJECT__
#define	__NOBJECT__


		#include "core/renderable.h"
		#include "core/skin.h"
		#include "core/item.h"


namespace GS {
	namespace Core {

/*!
	@short	Object class.

	This class simply links a geometry with an item and provide some wrapper
	functions to render them.

	@author Emmanuel Julien (ejulien@gsworks.fr)
*/
class	Object : public Item, public Renderable
{
protected:

		AutoPtr <Skin> skin;

public:

struct	RenderData
{	Render::sGeometry geometry;	};

static	float			lod_bias;

/*!
	@name	Renderable interface.
	@{
*/
		/// Compute the renderable minmax.
virtual	void			ComputeRenderableMinMax(MinMax &);
		/// Get the renderable primitive list for this renderable.
virtual	uint			GetRenderablePrimitiveList(const Camera &view, const Camera &default_view, Stack <Render::Primitive *> &, Renderable::Context = Renderable::Context_Default, bool cull = true);

		/// Setup item render data.
virtual	void			RenderSetup(ResourceFactories * = 0);
/// @}

		bool			cache_geometry;			///< Whether the object should reuse cached geometry or create new instances.

		/// Compute object world axis-aligned bounding box.
		void			ComputeLocalMinMax(MinMax &) const;

		/// Return the object skin.
		Skin			*GetSkin() const { return skin; }

		/// Return the binding bone matrix.
		bool			GetBindMatrix(uint, Matrix4 &) const;
		/// Update skin matrices.
		void			UpdateSkin();

		/// Has skin.
inline	bool			HasSkin() const
		{	return skin.IsValid() && skin->bones.GetCount();	}

inline	uint			GetBoneCount() const
		{	return skin.IsValid() ? skin->bones.GetCount() : 0;	}
inline	Item			*GetBone(uint n) const
		{	return skin.IsValid() ? skin->bones[n] : 0;	}

		/// Allocate skin binding structures.
virtual	bool			AllocateSkin(uint bone_count);
		/// Free skin binding structures.
virtual	void			FreeSkin();
		/*!
			@short	Bind a bone to this item's skin.

			@note	You can specify the binding matrix for this bone. If you do
					not the current bone item matrix will be used.
		*/
virtual	bool			BindBone(uint n, Item *bone);

		String			geometry;
		AutoPtr <RenderData> render_data;

		bool			FromMetaTag(NML::Tag &);
		NML::Tag		*AsMetaTag() const;

		Object();
};

	} // Core
} // GS


#endif	// __NOBJECT__
