///////////////////////////////////////////////////////////
//
//  DEFINITION
//
//  CONTEXT: Genesis3D lightweight framework
//  MODULE:	 Genesis3D wrapper (service)
//  PREREQ:	 mainviewcontroller.h 
//  FILE:	 genewrap.h
//	AUTHOR:  Klaus Zerbe <klaus@zerbe.com>
//  ORIGIN:  http://klaus.zerbe.com
//  VERSION: 1.0
//  DATE:    3.2.1999
//  PURPOSE: encapsulate Genesis engine details
//
///////////////////////////////////////////////////////////

#ifndef __GENEWRAP__
#define __GENEWRAP__
//#include <ExtBox.h>
// mouse navigation is done by clicking in one of nine "zones"
// of the viewport allowing four degrees of freedom
//
//   |===============|===============|===============|
//   | strLeft       | lookup        | strRight      |
//   |===============|===============|===============|
//   | left          | lookStraight  | right         |
//   |===============|===============|===============|
//   | back          | lookdown      | fore          |
//   |===============|===============|===============|
//
//   where:
//   strLeft, strRight: strafe left and right
//   fore, back: 		step fore and back
//   left, right: 		turn left and right
//   lookup, lookdown:  look up and down
//   lookStraight:		look in front of you
//   Those codes are also used for keyboard navigation
//   which is mapped in "Duke Nukem" style
//
enum MouseMode { off, left, right, fore, back, 
	lookup, lookdown, strLeft, strRight, lookStraight };

// forward declaration of wrapper class
class CEngineWrapper;

////////////////////////////////////////////////////////////////////////////////
//
// abstract entity meta class
//
// This manages a list of subclass instances which are used as templates 
// (meta classes) for all kinds of entities (lights, actors, Artefacts, doors etc.)
// 
////////////////////////////////////////////////////////////////////////////////

class CEntityTemplate {
public:
	//
	// common interface
	// all inherited classes should implement the following
	//
	// register a new meta class (entity type)
	CEntityTemplate(CEngineWrapper *pEngine);
	// remove template and all its instances
	virtual ~CEntityTemplate();
	// called on each render cycle after positioning camera
	virtual void Render(geXForm3d *pViewPoint, DWORD  dwTime)=0;
	// handle collision with player
	virtual void DoCollision(geWorld_Model *pModel) {}
	//
	// entity class management
	// 
	// destroy all registered entity classes
	static void ShutDown();
	// render all entities
	static void RenderAll(geXForm3d *pViewPoint, DWORD  dwTime);
	// check/handle player collision with all entities
	static void HandleCollision(geWorld_Model *pModel);
	
protected:	
	// helper functions
	// create Genesis3D bitmap with alpha channel from two windows bitmaps
	geBitmap* CEntityTemplate::CreateAlphaBitmap(const geVFile *pBaseFS, const char *pBmpName, 
		const char *pAlphaName);
	CEngineWrapper *m_pWrapper; // related wrapper instance
	geVFile *m_pContext;  // directory containing artwork
	geEngine *m_pEngine;  // Genesis3D engine handle
	geWorld *m_pWorld;	  // current scene
private:
	// list management
	static CEntityTemplate *m_pFirst, *m_pLast;
	CEntityTemplate *m_pNext;
};

////////////////////////////////////////////////////////////////////////////////
//
// Genesis3D Engine - Wrapper Class
//
// encapsulates all Genesis3D groundwork
//
////////////////////////////////////////////////////////////////////////////////

class CEngineWrapper {
public:
	// create wrapper on view pView
	CEngineWrapper(CMainViewController *pView);
	// shutdown engine and all related objects
	~CEngineWrapper() { Shutdown();	}
	// start engine with artwork in pVirtualFile on level pLevel
	// pVirtualFile can be a DOS-directory or a VFS generated Hollywood3D virtual file
	void Startup(char *pVirtualFile, char *pLevel);
	// turn framerate display on/off
	void SetFramerateCount(bool bFramerateCnt= true);
	// shutdown engine and clean up all related stuff
	void Shutdown();
	// reset camera to player defaults
	void CameraReset();
	// position camera for time dwTime
	void TransformCamera(DWORD dwTime);
	// render frame
	void RenderFrame();
	// position cursor (showing the correct navigation icon)
	void SetCursor();
	// cursor navigation function select
	void SetMouseMode(MouseMode mode) { m_mousemode= mode; }
	// helper function: degrees to radian angle
	float DegreesToRadians(float degrees) { return (degrees * GE_PI)/180.0f;	}
	// get current navigation function and cursor icon needed in idc
	MouseMode GetMouseMode(int *idc);
	// get engine handle
	geEngine* GetEngine() { return m_pEngine; }
	// get world  handle
	geWorld* GetWorld() { return m_pWorld; 	}
	// get artwork folder handle
	geVFile* GetContext() { return m_pLevel; }
	// get sound system handle
	geSound_System* GetSoundSystem() { return m_pSoundSys; }
private:
	// look for the best (accelerated) driver for rendering into a window;
	// worst case will be software renderer
	bool FindBestWindowedDriver(geDriver **pBestDriver, geDriver_Mode **pBestMode);
	// check new position at current+delta for being valid
	bool CheckPosition(geVec3d* delta);
	// check player can move along delta
	bool CanMove(geVec3d *delta);
	
