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


#ifndef	__NMITEM__
#define	__NMITEM__


		#include "physic/physic_item_desc.h"
		#include "physic/physic_item.h"
		#include "scene3d/mitem_event_interface.h"
		#include "scene3d/mitem_type.h"
		#include "core/ace.h"
		#include "core/item.h"
		#include "script/scripted_object.h"
		#include "automation/automation_player.h"
		#include "memory/nauto_ptr.h"


namespace GS {
	class Time;

	namespace Script { class VM; }

	namespace Core {
		class Item;
		struct Renderable;
	}

	namespace S3D {
		class Scene;
		class PhysicWorld;

/*!
	@short	Managed item.

	The scene graph base node class. It also provide a mean to key frame any
	base properties of derived entities such as colors, ranges, intensities, etc...

	@author Emmanuel Julien (ejulien@gsworks.fr)
*/
class	MItem : public ACE::Unit, public SharedObject
{
		friend class Scene;

public:

enum	Flag
{
	Flag_None				=	0,

	Flag_Billboard			=	(1 << 0),
	Flag_SolveOverlap		=	(1 << 1),
	Flag_Ghost				=	(1 << 2),
	Flag_Physic				=	(1 << 3),
	Flag_TriggerDetected	=	(1 << 4),

	Flag_IsActive			=	(1 << 5),
	Flag_IsStatic			=	(1 << 6),
	Flag_IsHelper			=	(1 << 7),

	// Non-serialized.
	Flag_EditorHidden		=	(1 << 8),
	Flag_EditorLocked		=	(1 << 9)
};

protected:

		MItemType		item_type;

		bool			initial_state_set;		///< Is item initial state set?
		Matrix4			initial_matrix;			///< Initial matrix.

		uint			uid;					///< Item scene unique identifier.
		float			priority;				///< Heuristic bias value.

/*!
	@name	General section.
	@{
*/
public:

		String			name;					///< Item name.

		BitField		mitem_flags;

		float			global_alpha;

		uint			GetUid() const { return uid; }
		MItemType		GetItemType() const { return item_type; }

virtual	Core::Item		*GetBaseItem() = 0;
virtual	Core::Renderable *GetRenderable() = 0;

		float			GetPriority() const { return priority; }
		void			SetPriority(float p = 0.5f) { priority = p; }

		/// Store the current transformation as the initial transformation.
		void			SetInitialTransformation();
		/// Reset to initial transformation.
		void			ResetToInitialTransformation();

		/// Return the active state of the item.
virtual	inline bool		isActive() const { return mitem_flags.IsSet(Flag_IsActive); }
		/// Return the static state of the item.
virtual	bool			isStatic() const { return mitem_flags.IsSet(Flag_IsStatic); }

virtual	void			Update(const Time &dt);
virtual	void			Setup(PhysicWorld *);
void					ForceUpdateMassShapePhysic(PhysicWorld *physic_world);
		void			Reset();
/// @}

		bool			ExecCommand(ACE::Command *, float dt);

		PhysicItemDesc	physic_item_desc;
		sPhysicItem		physic_item;

		AutoPtr <IItemEvent> item_event;
		AutoPtr <Script::ScriptedObject> scripted_object;
		AutoPtr <Automation::Player> automation_player;

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

		MItem();
virtual	~MItem() {}
};

typedef	SharedPtr <MItem> sMItem;

	} // S3D
} // GS


#endif // __NMITEM__
