//
// EnginePlugin
//
// This example plugin demostrates loading proprietary file format,
// how to use the file duration methods, and how to set the value
// of a parameter when another parameter changes.
//

#ifndef __ENGINEPLUGIN_H__
#define __ENGINEPLUGIN_H__


#include "DemopajaVersion.h"
#include "PajaTypes.h"
#include "EffectI.h"
#include "EditableI.h"
#include "UndoC.h"
#include "ParamI.h"
#include "ImportableImageI.h"
#include "BBox2C.h"
#include "Matrix2C.h"
#include "DeviceContextC.h"
#include "DeviceInterfaceI.h"
#include "DemoInterfaceC.h"
#include "OpenGLViewportC.h"
#include "OpenGlDeviceC.h"
#include "TimeContextC.h"
#include "AutoGizmoC.h"

#include "ScenegraphItemI.h"
#include "MeshC.h"
#include "LightC.h"
#include "CameraC.h"
#include "BoneC.h"
#include "ShapeC.h"
#include "MaterialC.h"
#include "ParticleSystemC.h"
#include "WSMObjectC.h"

#include "PBufferC.h"

//////////////////////////////////////////////////////////////////////////
//
//  Class IDs
//  Remember to make new ones if you this file as template!
//

const PluginClass::ClassIdC	CLASS_ASE_IMPORT( 0, 207 );
const PluginClass::ClassIdC	CLASS_ASEPLAYER_EFFECT( 0, 107 );
const PluginClass::ClassIdC	CLASS_FLARE_EFFECT( 0xABA335D9, 0x73C54B6C );

//////////////////////////////////////////////////////////////////////////
//
//  MAS importer class descriptor.
//

class MASImportDescC : public PluginClass::ClassDescC
{
public:
	MASImportDescC();
	virtual ~MASImportDescC();
	virtual void*						create();
	virtual PajaTypes::int32			get_classtype() const;
	virtual PluginClass::SuperClassIdC	get_super_class_id() const;
	virtual PluginClass::ClassIdC		get_class_id() const;
	virtual const char*					get_name() const;
	virtual const char*					get_desc() const;
	virtual const char*					get_author_name() const;
	virtual const char*					get_copyright_message() const;
	virtual const char*					get_url() const;
	virtual const char*					get_help_filename() const;
	virtual PajaTypes::uint32			get_required_device_driver_count() const;
	virtual const PluginClass::ClassIdC&	get_required_device_driver( PajaTypes::uint32 ui32Idx );
	virtual PajaTypes::uint32			get_ext_count() const;
	virtual const char*					get_ext( PajaTypes::uint32 ui32Index ) const;
};


//////////////////////////////////////////////////////////////////////////
//
//  ASE player effect class descriptor.
//

class EngineDescC : public PluginClass::ClassDescC
{
public:
	EngineDescC();
	virtual ~EngineDescC();
	virtual void*						create();
	virtual PajaTypes::int32			get_classtype() const;
	virtual PluginClass::SuperClassIdC	get_super_class_id() const;
	virtual PluginClass::ClassIdC		get_class_id() const;
	virtual const char*					get_name() const;
	virtual const char*					get_desc() const;
	virtual const char*					get_author_name() const;
	virtual const char*					get_copyright_message() const;
	virtual const char*					get_url() const;
	virtual const char*					get_help_filename() const;
	virtual PajaTypes::uint32			get_required_device_driver_count() const;
	virtual const PluginClass::ClassIdC&	get_required_device_driver( PajaTypes::uint32 ui32Idx );
	virtual PajaTypes::uint32			get_ext_count() const;
	virtual const char*					get_ext( PajaTypes::uint32 ui32Index ) const;
};


//////////////////////////////////////////////////////////////////////////
//
//  Flare effect class descriptor.
//

class FlareDescC : public PluginClass::ClassDescC
{
public:
	FlareDescC();
	virtual ~FlareDescC();
	virtual void*						create();
	virtual PajaTypes::int32			get_classtype() const;
	virtual PluginClass::SuperClassIdC	get_super_class_id() const;
	virtual PluginClass::ClassIdC		get_class_id() const;
	virtual const char*					get_name() const;
	virtual const char*					get_desc() const;
	virtual const char*					get_author_name() const;
	virtual const char*					get_copyright_message() const;
	virtual const char*					get_url() const;
	virtual const char*					get_help_filename() const;
	virtual PajaTypes::uint32			get_required_device_driver_count() const;
	virtual const PluginClass::ClassIdC&	get_required_device_driver( PajaTypes::uint32 ui32Idx );
	virtual PajaTypes::uint32			get_ext_count() const;
	virtual const char*					get_ext( PajaTypes::uint32 ui32Index ) const;
};