	// DOS folder for artwork
	char m_szArtworkFolder[MAX_PATH];
	CMainViewController *m_pView; // output view
	geEngine *m_pEngine; // engine handle
	geCamera *m_pCamera; // main camera handle
	geWorld *m_pWorld; // world handle
	geRect m_rcCamera; // camera viewport rectangle
	geXForm3d m_xfmCamera; // camera transformation matrix
	geVFile *m_pLevel, *m_pVirtual; // artwork folder and virtual artwork file
	geSound_System *m_pSoundSys;  // soundsystem handle
	geVec3d m_pos, m_mins, m_max;  // player position and bounding rectangle
	float m_heading, m_headup; // player viewing angles
	float m_speed, m_rotSpeed; // player speed and rotation speed
	MouseMode m_mousemode; // current navigation function
	DWORD m_dwLastRenderTime; // time when last frame was rendered
	bool m_bRendering; // currently rendering flag
};

////////////////////////////////////////////////////////////////////////////////
//
// some entity templates follow ..
//
////////////////////////////////////////////////////////////////////////////////

// get rid of unknown pragam warnings
#pragma warning( disable : 4068 )

////////////////////////////////////////////////////////////////////////////////
//
// player start
//
////////////////////////////////////////////////////////////////////////////////

// 
// position, view direction and size of player
// 
//
#pragma GE_Type("Player.ico") // icon used for GEDIT
typedef struct	PlayerStart
{
#pragma GE_Published // items which are editable in GEDIT
    geVec3d     Origin;			// position in world
    geVec3d		orientation;	// viewing angles
    geVec3d		mins;			// bounding rectangle
    geVec3d		maxs;			// 
    float		speed;			// player speed
    float		rotspeed;		// player rotation speed

#pragma GE_Origin(Origin)		

// GEDIT defaults for the items above
#pragma GE_DefaultValue(orientation, "0 0 0")
#pragma GE_DefaultValue(mins, "-30 -100 -30")
#pragma GE_DefaultValue(maxs, "40 60 40")
#pragma GE_DefaultValue(speed, "0.3")
#pragma GE_DefaultValue(rotspeed, "0.1")
    
// tooltip help lines for each item
#pragma GE_Documentation(orientation, "viewing direction x,y,z")
#pragma GE_Documentation(mins, "lower bounds of bounding rectangle")
#pragma GE_Documentation(maxs, "upper bounds of bounding rectangle")
#pragma GE_Documentation(maxs, "speed")
#pragma GE_Documentation(maxs, "rotation speed")
}	PlayerStart;

//Simple navigation entity for actor automation:  JJ Robinson II
#pragma GE_Type("WayPoint.bmp")
typedef struct WayPoint {
#pragma GE_Published
geVec3d		origin;
#pragma GE_Origin(origin)
} WayPoint;


////////////////////////////////////////////////////////////////////////////////
//
// movable world parts (eg. doors)
//
////////////////////////////////////////////////////////////////////////////////

// automatic door (opens on collide, closes after some seconds)

// this structure contains the individual data for each door instance
//

#pragma GE_Type("Model.ico") 
typedef struct  Door
{
#pragma	GE_Private // items hidden to GEDIT
	geFloat			lastTime;	// current animation time
	geFloat 		startTime;  // time when animation started
	geBoolean		bInAnimation; // currently in door animation?
	geBoolean		bTrigger;   // door triggered?

#pragma GE_Published
    geWorld_Model	*Model;	// world part to animate (eg. door)
    geVec3d			Origin; // door position
#pragma GE_Origin(Origin)
}   Door;

// this class contains the door controlling code
// and "class data" shared by all doors
//
class CDoor : public CEntityTemplate {
public:
	// create meta class for door behaviour
	CDoor(CEngineWrapper *pEngine);
	// destroy shared ressources	
	~CDoor();
	// render frame of door
	void Render(geXForm3d *pViewPoint, DWORD  dwTime);
	// collision handling (here: trigger open door animation)
	void DoCollision(geWorld_Model *pModel);
private:
	geSound_Def *m_pSound;	// door open sound
};

