//////////////////////////////////////////////////////////////////////////////////////
// 
// FILE : Tools_Entity_PhysicalObject.h
//
// AUTHOR : Martin G. Harris
//
// Copyright 2002 Rebellion, All Rights Reserved.
//
//////////////////////////////////////////////////////////////////////////////////////

#ifdef ASURA_USE_PRAGMA_ONCE
    #pragma once
#endif

#ifndef _TOOLS_ENTITY_PHYSICAL_OBJECT_H_
#define _TOOLS_ENTITY_PHYSICAL_OBJECT_H_

#include "Entity/Tools_Entity_Object.h"

#include "Core/Asura_String.h"
#include "Entity/PhysicalObject/Asura_ServerEntity_PhysicalObject.h"
#include "Network/Asura_Message.h"
#include "Shapes/Asura_Shapes.h"

const Asura_Hash_ID uTOOLS_SHAREDPARAMHASH_PHYSICALOBJECT_MERGEWITHENV      = 0x6069272B; // Asura_GetHashID("Asura_PhysicalObject_MergeWithEnv")
const Asura_Hash_ID uTOOLS_SHAREDPARAMHASH_PHYSICALOBJECT_MERGESCALEX       = 0x3DFC2B2A; // Asura_GetHashID("Asura_PhysicalObject_MergeScaleX")
const Asura_Hash_ID uTOOLS_SHAREDPARAMHASH_PHYSICALOBJECT_MERGESCALEY       = 0x3DFC2B2B; // Asura_GetHashID("Asura_PhysicalObject_MergeScaleY")
const Asura_Hash_ID uTOOLS_SHAREDPARAMHASH_PHYSICALOBJECT_MERGESCALEZ       = 0x3DFC2B2C; // Asura_GetHashID("Asura_PhysicalObject_MergeScaleZ")
const Asura_Hash_ID uTOOLS_SHAREDPARAMHASH_PHYSICALOBJECT_MERGEUNIFORMSCALE = 0x5A872DD2; // Asura_GetHashID("Asura_PhysicalObject_MergeUniformScale")
const Asura_Hash_ID uTOOLS_SHAREDPARAMHASH_PHYSICALOBJECT_DESTRUCTIBLE      = 0x695390E4; // Asura_GetHashID("Asura_PhysicalObject_Destructible")
const Asura_Hash_ID uTOOLS_SHAREDPARAMHASH_PHYSICALOBJECT_HEALTH            = 0x23AD4F58; // Asura_GetHashID("Asura_PhysicalObject_Health")
const Asura_Hash_ID uTOOLS_SHAREDPARAMHASH_PHYSICALOBJECT_MERGEWITHSKY      = 0x60695B5F; // Asura_GetHashID("Asura_PhysicalObject_MergeWithSky")

////////////////////////////////////////////////////////////////////////////////
// Tools_Entity_PhysicalObject                                                //
//                                                                            //
// *NOTE*: only tools objects that have Asura_ServerEntity_PhysicalObject     //
// entities associated with them should inherit from this class.              //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
class Tools_Entity_PhysicalObject: public Tools_Entity_Object
{
public:
	friend class Tools_Entity_PhysicsObject;
#ifndef ASURA_TARGET_SM3
	friend class Tools_Entity_DestructibleLight;
#endif // #ifndef ASURA_TARGET_SM3
	virtual void Destroy(); // Make sure all client entities are destroyed too.
    virtual void Render();
    virtual void RenderPreFSFX();

	#ifndef TOOLS_USE_OLD_ENTITY_MANAGER
	virtual const char* GetShortName(){return "PHOBJ";}
	#endif

	// Make sure server position/orientation is updated.
	virtual void UpdatePositionInAsuraData(bool /*bUpdateLinkedObjects*/);

	virtual const char* GetTypeDescription() { return "Physical Object"; }

    // virtual override
	virtual bool ShouldRenderShadow();
	virtual bool UseLighting(){return true;}

    // for triggering anim changes
    virtual bool HandlesThisMessage(int messageID);
	virtual bool HandlesThisEvent(int iEventID) const;

	// message overlay deletion/creation functions for overriding. Used in AddMessageBlock
	virtual void DeleteMessageOverlay(void) { DeleteOverlay(); }
	virtual void CreateMessageOverlay(void) { CreateOverlay(); }

    // virtual overrides to add required files to tools export
    virtual void AddFilesToExportList(List<Asura_String>& nameList) const;
    virtual void AddFilesToExportListFromMessage(u_short usMessageID, void* pData, 
        List<Asura_String>& nameList) const;

	virtual bool ShouldAddFilesToExportList() const;
	
    void AddBlockLinksOverlayControl(Asura_Overlay* pxNewOverlay, Asura_Vector_2& xOffset);
    virtual void AddHealthOverlayControl(Asura_Overlay* pxNewOverlay, Asura_Vector_2& xOffset, bool bAddDestructibleFlag = true);
	void AddMergeWithEnvOverlayControl(Asura_Overlay* pxNewOverlay, Asura_Vector_2& xOffset);
	void AddMergeWithSkyOverlayControl(Asura_Overlay* pxNewOverlay, Asura_Vector_2& xOffset);
    virtual bool AddSharedParamDialogToOverlay( Asura_Overlay* pxOverlay, const Asura_Vector_2& xOffset, Asura_Hash_ID uParamID );

	virtual void UpdateWhileSelected(void);	


	virtual void Copy(const Tools_Object*);

	virtual bool ShouldRenderSelectionOutlineOnly();
	virtual void SetEntityModified();

