// EdGUIObject.h: interface for the EdGUIObject class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_EDGUIOBJECT_H__A1F90212_DD09_4804_925F_AEE14F3D42E1__INCLUDED_)
#define AFX_EDGUIOBJECT_H__A1F90212_DD09_4804_925F_AEE14F3D42E1__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include<Stuff\Stuff.hpp>

class DrawInfo;
class ViewWindowInfo;
class EdGUIObject; 
class CObjPanelDlg;

#include"GlobalFlags.h"

using namespace Stuff;
class UndoCommand;
class ObjectManager;
class CObjManListCtrl;
class GUILine
{
protected:
	Stuff::Point3D Begin,End;		
public:
	void SetLine(Point3D s,Point3D f) {Begin=s; End=f; }
	void SetLine(Scalar sx,Scalar sy,Scalar ex,Scalar ey) {Begin=Point3D(sx,0.0f,sy); End=Point3D(ex,0.0f,ey); }
	friend class EdGUIObject;
};

class BaseEdObject
{
private:
	UnitQuaternion RotQuat;
	Point3D Pos;

protected:
	void Copy(BaseEdObject &obj);

public:
	BaseEdObject() {RotQuat=UnitQuaternion::Identity; Pos=Point3D(0.0f,0.0f,0.0f); }
	Scalar DistSquTo(Point3D &pnt)			{ return (Pos.x-pnt.x)*(Pos.x-pnt.x)+(Pos.z-pnt.z)*(Pos.z-pnt.z);}	

	void SetRot(UnitQuaternion &rot)		{ RotQuat=rot; UpdateMat(); }
	void SetPos(Point3D &newloc)			{ Pos=newloc; UpdateMat();   }
	void SetPosNoUpdate(Point3D &newloc)	{ Pos=newloc; }
	void SetRotNoUpdate(UnitQuaternion &newrot)	{ RotQuat=newrot; }
	void SetMatNoUpdate(LinearMatrix4D &mat)	{ Pos=mat; RotQuat=mat;}
	void SetPos(Scalar x,Scalar y,Scalar z) { SetPos(Point3D(x,y,z));    } 
	const Point3D &GetPos()					{ return Pos;} 
	const UnitQuaternion &GetRot()		{ return RotQuat;} 

	LinearMatrix4D GetMat();
	void SetMat(const LinearMatrix4D &mat);

	virtual void OffsetBy( Point3D &pnt)			{ Pos+=pnt; UpdateMat();     }
	virtual void RotateBy(UnitQuaternion &rot);
	void RotateAround(Point3D &pnt,UnitQuaternion &rot);

	virtual void UpdateMat() {RotQuat.Normalize();}
};

class GUIObjectList;
class MoveCommand;
class RotateCommand;
class CObjProps;

class EdGUIObject:public BaseEdObject
{
friend class GUIObjectList;
private:
protected: 
	
	void Copy(EdGUIObject &obj);
	GUIObjectList *Parent;
	GUILine *LineList;
	int LineCount;
	Scalar RadiusSqu;
	CString Name;
	Scalar HoverElevation;
	bool Selected;
	bool SnapToGround;
	bool Frozen;
	bool Modified;
	bool Visual;
	bool Hidden;
	bool InMap;
	int ReferenceCount;

	int DrawPen,SelPen;
	int ScreenDiv;
	int GetScreenRadius(ViewWindowInfo &vinf);
	
	virtual void BuildRadius();
	bool InDisplayRegion(DrawInfo &dinf);  
	virtual bool InRadius( Point3D &pnt); 
	bool InsideBox( Point3D &tl, Point3D &br); 
	bool IntersectsBox( Point3D &tl, Point3D &br); 
	virtual bool DeleteSelected(UndoCommand **delcom) { return false;} 
	virtual bool DeleteSelected() { return false;} 
public:
	virtual void DefaultExtraData() {HoverElevation=0.0f; SnapToGround=true;}
	void Freeze() {Frozen=true;}
	void UnFreeze() {Frozen=false;}
	bool IsFrozen() {return Frozen;}
	virtual CString GetTypeName() {return ("GUI Helper");} 
	virtual int GetUnSelIcon() {return ICON_NONE; }
	virtual int GetSelIcon()   {return ICON_NONE; }
	void OffsetBy( Point3D &pnt);
	void RotateBy(UnitQuaternion &rot)	{ if(!IsHidden()) BaseEdObject::RotateBy(rot); }
	virtual void SnapObjectToGround(bool overrideflag=true);
	virtual EdGUIObject *FindFirstSelected() { if(IsSelected()) return this; else return NULL;}

	void AddRefernce() {ReferenceCount++; Verify(ReferenceCount>=0);}
	void RemoveRefernce() {ReferenceCount--; Verify(ReferenceCount>=0);}
	virtual void SaveTextInfo(NotationFile *not_file);	
	virtual void SetInfo(Page *page);	
	virtual void SyncData() {}


	virtual void AddPanel(CObjPanelDlg *pnl,UndoCommand **cmd);
	GUIObjectList *GetParent() {return Parent;}

	// Undo Methods
	virtual void SavePosIfSelected(UndoCommand **cmd);
	virtual void SaveRotIfSelected(UndoCommand **cmd);
	void SaveGroup(UndoCommand **cmd);
	void SavePos(UndoCommand **cmd);
	void SaveRot(UndoCommand **cmd);
	