////////////////////////////////////////////////////////////////////////////////
//
// lights (more of that see effects.h, effects.cpp)
//
////////////////////////////////////////////////////////////////////////////////

// voluminetric fog
#pragma GE_Type("FogLight.ico")
typedef struct FogLight
{

#pragma GE_Published
	geVec3d		Origin;
	GE_RGBA		Color;		// fog color
	float		Brightness; // emitted fog brightness
	float		Radius;		// cloud size
#pragma GE_Origin(Origin)
} FogLight;

////////////////////////////////////////////////////////////////////////////////
//
// make some music (play MIDI files, see mci.h, mci.cpp for details)
//
////////////////////////////////////////////////////////////////////////////////

// definition of some MIDI file for level
#pragma GE_Type("Music.ico")
typedef struct Music
{
#pragma GE_Published
	geVec3d		Origin;
	char *		MidiFile;	// midi file  name
#pragma GE_Origin(Origin)
#pragma GE_DefaultValue(MidiFile, "")
#pragma GE_Documentation(MidiFile, "music for level")
} Music;

// clas controlling midi playing
class CMusic : public CEntityTemplate
{
public:	
	// make music controlling meta class instance
	CMusic(CEngineWrapper *pEngine);
	~CMusic();
	// not much to render for background music :)
	void Render(geXForm3d *pViewPoint, DWORD  dwTime) {}
};

////////////////////////////////////////////////////////////////////////////////
//
// general meta class for most passive world objects (polygon models)
// supports rotation around a given axis and a predefined animation and sound
//
////////////////////////////////////////////////////////////////////////////////

#pragma GE_Type("Artefact.bmp")
typedef struct Artefact
{
#pragma	GE_Private	// hidden to GEDIT
	geFloat			lastTime; 	// current animation time
	geFloat 		startTime;	// animation start time
	geFloat			SoundStartTime;
	geFloat			SoundCurrentTime;
	geActor	*		pActor;		// animated polygon model instance
	geActor_Def *	pActorDef;	// template for polygon model

	geSound_Def *	pDefSoundDef;  // sound template
	geSound_Def *	pProxSoundDef;  // sound template
	geSound_Def *	pCollSoundDef;  // sound template

	geSound *		pDefSound;  // current default sound instance
	geSound *		pProxSound;  // current proximity sound instance
	geSound *		pCollSound;  // current collision sound instance
#pragma GE_Published
    geVec3d			Origin;
    char *			actorName;  // actor file name (ACT-file)
    geVec3d			scale;		// scaling in x,y,z direction
    geVec3d			orientation; // orientation around x,y,z axis
    geVec3d			rotation;   // rotation degrees/secod around x,y,z
	geVec3d			mins;
	geVec3d			maxs;
    char *			DefMotion;		// default animation
    char *			DefSound;		// default sound (WAV- file name)
	int				DefSoundInterval;	//time between default sound starts
  //char *			soundTrig;  // c= continous, t= triggered
	geFloat 		Speed;		// Magnitude of velocity: JJ Robinson II
	geBoolean		hasWayPointTracking; //Does entity track WayPoints?: JJ Robinson II
	char *			CurrentWayPointName; //Name of WayPoint entity is currently tracking: JJ Robinson II
	geBoolean		hasActOnProximity; //Does entity have action on proximity to player?: JJ Robinson II
	geFloat			ProximityActionRadius;
	char *			ProxMotion;		// proximity animation
    char *			ProxSound;		// proximity sound (WAV- file name)
    int				ProxSoundInterval;	//time between proximity sound starts
	geBoolean		hasActOnCollision; //Does entity have action on collision with player?: JJ Robinson II
	char *			CollMotion;		// collision animation
    char *			CollSound;		// collision sound (WAV- file name)
    int 			CollSoundInterval;	// //time between collision sound starts

	// GEDIT  defaults
#pragma GE_Origin(Origin)
#pragma GE_DefaultValue(actorName, "Mannequin1.act")
#pragma GE_DefaultValue(scale, "2.0 2.0 2.0")
#pragma GE_DefaultValue(orientation, "90 0 90")
#pragma GE_DefaultValue(rotation, "0 0 0")
#pragma GE_DefaultValue(mins, "0 0 0")
#pragma GE_DefaultValue(maxs, "0 0 0")
#pragma GE_DefaultValue(DefMotion, "Mannequin Walk1")
#pragma GE_DefaultValue(DefSound, "")
//#pragma GE_DefaultValue(soundTrig, "c")
#pragma GE_DefaultValue(Speed, "5.0")
#pragma GE_DefaultValue(hasWayPointTracking, "TRUE")
#pragma GE_DefaultValue(CurrentWayPointName, "WayPoint1")
#pragma GE_DefaultValue(hasActOnProximity, "TRUE")
#pragma GE_DefaultValue(ProximityActionRadius, "150")
#pragma GE_DefaultValue(ProxMotion, "Mannequin Talk1")
#pragma GE_DefaultValue(ProxSound, "WatchItBub.wav")
#pragma GE_DefaultValue(ProxSoundInterval, "10000")
#pragma GE_DefaultValue(hasActOnCollision, "TRUE")
#pragma GE_DefaultValue(CollMotion, "Mannequin Wait1")
#pragma GE_DefaultValue(CollSound, "AnyTimeYoureReadyBub.wav")
#pragma GE_DefaultValue(CollSoundInterval, "10000")

// Editor toolnotes documentation
#pragma GE_Documentation(actorName, "model file name")
#pragma GE_Documentation(scale, "scale x,y,z")
#pragma GE_Documentation(orientation, "base direction x,y,z")
#pragma GE_Documentation(rotation, "rotation (degrees/sec) x,y,z")
#pragma GE_Documentation(DefMotion, "predefined animation")
#pragma GE_Documentation(DefSound, "predefined sound file")
//#pragma GE_Documentation(soundTrig, "(C)ontinous, (T)riggered")
#pragma GE_Documentation(Speed, "Magnitude of velocity")
#pragma GE_Documentation(hasWayPointTracking, "Does entity track WayPoints?")
#pragma GE_Documentation(CurrentWayPointName, "Name of WayPoint entity is currently tracking")
#pragma GE_Documentation(hasActOnProximity, "Does Actor have special animation when near Player?")
#pragma GE_Documentation(ProximityActionRadius, "How close should Actor be to Player to activate animation?")
#pragma GE_Documentation(ProxMotion, "Animation to use when in proximity to Player")
#pragma GE_Documentation(ProxSound, "Sound to play when in proximity to Player")
#pragma GE_Documentation(ProxSoundInterval, "How often to play sound when in proximity to Player")
#pragma GE_Documentation(hasActOnCollision, "Does Actor have special animation when collision occurs?")
#pragma GE_Documentation(CollMotion, "Animation to use when collision occurs")
#pragma GE_Documentation(CollSound, "Sound to play when collision occurs")
#pragma GE_Documentation(CollSoundInterval, "How often to play sound when collision occurs")
} Artefact;