namespace MASPlugin {


//////////////////////////////////////////////////////////////////////////
//
// ASE Importer class.
//

class MASImportC : public Import::ImportableI
{
public:
	static MASImportC*				create_new();
	virtual Edit::DataBlockI*		create();
	virtual Edit::DataBlockI*		create( Edit::EditableI* pOriginal );
	virtual void					copy( Edit::EditableI* pEditable );
	virtual void					restore( Edit::EditableI* pEditable );

	virtual const char*				get_filename();
	virtual void					set_filename( const char* szName );
	virtual bool					load_file( const char* szName, PajaSystem::DemoInterfaceC* pInterface );
	virtual void					initialize( PajaTypes::uint32 ui32Reason, PajaSystem::DemoInterfaceC* pInterface );


	virtual PluginClass::ClassIdC	get_class_id();
	virtual	PluginClass::SuperClassIdC	get_super_class_id();
	virtual const char*				get_class_name();

	virtual const char*				get_info();
	virtual PluginClass::ClassIdC	get_default_effect();

	virtual void					eval_state( PajaTypes::int32 i32Time );

	virtual PajaTypes::int32		get_current_frame() const;

	virtual PajaTypes::int32		get_duration();
	virtual PajaTypes::float32		get_start_label();
	virtual PajaTypes::float32		get_end_label();

	virtual PajaTypes::uint32		get_reference_file_count();
	virtual Import::FileHandleC*	get_reference_file( PajaTypes::uint32 ui32Index );


	virtual PajaTypes::uint32		get_scenegraphitem_count();
	virtual ScenegraphItemI*		get_scenegraphitem( PajaTypes::uint32 ui32Index );

	virtual PajaTypes::uint32		get_camera_count();
	virtual CameraC*				get_camera( PajaTypes::uint32 ui32Index );

	virtual PajaTypes::uint32		get_light_count();
	virtual LightC*					get_light( PajaTypes::uint32 ui32Index );

	virtual void					get_time_parameters( PajaTypes::int32& i32FPS, PajaTypes::int32& i32TicksPerFrame, PajaTypes::int32& i32FirstFrame, PajaTypes::int32& i32LastFrame );


	virtual PajaTypes::uint32		save( FileIO::SaveC* pSave );
	virtual PajaTypes::uint32		load( FileIO::LoadC* pLoad );

protected:
	MASImportC();
	MASImportC( Edit::EditableI* pOriginal );
	virtual ~MASImportC();

private:

//	ScenegraphItemI*				find_object( const std::string& sName );
//	BoneC*							find_bone( PajaTypes::uint32 ui32Id );
	void							count_file_references();

	std::string							m_sFileName;
	bool								m_bFileRefsValid;
	std::vector<Import::FileHandleC*>	m_rFileRefs;

	std::vector<ScenegraphItemI*>		m_rScenegraph;
	std::vector<CameraC*>				m_rCameras;
	std::vector<LightC*>				m_rLights;
	PajaTypes::int32					m_i32FPS;
	PajaTypes::int32					m_i32TicksPerFrame;
	PajaTypes::int32					m_i32FirstFrame;
	PajaTypes::int32					m_i32LastFrame;
	PajaTypes::int32					m_i32CurrentFrame;

};




struct RenderContextS {
	PajaTypes::int32				m_i32Time;
	PajaSystem::DeviceContextC*		m_pContext;
	PajaSystem::TimeContextC*		m_pTimeContext;
	PajaSystem::OpenGLViewportC*	m_pInterface;
	PajaSystem::OpenGLDeviceC*		m_pDevice;
};



//////////////////////////////////////////////////////////////////////////
//
// The 3D engine effect class.
//

class EngineEffectC : public Composition::EffectI
{
public:
	static EngineEffectC*			create_new();
	virtual Edit::DataBlockI*		create();
	virtual Edit::DataBlockI*		create( Edit::EditableI* pOriginal );
	virtual void					copy( Edit::EditableI* pEditable );
	virtual void					restore( Edit::EditableI* pEditable );

	virtual PajaTypes::int32		get_gizmo_count();
	virtual Composition::GizmoI*	get_gizmo( PajaTypes::int32 i32Index );

	virtual PluginClass::ClassIdC	get_class_id();
	virtual const char*				get_class_name();

