/********************************************************************************
	hierarchy.h: Ultra 64 MARIO Brothers include file

	Copyright (c) 1996 Nintendo co., ltd.  All rights reserved

	May 9, 1996
 ********************************************************************************/

#ifndef HIERARCHY_H
#define	HIERARCHY_H


/* node code */

#define	MAP_TYPE_CBACK		0x100

#define	MAP_NODE			 0
#define	MAP_NODE_SCENE		 1
#define	MAP_NODE_ORTHO		 2
#define	MAP_NODE_PERSP		 3 + MAP_TYPE_CBACK
#define	MAP_NODE_LAYER		 4

#define	MAP_NODE_GROUP		10
#define	MAP_NODE_LOD		11
#define	MAP_NODE_SELECT		12 + MAP_TYPE_CBACK
#define	MAP_NODE_AREA		13

#define	MAP_NODE_CAMERA		20 + MAP_TYPE_CBACK
#define	MAP_NODE_COORD		21
#define	MAP_NODE_TRANS		22
#define	MAP_NODE_ROTATE		23
#define	MAP_NODE_SHAPE		24
#define	MAP_NODE_JOINT		25
#define	MAP_NODE_BBOARD		26
#define	MAP_NODE_GFX		27
#define	MAP_NODE_SCALE		28
#define	MAP_NODE_MATRIX		29

#define	MAP_NODE_SHADOW		40
#define	MAP_NODE_BRANCH		41
#define	MAP_NODE_CPROG		42 + MAP_TYPE_CBACK
#define	MAP_NODE_CLEAR		44 + MAP_TYPE_CBACK
#define	MAP_NODE_PRINT		45
#define	MAP_NODE_SUCKER		46 + MAP_TYPE_CBACK
#define	MAP_NODE_HEADER		47


/* flag of node */

#define	MAP_FLAG_ENABLE			(1<<0)
#define	MAP_FLAG_THROUGH		(1<<1)
#define	MAP_FLAG_BBOARD			(1<<2)
#define	MAP_FLAG_ZBUFFER		(1<<3)
#define	MAP_FLAG_HIDESHAPE		(1<<4)
#define	MAP_FLAG_ANIMESW		(1<<5)

/* flag of call back routine */

#define	MAP_CBACK_INIT			0
#define	MAP_CBACK_EXEC			1

#define	MAP_CBACK_INITIAL		0
#define	MAP_CBACK_EXECUTE		1
#define	MAP_CBACK_SUSPEND		2
#define	MAP_CBACK_ACTIVAT		3
#define	MAP_CBACK_ACTIVATE		3
#define	MAP_CBACK_DISPOSE		4
#define	MAP_CBACK_MATRIX		5


/* flag of skeleton animation */

#define	MAP_ANIM_NORMAL			0x00
#define	MAP_ANIM_ONETIME		0x01
#define	MAP_ANIM_REVERSE		0x02
#define	MAP_ANIM_FREEZE			0x04
#define	MAP_ANIM_TRVERTI		0x08
#define	MAP_ANIM_TRPLANE		0x10
#define	MAP_ANIM_FIXSHADOW		0x20
#define	MAP_ANIM_NOTRANS		0x40


#ifndef ASSEMBLER


/*--------------------------------------------------------------------------------
 *	Skeleton animation record
 */
typedef struct {
	short	attr;					/* attribute								*/
	short	hbase;					/* height base								*/
	short	start;					/* start frame number						*/
	short	loop;					/* loop frame number						*/
	short	nframes;				/* number of frames							*/
	short	njoints;				/* number of joiunts						*/
	short	*param;					/* pointer to the parameters				*/
	ushort	*table;					/* pointer to the animation 				*/
	long	size;					/* size of animation data					*/
} AnimeRecord, *AnimePtr;

typedef struct {
	AnimeRecord	*info;
	char		*head;
	char		*tail;
} AnimeList;