#pragma warning( default : 4068 )
//
// since there can be several actor definitions with each having several instances
// in a scene, this class manages a list of all actor definitions used,
// allowing usage of the same definition for several instances and destroying all
// definitions on shutdown.
//

class CActorDefEntry {
public:
	// create new template using actor file pName and definition pActorDef
	CActorDefEntry(char *pName, geActor_Def *pActorDef);
	// destroy template
	~CActorDefEntry() {}
	// add template using actor file pName and definition pActorDef to list
	static void Add(char *pName, geActor_Def *pActorDef);
	// try to find definition pName; return it or NULL if not found
	static geActor_Def* Find(char *pName);
	// clear all definitions
	static void Clear();
private:
	char m_szName[40]; // template / actor file name
	geActor_Def *m_pActorDef; // actor definition
	CActorDefEntry *m_pNext; // list management
	static CActorDefEntry *m_pFirst, *m_pLast; 
};

//
// meta class for managing polygon actor (Artefact) behaviour
//
class CArtefact : public CEntityTemplate {
public:
	// allowing "Artefact" entity support
	CArtefact(CEngineWrapper *pEngine);
	// shutdown Artefact support
	~CArtefact();
//Automated actor behavior functions:  JJ Robinson II
	geVec3d CArtefact::MoveToWaypoint(Artefact *pArtefact);
	geXForm3d CArtefact::FaceToDirectionVector(geVec3d *DirectionVector);
bool CArtefact::CanMove(Artefact *pArtefact, geXForm3d *pViewPoint, geVec3d *delta);

geXForm3d CArtefact::FaceToPlayer(Artefact *pArtefact, geXForm3d *pViewPoint);
bool CArtefact::DetectProximityToPlayer(Artefact *pArtefact, geXForm3d *pViewPoint);
	// render Artefact
	virtual void Render(geXForm3d *pViewPoint, DWORD  dwTime);
};

#endif