	virtual void					set_default_file( PajaTypes::int32 i32Time, Import::FileHandleC* pHandle );
	virtual Composition::ParamI*	get_default_param( PajaTypes::int32 i32Param );

	virtual PajaTypes::uint32		update_notify( Edit::EditableI* pCaller );

	virtual void					initialize( PajaTypes::uint32 ui32Reason, PajaSystem::DemoInterfaceC* pInterface );

	virtual void					eval_state( PajaTypes::int32 i32Time );
	virtual PajaTypes::BBox2C		get_bbox();

	virtual const PajaTypes::Matrix2C&	get_transform_matrix() const;

	virtual bool					hit_test( const PajaTypes::Vector2C& rPoint );

	virtual PajaTypes::uint32		save( FileIO::SaveC* pSave );
	virtual PajaTypes::uint32		load( FileIO::LoadC* pLoad );


protected:
	EngineEffectC();
	EngineEffectC( Edit::EditableI* pOriginal );
	virtual ~EngineEffectC();

private:


	enum TransformGizmoParamsE {
		ID_TRANSFORM_POS = 0,
		ID_TRANSFORM_SCALE,
		TRANSFORM_COUNT,
	};

	enum AttributeGizmoParamsE {
		ID_ATTRIBUTE_SIZE = 0,
		ID_ATTRIBUTE_CAMERA,
		ID_ATTRIBUTE_CLEAR,
		ID_ATTRIBUTE_CLEARCOLOR,
		ID_ATTRIBUTE_FILE,
		ATTRIBUTE_COUNT,
	};

	enum TimeGizmoParamsE {
		ID_TIME_FPS = 0,
		ID_TIME_FRAME,
		TIME_COUNT,
	};

	enum ToonGizmoParamsE {
		ID_TOON_WIRE_OUTERSIZE = 0,
		ID_TOON_WIRE_INNERSIZE,
		ID_TOON_WIRE_COLOR,
		TOON_COUNT,
	};

	enum FogGizmoParamsE {
		ID_FOG_MODE = 0,
		ID_FOG_START,
		ID_FOG_END,
		ID_FOG_DENSITY,
	};

	enum DOFGizmoParamsE {
		ID_DOF_MODE = 0,
		ID_DOF_START,
		ID_DOF_END
	};

	enum LineGizmoParamsE {
		ID_LINE_WIDTH = 0,
		ID_LINE_SMOOTH,
	};

	enum FogModeE {
		FOG_MODE_OFF,
		FOG_MODE_LINEAR,
		FOG_MODE_EXP,
		FOG_MODE_EXP2,
	};

	enum ImageEffectGizmosE {
		ID_GIZMO_TRANS = 0,
		ID_GIZMO_ATTRIB,
		ID_GIZMO_TIME,
		ID_GIZMO_TOON,
		ID_GIZMO_FOG,
		ID_GIZMO_LINE,
		ID_GIZMO_DOF,
		GIZMO_COUNT,
	};


	void							render_wsm_object( RenderContextS* pContext, WSMObjectC* pObj, const PajaTypes::Matrix3C& rCamTM, PajaTypes::Vector3C* pPlanes );
	void							render_bone( RenderContextS* pContext, BoneC* pBone );

	bool							render_mesh( RenderContextS* pContext, MeshC* pMesh, const PajaTypes::Matrix3C& rCamTM, PajaTypes::Vector3C* pPlanes );
	bool							render_mesh_index( RenderContextS* pContext, MeshC* pMesh, const PajaTypes::Matrix3C& rCamTM, PajaTypes::Vector3C* pPlanes );
	void							render_mesh_spot( RenderContextS* pContext, MeshC* pMesh, const PajaTypes::Matrix3C& rCamTM, PajaTypes::Vector3C* pPlanes );
	void							render_mesh_dof( RenderContextS* pContext, MeshC* pMesh, const PajaTypes::Matrix3C& rCamTM, PajaTypes::Vector3C* pPlanes );

	void							render_particlesystem( RenderContextS* pContext, ParticleSystemC* pPSys, const PajaTypes::Matrix3C& rCamTM, PajaTypes::Vector3C* pPlanes );
	void							render_particlesystem_index( RenderContextS* pContext, ParticleSystemC* pPSys, const PajaTypes::Matrix3C& rCamTM, PajaTypes::Vector3C* pPlanes );