typedef struct {
	short		animeID;			/* animation ID								*/
	short		height;				/* shape height								*/
	AnimePtr	anime;				/* pointer to the animation record			*/
	short		frame;				/* animation frame counter (integer)		*/
	ushort		stamp;				/* time stamp								*/
	long		vframe;				/* frame counter for variable speed			*/
	long		vspeed;				/* animation speed							*/
} SkelAnime;

/*-------------------------------------------------------------------------------
 *	Map hierarchy base structures.
 */
typedef struct map_node 	MapNode, MapGroup;
typedef ulong				(*MapCBack)(int code, MapNode *node, void *data);

struct map_node {
	short		type;				/* node type								*/
	short		flags;				/* flags									*/
	MapNode		*prev;				/* pointer to the prev sibling node			*/
	MapNode		*next;				/* pointer to the next sibling node			*/
	MapNode		*parent;			/* pointer to the parent node				*/
	MapNode		*child;				/* pointer to the child node				*/
};

/*-------------------------------------------------------------------------------
 *	Shape information structure.
 */
typedef struct map_actor  ActorRecord, *ActorPtr;

struct map_actor {
	SVector		position;			/* shape initial position					*/
	SVector		angle;				/* shape initial angle						*/
	char		sceneNo;			/* scene number								*/
	char		actorID;			/* actor ID code							*/
	ushort		scale;				/* object scale								*/
	ulong		code;				/* shape discription code					*/
	ulong		*strategy;			/* pointer to the strategy					*/
	MapNode		*shape;				/* pointer to the shape						*/
	ActorRecord	*next;				/* pointer to the next shape				*/
};

/*-------------------------------------------------------------------------------
 *	Display list link structure.
 */

typedef struct displist {
	MtxPtr			matrix;				/* pointer to the RCP matrix			*/
	GfxPtr			gfxlist;			/* pointer to the gfx list				*/
	struct displist	*next;				/* pointer to the next render link		*/
} DispList, *DispPtr;



/*-------------------------------------------------------------------------------
 *	Map hierarchy node structures.
 */

/*
 *	Scene node.
 */
typedef struct {
	MapNode		node;				/* node structure							*/
	uchar		sceneNo;			/* serial number of scene					*/
	uchar		splitID;			/* ID number for splited screen				*/
	short		centerh;			/* center of the view port					*/
	short		centerv;			/* center of the view port					*/
	short		offseth;			/* offset of the view port					*/
	short		offsetv;			/* offset of the view port					*/
	ushort		nstorages;			/* number of the storages					*/
	MapNode		**storage;			/* pointer to the node strage				*/
} MapScene;



/*
 *	Ortho node.
 */
typedef struct {
	MapNode		node;				/* node structure							*/
	float		scale;				/* scale of orthographic					*/
} MapOrtho;



/*
 *	Pers node.
 */
typedef struct {
	MapNode		node;				/* node structure							*/
	MapCBack	callBack;			/* perspective call back routine			*/
	ulong		refCon;
	float		angle;				/* view angle								*/
	short		near;				/* near clipping point						*/
	short		far;				/* far clipping point						*/
} MapPersp;



/*
 *	Layer node.
 */
typedef struct {
	MapNode		node;					/* node structure						*/
	DispPtr		first[NUM_RENDERS];		/* first pointer of the display list	*/ 
	DispPtr		last[NUM_RENDERS];		/* last pointer of the display list		*/
} MapLayer;



/*
 *	Camera node.
 */
typedef struct {
	MapNode		node;				/* node structure							*/
	MapCBack	callBack;			/* camera call back routine					*/
	ulong		refCon;
	FVector		position;			/* camera position							*/
	FVector		lookat;				/* camera look at							*/
	AffineMtx	*matrix;			/* pointer to the affine matrix				*/
	short		bank;				/* bank angle								*/
	short		rotscrn;			/* screen rotation angle					*/
} MapCamera;



/*
 *	LOD node for the level of detail.
 */
