/*------------------------------------------------------------------
			Tool Include
			------------

	This is the main tool include file. Any tool DLLs should
	include this file as it contains the interface for the
	tool base class from which all tools are derived. It
	also provides the prototypes for the main DLL entry points
	used to create and delete the tool object (NB. The editor
	code cannot create a derived class it doesn't know about)

	(C) Silicon Dream Ltd 1994

  ------------------------------------------------------------------

Changes:						Date:
* Created file						27/12/94
*/

#ifndef TOOL
#define TOOL

#ifndef STRICT
#define STRICT		// For correct HDC definition, otherwise derived tools get linker error
#endif

#include <windows.h>
#include <atomic.h>
#include <cppmaths.h>
#include <cppdebug.h>
#include <geometry.h>

/* Used by tool to inform editor what to redraw after a tool action */

typedef enum Redraw{REDRAW_ALL=0,		// Re-renders and redraws overlay for all views
		    REDRAW_NONE,		// No redraws at all
		    REDRAW_TOOL,		// Redraw ONLY using tools DrawSoFar() routine
		    REDRAW_NOTOOL,		// Refreshes screen from bitmaps and thats all
		    REDRAW_REFRESH,		// Refreshes screen from bitmaps and calls DrawSoFar()
		    REDRAW_OBJECT_WIRE,		// Redraw current object only direct to screen in XOR
		    REDRAW_SHADING,		// Re-renders but doesn't change the overlay
		    PRIVATE_REDRAW_OVERLAY,	// Reserved
		    PRIVATE_REDRAW_ALL_OVERLAY};// Reserved

/* Used by tool to put editor into a new mode */

typedef enum Mode{MODE_EDIT=0, MODE_VIEW=1, MODE_SELECT=2, MODE_FLIGHT=3};

/* Handle to an object archive */

typedef ulong		HanArchive;	// harch

/* Tool callback codes and router function definition */

#define CT_WRITEMESSAGE		0
#define CT_SETVIEWDATA		1
#define CT_ADDNAMEDOBJ		2
#define CT_ADDNAMEDCSYS		3
#define CT_GETOBJHANDLE		4
#define CT_GETCSYSHANDLE	5
#define CT_GETOBJNAME		6
#define CT_GETCSYSNAME		7
#define CT_UPDATEVIEWS		8
#define CT_ACTIVATECSYSWIN	9
#define CT_ADDUSERDATA		10
#define CT_GETUSERDATA		11
#define CT_REMOVEUSERDATA	12
#define CT_QRYNEXTCSYS		13
#define CT_NOVIEWCHANGE		14
#define CT_MAKEOBJWIREFRAME	15
#define CT_PARTSELECTED		16
#define CT_PASTERECEIVER	17
#define CT_MODIFIEDSCENE	18
#define CT_AUTOSMOOTHDLG	19
#define CT_SURFACEDLG		20
#define CT_CHANGEMODE		21
#define CT_SETCURSOR		22
#define CT_ARCHIVEOBJECT	23
#define CT_CREATEFROMARCHIVE	24
#define CT_DELETEARCHIVE	25

typedef ulong _exp fnToolCallback(void *pvDoc, ushort usCallType,
				  ulong ul1, ulong ul2, ulong ul3);

/* For updating tool specific toolbar buttons and menu items */

typedef enum CmdUpdate {ENABLE, DISABLE, CHECK, UNCHECK,
			INDETER, RADIOON, RADIOOFF, SETTEXT};


/* Marker types */

#define MT_BOX		0
#define MT_PLUS		1
#define MT_CROSS	2
#define MT_DIAMOND	3

/* Flags for DrawArrow */

#define DA_FILLED		1
#define DA_FIXEDSIZE		2

/* Maximum list object name length */

#define MAX_NAME_BUFF_LEN	35	// To allow for null and digits
#define MAX_NAME_LEN		30

/* Reserved structure */

typedef struct UserDataInfotag		// pudi
	{
	HanObject		hobj;
	Handle			han;
	HandleType		htype;
	} UserDataInfo;

/* Notice a lot of the functions in the Tool class are virtual as it serves
   purely as a polymorphic interface for derived classes. The functions
   implemented in the Tool class do nothing. We cannot however make them
   pure virtual as we would then have an abstract class, and derived tools
   would be required to implement every function otherwise they too would
   become abstract classes (ie. we wouldn't be able to create one) */