	bool							render_shape( RenderContextS* pContext, ShapeC* pShape, const PajaTypes::Matrix3C& rCamTM, PajaTypes::Vector3C* pPlanes, bool bProjTex = false );
	bool							render_shape_index( RenderContextS* pContext, ShapeC* pShape, const PajaTypes::Matrix3C& rCamTM, PajaTypes::Vector3C* pPlanes, bool bProjTex = false );
	void							render_shape_spot( RenderContextS* pContext, ShapeC* pShape, const PajaTypes::Matrix3C& rCamTM, PajaTypes::Vector3C* pPlanes, bool bProjTex = false );

	void							init_pbuffer();
	void							release_pbuffer();

	void							calc_frustum_planes( PajaTypes::float32 f32FOV, PajaTypes::float32 f32Aspect, PajaTypes::Vector3C* pPlanes );

	struct CGItemSortS {
		bool				m_bLightVisible;
		bool				m_bCamVisible;
		PajaTypes::Vector3C	m_rPos;
		ScenegraphItemI*	m_pItem;

		bool	operator<( const CGItemSortS& rOther ) const
		{
			if( m_rPos[2] < rOther.m_rPos[2] )
				return true;
			return false;
		}
	};

	Composition::AutoGizmoC*	m_pTraGizmo;
	Composition::AutoGizmoC*	m_pAttGizmo;
	Composition::AutoGizmoC*	m_pTimeGizmo;
	Composition::AutoGizmoC*	m_pToonGizmo;
	Composition::AutoGizmoC*	m_pFogGizmo;
	Composition::AutoGizmoC*	m_pLineGizmo;
	Composition::AutoGizmoC*	m_pDOFGizmo;

//	PajaTypes::int32			m_i32Frame;
/*	PajaTypes::float32			m_f32Aspect;
	PajaTypes::ColorC			m_rClearColor;
	PajaTypes::int32			m_i32ClearFlags;
	CameraC*					m_pCam;
	PajaTypes::float32			m_f32OuterWireSize;
	PajaTypes::float32			m_f32InnerWireSize;
	PajaTypes::ColorC			m_rWireColor;
	PajaTypes::Vector2C			m_rSize;

	PajaTypes::int32			m_i32FogMode;
	PajaTypes::float32			m_f32FogStart;
	PajaTypes::float32			m_f32FogEnd;
	PajaTypes::float32			m_f32FogDensity;

	PajaTypes::int32			m_i32LineSmooth;
	PajaTypes::float32			m_f32LineWidth;*/

	PajaTypes::float32			m_f32OuterWireSize;
	PajaTypes::float32			m_f32InnerWireSize;
	PajaTypes::ColorC			m_rWireColor;
	PajaTypes::int32			m_i32LineSmooth;
	PajaTypes::float32			m_f32LineWidth;

	PajaTypes::Matrix2C			m_rTM;
	PajaTypes::BBox2C			m_rBBox;

	bool											m_bPBufferRef;
	static PajaTypes::uint32	m_ui32RampTexId;
	static PBufferC*					m_pPBuffer;
	static PajaTypes::int32		m_i32PBufferRefCount;
};



//////////////////////////////////////////////////////////////////////////
//
// The flare effect class.
//

class FlareEffectC : public Composition::EffectI
{
public:
	static FlareEffectC*			create_new();
	virtual Edit::DataBlockI*		create();
	virtual Edit::DataBlockI*		create( Edit::EditableI* pOriginal );
	virtual void					copy( Edit::EditableI* pEditable );
	virtual void					restore( Edit::EditableI* pEditable );

	virtual PajaTypes::int32		get_gizmo_count();
	virtual Composition::GizmoI*	get_gizmo( PajaTypes::int32 i32Index );

	virtual PluginClass::ClassIdC	get_class_id();
	virtual const char*				get_class_name();

	virtual void					set_default_file( PajaTypes::int32 i32Time, Import::FileHandleC* pHandle );
	virtual Composition::ParamI*	get_default_param( PajaTypes::int32 i32Param );

	virtual PajaTypes::uint32		update_notify( Edit::EditableI* pCaller );

	virtual void					initialize( PajaTypes::uint32 ui32Reason, PajaSystem::DemoInterfaceC* pInterface );

	virtual void					eval_state( PajaTypes::int32 i32Time );
	virtual PajaTypes::BBox2C		get_bbox();

	virtual const PajaTypes::Matrix2C&	get_transform_matrix() const;

	virtual bool					hit_test( const PajaTypes::Vector2C& rPoint );

	virtual PajaTypes::uint32		save( FileIO::SaveC* pSave );
	virtual PajaTypes::uint32		load( FileIO::LoadC* pLoad );


protected:
	FlareEffectC();
	FlareEffectC( Edit::EditableI* pOriginal );
	virtual ~FlareEffectC();

private:

	enum TransformGizmoParamsE {
		ID_TRANSFORM_POS = 0,
		ID_TRANSFORM_SCALE,
		TRANSFORM_COUNT,
	};

	enum AttributeGizmoParamsE {
		ID_ATTRIBUTE_SIZE = 0,
		ID_ATTRIBUTE_CAMERA,
		ID_ATTRIBUTE_CLEAR,
		ID_ATTRIBUTE_CLEARCOLOR,
		ID_ATTRIBUTE_FILE,
		ATTRIBUTE_COUNT,
	};

	enum FlareGizmoParamsE {
		ID_FLARE_COLOR = 0,
		ID_FLARE_USE_LIGHTING,
		ID_FLARE_RENDER_MODE,
		ID_FLARE_EXTRUDE,
		ID_FLARE_SIZE,
		ID_FLARE_IMAGE,
	};

	enum TimeGizmoParamsE {
		ID_TIME_FPS = 0,
		ID_TIME_FRAME,
		TIME_COUNT,
	};

	enum FlareEffectGizmosE {
		ID_GIZMO_TRANS = 0,
		ID_GIZMO_ATTRIB,
		ID_GIZMO_FLARE,
		ID_GIZMO_TIME,
		GIZMO_COUNT,
	};

	enum LightingE {
		LIGHTING_OFF = 0,
		LIGHTING_ON,
	};

	enum RenderModeE {
		RENDERMODE_NORMAL = 0,
		RENDERMODE_ADD = 1,
		RENDERMODE_MULT = 2,
	};

	void							render_mesh( RenderContextS* pContext, MeshC* pMesh, const PajaTypes::Matrix3C& rCamTM, PajaTypes::Vector3C* pPlanes );
	void							render_mesh_sorted( RenderContextS* pContext, MeshC* pMesh, const PajaTypes::Matrix3C& rCamTM, PajaTypes::Vector3C* pPlanes );
	void							render_shape( RenderContextS* pContext, ShapeC* pMesh, const PajaTypes::Matrix3C& rCamTM, PajaTypes::Vector3C* pPlanes );
	void							render_shape_sorted( RenderContextS* pContext, ShapeC* pMesh, const PajaTypes::Matrix3C& rCamTM, PajaTypes::Vector3C* pPlanes );

	struct CGItemSortS {
		PajaTypes::Vector3C	m_rPos;
		ScenegraphItemI*	m_pItem;

		bool	operator<( const CGItemSortS& rOther ) const
		{
			if( m_rPos[2] < rOther.m_rPos[2] )
				return true;
			return false;
		}
	};

	struct FlareSortS {
		PajaTypes::int32				m_i32Depth;
		PajaTypes::uint32				m_ui32Idx;

		bool	operator<( const FlareSortS& rOther ) const
		{
			if( m_i32Depth > rOther.m_i32Depth )
				return true;
			return false;
		}
	};

	std::vector<FlareSortS>		m_rSortList;
	std::vector<PajaTypes::float32>		m_rVertices;
	std::vector<PajaTypes::float32>		m_rTexCoords;
	std::vector<PajaTypes::float32>		m_rNormals;


	Composition::AutoGizmoC*	m_pTraGizmo;
	Composition::AutoGizmoC*	m_pAttGizmo;
	Composition::AutoGizmoC*	m_pFlareGizmo;
	Composition::AutoGizmoC*	m_pTimeGizmo;

//	PajaTypes::int32			m_i32Frame;
	PajaTypes::float32			m_f32Aspect;
	PajaTypes::ColorC			m_rClearColor;
	PajaTypes::int32			m_i32ClearFlags;
	CameraC*					m_pCam;
	PajaTypes::Vector2C			m_rSize;

	PajaTypes::int32			m_i32FlareUseLighting;
	PajaTypes::int32			m_i32FlareRenderMode;
	PajaTypes::float32			m_f32FlareExtrude;
	PajaTypes::float32			m_f32FlareSize;
	PajaTypes::ColorC			m_rFlareColor;

	PajaTypes::Matrix2C			m_rTM;
	PajaTypes::BBox2C			m_rBBox;
};

};	// namespace

// The global descriptors.
extern EngineDescC		g_rEngineDesc;
extern FlareDescC		g_rFlareDesc;
extern MASImportDescC	g_rMASImportDesc;



#endif	// __ENGINEPLUGIN_H__