typedef struct {
	MapNode		node;				/* node structure							*/
	short		near;				/* display near limit						*/
	short		far;				/* display far limit						*/ 
} MapLOD;




/*
 *	Select node.
 */

typedef struct {
	MapNode		node;				/* node structure							*/
	MapCBack	callBack;			/* pointer to the call back routine			*/
	ulong		refCon;
	short		selid;
	short		selsw;				/* node selector							*/
} MapSelect;




/*
 *	Select node. (information node)
 */

typedef struct {
	MapNode		node;				/* node structure							*/
	SVector		point1;				/* left-bottom-far point					*/
	SVector		point2;				/* right-top-near point						*/
} MapArea;



/*
 *	Gfx node.
 */
typedef struct {
	MapNode		node;				/* node structure							*/
	GfxPtr		gfxlist;			/* pointer to the gfx list (segment addr)	*/
} MapGfx;



/*
 *	Coord node.  (make a matrix)
 */
typedef struct {
	MapNode	 	node;				/* node structure							*/
	GfxPtr		gfxlist;			/* pointer to the gfx list					*/
	SVector		position;			/* vector to the position					*/
	SVector		angle;				/* rotation angle							*/
} MapCoord;



/*
 *	Trans node.  (make a transration matrix)
 */
typedef struct {
	MapNode		node;
	GfxPtr		gfxlist;			/* pointer to the gfx list					*/
	SVector		position;			/* vector to the position					*/
	short		pad;
} MapTrans;



/*
 *	Rotate node.  (make a rotation matrix)
 */
typedef struct {
	MapNode		node;
	GfxPtr		gfxlist;			/* pointer to the gfx list					*/
	SVector		angle;				/* rotation angle							*/
	short		pad;
} MapRotate;



/*
 *	Scale node.
 */
typedef struct {
	MapNode		node;
	GfxPtr		gfxlist;			/* pointer to the gfx list					*/
	float		scaling;
} MapScale;



/*
 *	Matrix node.
 */
typedef struct {
	MapNode		node;
	GfxPtr		gfxlist;			/* pointer to the gfx list					*/
	AffineMtx	matrix;				/* affine matrix							*/
} MapMatrix;



/*
 *	Billboard node.
 */
typedef struct {
	MapNode	 	node;				/* node structure							*/
	GfxPtr		gfxlist;			/* pointer to the gfx list					*/
	SVector		position;			/* vector to the position					*/
	short		pad;
} MapBboard;



/*
 *	Joint node for skeleton animation.
 */
typedef struct {
	MapNode		node;
	GfxPtr		gfxlist;			/* pointer to the gfx list					*/
	SVector		offset;				/* vector to the position					*/
	short		number;
} MapJoint;



/*
 *	Shadow node.
 */
typedef struct {
	MapNode	 	node;				/* node structure							*/
	short		size;				/* size of shadow rectangle					*/
	uchar		level;				/* level of shadow							*/
	uchar		eight;				/* flag for eight height check				*/
} MapShadow;



/*
 *	Branch node.
 */
typedef struct {
	MapNode	 	node;				/* node structure							*/
	MapNode		*subnode;			/* pointer to the sub node structure		*/
} MapBranch;



/*
 *	CProg node.
 */

typedef struct {
	MapNode		node;				/* node structure							*/
	MapCBack	callBack;			/* pointer to the call back routine			*/
	ulong		refCon;
} MapCProg;



/*
 *	Clear node.
 */

typedef struct {
	MapNode		node;
	MapCBack	callBack;			/* pointer to the call back routine			*/
	ulong		refCon;
	ulong		color;
} MapClear;	



/*
 *	String node.
 */

typedef struct {
	MapNode		node;
	uchar		width;				/* character (font) width					*/
	uchar		height;				/* character (font) height					*/
	uchar		length;				/* length of string buffer					*/
	char		string[1];			/* string buffer (variable length)			*/
} MapPrint;



/*
 *	Shape node for the strategy.
 */