	virtual void GetMultiPropsIfSelected(CObjProps *props) {if(IsSelected()) GetMultiProps(props);}
	virtual void SetMultiPropsIfSelected(CObjProps *props,UndoCommand **cmd) {if(IsSelected()) SetMultiProps(props,cmd);}
	virtual void GetMultiProps(CObjProps *props);
	virtual void SetMultiProps(CObjProps *props,UndoCommand **cmd);
	virtual EdGUIObject *SelectClosestInternal(Point3D &pnt,Scalar *crat);	
	void SetPen(DrawInfo &dinf);
	virtual void SortChildren() {return;}
	virtual void SetHide(bool flag)	{Hidden=flag;}
	virtual bool IsMultiZone()		{return false;}
	virtual bool IsMultiTile()		{return false;}
	virtual void SelectMultiZone()	{  }
	virtual void SelectMultiTile()	{  }
	bool IsHidden() {return Hidden;}
	bool IsVisual() { return Visual;}
	virtual bool IsModified() {return Modified;}
	virtual void ClearModifyFlags() {Modified=false;}
	void Modify() {Modified=true;}


	// Tags
	virtual CString GetTag(unsigned long tag_flags);

	EdGUIObject &operator=(EdGUIObject &obj) { Copy(obj); return *this;}
virtual EdGUIObject *Clone();

virtual EdGUIObject *GetObjectByName(CString name);
	
	bool GetSnapToGround() {return SnapToGround;}
	float GetHoverElevation() {return HoverElevation;}
	virtual void SetSnapToGround(bool snap,bool preservepos=false);
	virtual void SetHoverElevation(float elev) {HoverElevation=elev; UpdateMat();}
	void UpdateMat();
	

	virtual ObjectManager *GetMyMission(); 
	CString GetMissionName() {return ((EdGUIObject *)GetMyMission())->GetName();}
	virtual void SetName( CString &name);
	virtual void Draw(DrawInfo &dinf);
	virtual void DrawTileViolation(DrawInfo &dinf) {}
	virtual void DrawTag(DrawInfo &dinf, unsigned long tag_flags);
	virtual void DrawSelectedObjects(DrawInfo &dinf,bool drawTags, unsigned long tag_flags );
	virtual void DrawUnSelectedObjects(DrawInfo &dinf,bool drawTags, unsigned long tag_flags);
	virtual bool InTree(EdGUIObject *gobj) {return gobj==this;}	
	virtual void GetExtents(Point3D *tl,Point3D *br);
	virtual bool GetSelectionExtents(Point3D *tl,Point3D *br); 
	virtual	void Dissociate() {}
	virtual	HTREEITEM AddToBranch(CTreeCtrl *tree,HTREEITEM itm) {return NULL;}
	virtual	int AddToList(CObjManListCtrl *list,unsigned long tag_flags);

	virtual void RemoveFromMap() {InMap=false;}
	virtual void AddToMap()		 {InMap=true; }
	virtual bool HasLocalizedName() { return false;}
	virtual void UseLocalizedName(bool flag) {}
	
	virtual void CopySelectionToList(GUIObjectList *list);

	
	
	//Selection Members
	virtual int DeSelect(Point3D &pnt);	
	virtual int Select(Point3D &pnt);	
	bool SelectClosest(Point3D &pnt);
	virtual bool SelectNext(Point3D &pnt,bool found=false); 	
	virtual int SelectionCount() {return Selected && !Hidden;}	//Cannot be selected if you are hidden	
	virtual int SelectionDepth(Point3D &pnt);	
	virtual int ObjectDepth(Point3D &pnt);	
	virtual int ToggleSelect(Point3D &pnt);	
	virtual int Select(Point3D &topleft,Point3D &bottomright);	
	virtual EdGUIObject *GetObjAtPoint(Point3D &pnt) {if(InRadius(pnt)) return this; else return NULL;}	
	
	virtual void Select()		{Selected=true;}
	virtual void DeSelect()		{Selected=false;}
	virtual void ToggleSelect() {Selected=!Selected;}
	virtual EdGUIObject *AddNodeIfSelected(Point3D &pnt,bool insert)	{return NULL;}
	virtual bool ContainsSelection() { return false;}
	virtual bool IsEmpty() {return false;}
	virtual int GroupSelected(UndoCommand **cmd) {return 0;}
	virtual bool UnGroupSelected(UndoCommand **cmd);
	virtual void MoveToGroup(EdGUIObject *gobj);
	virtual void PruneEmpty(UndoCommand **cmd) {}

	void YawAround(Point3D &pnt,Scalar yaw);
	void RollAround(Point3D &pnt,Scalar roll);
	void PitchAround(Point3D &pnt,Scalar pitch);

	bool IsSelected()	{return Selected;}
	CString &GetName()  {return Name;}
	
	//Test Members
	Scalar GetRadius(); 

	virtual void UpdateVisibility(DWORD visflag) { SetHide(false); }

	//Location Members
	virtual void RotateSelectionAround(Point3D &pnt,UnitQuaternion &vct);
	virtual void OffsetSelection(Point3D &vct); 
	virtual void RotateSelection(UnitQuaternion &vct);
	

	//Vector Rep Members
	int GetLineCount() {return LineCount;}
	void GetLine(int idx,Point3D *start,Point3D *end);
	EdGUIObject(CString name="Helper",Point3D pnt=Point3D(0,0,0));
	virtual ~EdGUIObject();
};

int _cdecl CompareGUIObjs(const void *elem1, const void *elem2);

#endif // !defined(AFX_EDGUIOBJECT_H__A1F90212_DD09_4804_925F_AEE14F3D42E1__INCLUDED_)