class _cppdyn Tool
	{
	private:
		void		*pvDoc;				// Ptr to document object
		fnToolCallback	*ToolCallback;			// Callback entry point to editor
		ulong		ulMaxVerts, ulMaxNorms, ulMaxPats;
		HanObject	hobjPrim;
		bool		bReportErrs, bUndoOnErr;

	private:
		int ToolMessageBox(GeomErr gerr);

	public:
		HINSTANCE	hinst;				// Instance of DLL
		HWND		hwnd;				// Main frame window
		HanVertex	*ahverPrim, hverPrim;		// Primitive vertex handle array
		HanNormal	*ahnorPrim, hnorPrim;		// Primitive normal handle array
		HanPatch	*ahpatPrim;			// Primitive patch handle array
		ulong		ulNumVerts, ulNumNorms, ulNumPats; // Numbers of elements
		HanCoorSys	hcsysTopLevel;			// Documents top level coor sys
		HanCoorSys	hcsysActive;			// Currently active coor sys
		HanSurf		hsurActive;			// Currently active surface type
		ushort		usSmoothFlags;			// Global autosmoothing flags
		float		fSmoothAng;			// Global autosmoothing angle threshold
		bool		bOverlay;			// Overlay is switched on is active view
		Mode		mode;				// Mode of active view

	public:
		// Overideables

		virtual ~Tool();			// Destructor
		virtual void Initialise();		// Called once when DLL loaded
		virtual Redraw OnSelect(Vec &vec);	// Called when tool is selected
		virtual Redraw OnUnSelect(bool *pbOkToChange); // Called when tool is selected
		virtual void OnConfigure();		// Called to configure tool
		virtual Redraw OnButtonDown(Vec &vec);	// Called when button pressed
		virtual Redraw OnMouseMove(Vec &vec);	// Called when mouse moves with button down
		virtual Redraw OnButtonUp(Vec &vec);	// Called when button is released
		virtual Redraw OnSet(Vec &vec);		// Called when the 'Set' button is clicked
		virtual Redraw OnUndo();		// Called when user wishes to undo effect of tool
		virtual void FreeUndo();		// Called when tool no longer needs to keep stuff for undoing
		virtual Redraw OnDo(Vec &vec);		// Called to end use of tool
		virtual void OnViewChange(HanCoorSys hcsys, Vec &vec); // Called when active view changes
		virtual Redraw OnPaste(Vec &vec, HanObject *ahobj, // Called when objects are pasted into the current view
				       ulong ulNumObjects);
		virtual void OnCommand(ushort usID);	// Called when a tool specific menu item/toolbar button selected
		virtual CmdUpdate OnCommandUpdate(ushort usID, // Called when a tool specific menu item/toolbar button needs updating
						  char *szText, ushort usBuffSize);
		virtual void DrawSoFar(HDC hdc, HanCoorSys hcsys, // Called to draw object so far into the view
				       void *pvViewData, bool bInvalid);

		// Tool support functions

		void WriteMessage(int iResId);		// Call to write message in status bar
		void WriteMessage(const char *szMsg);	// Call to write message in status bar
		int MessageBox(int iTitleId, int iMsgId, UINT uiStyle=MB_ICONEXCLAMATION); // Call to create message box
		int MessageBox(int iTitleId, const char *szMsg, UINT uiStyle=MB_ICONEXCLAMATION); // Call to create message box
		int MessageBox(int iTitleId, GeomErr gerr); // Call to create message box
		void EndPrim (void);			// Removes buffers for handles
		bool StartPrim (HanObject hobj, ulong ulMaxVerts, // Allocate buffers for handles
				ulong ulMaxNorms, ulong ulMaxPats,
				bool bReportErrs, bool bUndoOnErr);
		void RemovePrim (void);			// Removes all primitive elements (verts etc.)
		GeomErr AddVertex (const Vec &vec);	// Adds a vertex (records handle)
		GeomErr AddNormal (const Vec &vec);	// Adds a normal (records handle)
		GeomErr DefPatch (ushort usNumEdges, ushort usFlags, float fSmoothAng, // Adds a patch (records handle)
				  HanVertex *ahver, HanNormal *ahnor, HanSurf hsur=NULL_HANDLE);
		HanObject AddObject(HanCoorSys hcsys, char *szName, // Adds a new named object
				    ushort usBuffSize, float fNewVertTol, HanObject hobj);
		HanCoorSys AddCoorSys(HanCoorSys hcsysParent, char *szName, // Adds a new named coor sys
				      ushort usBuffSize, HanCoorSys hcsys,
				      const Mat &matToParent, const Mat &matFromParent,
				      ushort usType, bool bAddView);
		HanObject GetObjectHandle(const char *szName);// Returns the handle of a named object
		HanCoorSys GetCoorSysHandle(const char *szName);// Returns the handle of a named coor sys
		void GetObjectName(HanObject hobj, char *szName, // Returns the name of the object with the handle
				   ushort usBuffSize);
		void GetCoorSysName(HanCoorSys hcsys, char *szName, // Returns the name of the coor sys with the handle
				    ushort usBuffSize);
		void DrawMarker(HDC hdc, int iX, int iY, ushort usType); // Draws a marker on the DC
		void DrawArrow(HDC hdc, int iX, int iY, ushort usFlags); // Draws an arrow onto the DC
		void SetViewData(void *pvData, ushort usSize); // Sets data for all views
		void BackgroundYield(const char *szWrite=NULL);// Yields control and writes message
		void ForceRedraw(Redraw rd, HanCoorSys hcsys=NULL_HANDLE); // Forces a redraw independently of event
		bool ActivateCSysWin(HanCoorSys hcsys);	// Activates coor sys window (brings to top)
		void ModifiedScene();			// Mark scene as modified by this tool
		void *AddUserData(HanObject hobj, Handle han, // Adds user data to a Geometry item
				  HandleType htype, ulong ulSize);
		void *GetUserData(HanObject hobj, Handle han, // Retrieves user data from a Geometry item
				  HandleType htype);
		bool RemoveUserData(HanObject hobj, Handle han, // Removes user data from a Geometry item
				    HandleType htype);
		bool IsSelected(HanObject hobj, Handle han, HandleType htype); // Returns TRUE if item is selected
		Handle GetNextSelected(Handle hanParent, ulong *pulRef, HandleType htype); // Returns the next selected item
		HanCoorSys QryNextCoorSys(ulong *pulRef, CoorSysInfo *pcsi); // Queries next coor sys in a scene
		void EditInThisView(HanCoorSys hcsys);	// Do not allow editing in any other view
		void MakeObjWireframe(HanObject hobj);	// Makes object XOR'd on REDRAW_OBJECT_WIRE
		void NoneWireframe();			// Makes no objects XOR'd on REDRAW_OBJECT_WIRE
		void PasteReceiver();			// Sets this tool as the paste receiver
		void AutosmoothDlg();			// Calls up the autosmooth dialog
		void SurfaceDlg();			// Calls up the surface type dialog
		void ChangeMode(Mode mode);		// Puts editor into a new mode
		void SetCursor(const Vec &vec);		// Sets the position of the 3D cursor
		HanArchive ArchiveObject(HanCoorSys hcsysOrigin, // Creates an archive for an object
					 HanObject hobj, bool bRemove);
		HanObject CreateFromArchive(HanArchive harch, // Recreates an object from the archive
					    HanCoorSys hcsys);
		void DeleteArchive(HanArchive harch);	// Destroys an object archive

		// Editor support functions (not for use by derived tools)

		void Initialise(HINSTANCE hinstDLL,
				void *pvDocIn,
				HWND hwnd,
				fnToolCallback *ToolCallbackIn,
				HanCoorSys hcsysDocTop); // Called to initialise base class
		Redraw OnBaseSelect(HanCoorSys hcsys, HanSurf hsur, ushort usSmoothFlagsIn,
				    float fSmoothAngInVec, bool bOverlayIn, ushort usMode,
				    Vec &vec); // Called to initialise tools public data
		void OnBaseViewChange(HanCoorSys hcsys, bool bOverlayIn,
				      ushort usMode, Vec &vec); // Called when active view changes
		void OnBaseParmChange(HanSurf hsur, ushort usSmoothFlagsIn,
				      float fSmoothAngIn, bool bOverlayIn, ushort usMode); // Called when a global parameter changes
	};

/* The IMPLEMENT_OBJECT macro implements the CreateTool and DeleteTool functions, and the
   typedefs are used by the editor to call the function */

#ifdef _MSC_VER
#define IMPLEMENT_OBJECT(class) _st class tool; \
_getdyn Tool *CreateTool() {DebStart(); return New class;} \
_getdyn void DeleteTool(Tool *ptool) {Delete ptool;}
#endif
#ifndef _MSC_VER
#define IMPLEMENT_OBJECT(class) _st class tool; \
Tool * _getdyn CreateTool() {DebStart(); return New class;} \
void _getdyn DeleteTool(Tool *ptool) {Delete ptool;}
#endif
typedef Tool *fnCreateTool();
typedef void fnDeleteTool(Tool *ptool);

#endif