typedef struct {
	MapNode		node;				/* node structure							*/
	MapNode		*shape;				/* pointer to the shape header node			*/
	char		sceneNo;			/* scene number								*/
	char		actorID;			/* actor ID code							*/
	SVector		angle;				/* object rotation angle					*/
	FVector		position;			/* object position							*/
	FVector		scale;				/* object scale								*/
	SkelAnime	skelanim;			/* information for the skeleton animation	*/
	ActorPtr	actor;				/* pointer to the actor record				*/
	AffineMtx	*matrix;			/* pointer to the affine matrix				*/
	FVector		viewCoord;			/* view coordinates							*/
} MapShape;



/*
 *	Header node (shape information).
 */
typedef struct {
	MapNode		node;				/* node structure							*/
	short		radius;				/* shape radius								*/
	short		pad;
} MapHeader;



/*
 *	Sucker node for taking.
 */
typedef struct {
	MapNode		node;				/* node structure							*/
	MapCBack	callBack;			/* pointer to the call back routine			*/
	ulong		refCon;
	MapShape	*shape;				/* pointer to the MapShape node				*/
	SVector		offset;				/* vector to the position					*/
	short		pad;
} MapSucker;





/********************************************************************************
 *
 *	Global works
 *
 ********************************************************************************/

extern MapScene  *hmsActiveScene;
extern MapLayer  *hmsActiveLayer;
extern MapPersp  *hmsActivePersp;
extern MapCamera *hmsActiveCamera;
extern MapShape  *hmsActiveShape;
extern MapSucker *hmsActiveSucker;


extern ushort animationCounter;

/********************************************************************************
 *
 *	Function prototypes
 *
 ********************************************************************************/

extern MapGroup strategyGroup;


#define	MapEnable(node)					((MapNode *)(node))->flags |=  MAP_FLAG_ENABLE
#define	MapDisable(node)				((MapNode *)(node))->flags &= ~MAP_FLAG_ENABLE

#define	MapBboardOn(node)				((MapNode *)(node))->flags |=  MAP_FLAG_BBOARD
#define	MapBboardOff(node)				((MapNode *)(node))->flags &= ~MAP_FLAG_BBOARD

#define	MapThroughOn(node)				((MaoNode *)(node))->flags |=  MAP_FLAG_THROUGH
#define	MapThroughOff(node)				((MaoNode *)(node))->flags &= ~MAP_FLAG_THROUGH

#define	MapGetRenderMode(node)			(((MapNode *)(node))->flags >> 8)
#define	MapSetRenderMode(node, mode)	((MapNode *)(node))->flags = ((mode)<<8) | (((MapNode *)(node))->flags & 0xff)

#define	MapHideShape(node)				((MapNode *)(node))->flags |=  MAP_FLAG_HIDESHAPE
#define	MapDispShape(node)				((MapNode *)(node))->flags &= ~MAP_FLAG_HIDESHAPE

#define	MapAnimeEnable(node)			((MapNode *)(node))->flags |=  MAP_FLAG_ANIMESW
#define	MapAnimeDisable(node)			((MapNode *)(node))->flags &= ~MAP_FLAG_ANIMESW

#define	MapIsEnable(node)				((((MapNode *)(node))->flags & MAP_FLAG_ENABLE) != 0)


/*
 *	Map hierarchy node creators.
 */
extern MapScene *
MapNewScene(ArenaPtr arena, MapScene *scene, short sceneNo, short centh, short centv, short ofsh, short ofsv);

extern MapOrtho *
MapNewOrtho(ArenaPtr arena, MapOrtho *ortho, float scale);

extern MapPersp *
MapNewPersp(ArenaPtr arena, MapPersp *persp, float angle, short near, short far, MapCBack proc, long code);

extern MapGroup *
MapNewGroup(ArenaPtr arena, MapGroup *group);

extern MapArea *
MapNewArea(ArenaPtr arena, MapArea *area, SVector point1, SVector point2);