	virtual bool Verify( const bool bAutomatic );

	//Checks all objects flagged for merging into environment and does the merging.
	//If bForceRecalculateAll then all entity polygons are deleted first and redone
	//from scratch , in case the environment and entity files are out of sync	
	static void MergeObjectsIntoEnvironmentIfNeeded(bool bForceRecalculateAll);

	//Makes some checks to see if environment/entity file is out of sync for merging
	static void CheckIsMergedWithEnvironmentFlags();


	Asura_Hash_ID GetShapeOrSkinFileID() const { return m_uFileID; }
	virtual Asura_String GetShapeOrSkinName() const;

	virtual void SelectShape( void );
	virtual void SelectSkinAndAnim(bool bForceNoAnimation = false);
	virtual void SelectAnim( void );

	//Attempts to load all the skins and animations used by physical objects
	static void LoadSkinsAndAnims();

	Asura_ServerEntity_PhysicalObject* GetPhysicalObject() const { return m_pxPhysicalObject; }

protected:
	Tools_Entity_PhysicalObject(Asura_Entity* pxEntity);
	virtual ~Tools_Entity_PhysicalObject();

	void SetToolsShape(Asura_Hash_ID uShapeID);
    void SetToolsSkinAndAnim(Asura_Hash_ID uFileID, Asura_Hash_ID uSkinID, Asura_Hash_ID uAnimID, Asura_Hash_ID uAnimFileID);

    const Asura_String& GetShapeFilename( void ) const { return m_xShapeFilename; }
    const Asura_String& GetAnimName( void ) const { return m_xAnimName; }

	static void SelectShape_Dialog();
	static void SelectSkinOnly_Dialog();
	static void SelectSkinAndAnim_Dialog();
	static void SelectAnim_Dialog();

	virtual void PrintInfo(float& x,float& y);

	// Helper function to add a new object in tools.
	static void CreationHelper( const char* szTypeName,
								const char* szShortName,
								void (*pfnCreate1)(Asura_Guid),
								Tools_Object* (pfnCreate2)(Asura_Entity*),
								const char* szNamePrefix = 0 );

	virtual void OnSelection();
	virtual void OnDeselection();
	virtual void OnGroupDeselection();
	virtual void OnUpdateFromTemplate();
	virtual bool ShouldHideWithinTemplate() const {return false;}



	void SetPhysicalObjectFlags(u_int uFlags);
	u_int GetPhysicalObjectFlags() const {return m_uPhysicalObjectFlags;;}

	//Unmerges this objects polygons from the environment , if they are currently merged
	void UnmergePolygonsFromEnvironment();
	//Merges this objects polygons into the environment , if this object is flagged to do so,
	//and if the polygons aren't already merged
	void MergePolygonsIntoEnvironmentIfNeeded();

	static void ForceUpdateOfAllMergedObject();

	u_int GetChecksumForMerge() const;

	//Should return true if the  properties overlay for the derived class will have the merge options added.
	//(This is used to prevent the settings from being changed by Get/Set parameter on objects that
	//don't support merging).
	virtual bool SupportsMerging() const {return false;}

	virtual Asura_Handle GetEntityPhysicsObjectHandle() const;

	virtual bool DoesObjectNeedToBeAbleToMove() const;

	virtual bool GetParameter(Asura_Hash_ID uParamID,class Tools_Parameter* pxParam) const;
	virtual bool SetParameter(Asura_Hash_ID uParamID,const class Tools_Parameter* pxParam);

	virtual void UpdateScaleInAsuraData();
	virtual bool CanBeScaled() const;

	//Sets the mesh to use if no shape/skin has been chosen
	void SetDefaultMesh(const char* szMeshName);

	//Recalculates waypoint blocking , and updates stuff that needs updating.
	void RecalculateWaypointLinkBlocks();

	bool IsMergedWithSkybox() const {return (m_uPhysicalObjectFlags & ASURA_PHYSICALOBJECT_FLAG_SHOULDMERGEWITHSKY) !=0;}


protected:
	// Keep an extra copy of the entity pointer, as we can't downcast from Asura_Entity*.
	Asura_ServerEntity_PhysicalObject* m_pxPhysicalObject;
	static bool s_bCreating;
	bool  m_bIsDestructible;
	u_int m_uPhysicalObjectFlags;

	static Tools_Entity_PhysicalObject* s_pxCurrentlySelectedObject;

private:

    typedef Tools_Entity_Object PARENT;

	Asura_String  m_xShapeFilename; // Full file name of the shape mesh.
	Asura_String m_xAnimName;
	Asura_String m_xAnimFilename;
	Asura_Hash_ID m_uFileID;   // Hash ID corresponding to the filename.
    Asura_Hash_ID m_uSkinID;
    Asura_Hash_ID m_uAnimID;
    Asura_Hash_ID m_uAnimFileID;
	bool m_bNotRenderedInGame;//true if it uses shapes with 'Never Rendered' flag

	bool m_bUniformScale;

	//mesh to use if no shape/skin has been chosen
	Asura_Mesh* m_pxDefaultMesh;
	bool m_bUsingDefaultMesh;


	static bool s_bOffsetSkyboxObjectsWhenFlagChanged;

	friend class Asura_Skybox;

	static Asura_Hashed_List<Tools_Entity_PhysicalObject> s_xList;

	//list of failed merges, for tracking which the user has been warned about
	static List<Asura_Guid> s_xFailedMergeList;

};


#endif //_TOOLS_ENTITY_PHYSICAL_OBJECT_H_