extern MapLayer *
MapNewLayer(ArenaPtr arena, MapLayer *layer, short zbuffer);

extern MapLOD *
MapNewLOD(ArenaPtr arena, MapLOD *lodOp, short near, short far);

extern MapSelect *
MapNewSelect(ArenaPtr arena, MapSelect *select, short selid, short selsw, MapCBack proc, long code);

extern MapCamera *
MapNewCamera(ArenaPtr arena, MapCamera *camera, FVector pos, FVector look, MapCBack proc, long code);

extern MapCoord *
MapNewCoord(ArenaPtr arena, MapCoord *coord, int render, GfxPtr gfxlist, SVector position, SVector angle);

extern MapTrans *
MapNewTrans(ArenaPtr arena, MapTrans *trans, int render, GfxPtr gfxlist, SVector position);

extern MapRotate *
MapNewRotate(ArenaPtr arena, MapRotate *rotate, int render, GfxPtr gfxlist, SVector angle);

extern MapScale *
MapNewScale(ArenaPtr arena, MapScale *scale, int render, GfxPtr gfxlist, float scaling);

extern MapMatrix *
MapNewMatrix(ArenaPtr arena, MapMatrix *matrix, int render, GfxPtr gfxlist, AffineMtx affine);

extern MapShape *
MapNewShape(ArenaPtr arena, MapShape *mapShape, MapNode *shape, FVector position, SVector angle, FVector scale);

extern MapHeader *
MapNewHeader(ArenaPtr arena, MapHeader *mapHeader, short radius);

extern MapJoint *
MapNewJoint(ArenaPtr arena, MapJoint *joint, int render, GfxPtr gfxlist, SVector offset);

extern MapBboard *
MapNewBboard(ArenaPtr arena, MapBboard *board, int render, GfxPtr gfxlist, SVector position);

extern MapGfx *
MapNewGfx(ArenaPtr arena, MapGfx *gfxOp, int render, GfxPtr gfxlist);

extern MapShadow *
MapNewShadow(ArenaPtr arena, MapShadow *shadow, short size, uchar level, uchar eight);

extern MapBranch *
MapNewBranch(ArenaPtr arena, MapBranch *branch, MapNode *node);

extern MapCProg *
MapNewCProg(ArenaPtr arena, MapCProg *cprog, MapCBack proc, long code);

extern MapClear *
MapNewClear(ArenaPtr arena, MapClear *clear, ushort color, MapCBack proc, long code);

extern MapPrint *
MapNewPrint(ArenaPtr arena, MapPrint *print, short width, short height, short length, char *string);

extern MapSucker *
MapNewSucker(ArenaPtr arena, MapSucker *sucker, MapShape *shape, SVector offset, MapCBack proc, long code);


/*
 *	Map hierarcky builder
 */
extern MapNode *
MapAddChild(MapNode *parent, MapNode *child);

extern MapNode *
MapRemoveChild(MapNode *child);

extern MapNode *
MapChangeFirstChild(MapNode *node);

extern void
MapSendMessage(MapScene *scene, int message);


/*
 *	Map hierarchy utilities
 */
extern void
MapInitShape(MapShape *shape);

extern void
MapEnterShape(MapShape *mapShape, MapNode *shape, FVector position, SVector angle);

extern void
MapEnterActor(MapShape *mapShape, ActorPtr actor);

extern void
MapSetAnimation(MapShape *shape, AnimePtr *animation);

extern void
MapSetVariableAnime(MapShape *shape, AnimePtr *animation, long speed);

extern int
MapAnimeIndex(int frame, ushort **table);

extern short
MapNextAnimeFrame(SkelAnime *skelanim, long *vframe);

extern void
MapGetWaistOffset(MapShape *shape, FVector offset);




extern void
DrawScene(MapScene *scene, Vp *viewing, Vp *trimming, ulong blanking);

extern MapScene *
MapGetScenePtr(MapNode *node);

#endif
#endif
