/////////////////////////////////////////////////////////////
// CINEMA 4D SDK                                           //
/////////////////////////////////////////////////////////////
// (c) 1989-2004 MAXON Computer GmbH, all rights reserved  //
/////////////////////////////////////////////////////////////

#ifndef __C4DBASETAG_H
#define __C4DBASETAG_H

#include "c4d_baselist.h"
#include "operatingsystem.h"
#include "ge_vector.h"

class BaseObject;
class BaseSelect;
class GvNodeMaster;

#define TAG_VISIBLE								(1<<0)
#define TAG_MULTIPLE							(1<<1)
#define TAG_HIERARCHICAL					(1<<2)
#define TAG_EXPRESSION						(1<<3)
#define TAG_TEMPORARY							(1<<4)

class BaseTag : public BaseList2D
{
	private:
		BaseTag();
		~BaseTag();
	public:
		BaseObject *GetObject(void) { return (BaseObject*)AtCall(GetMain)(); }

		BaseTag *GetNext(void) { return (BaseTag*)AtCall(GetNext)(); }
		BaseTag *GetPred(void) { return (BaseTag*)AtCall(GetPred)(); }

		BaseTag *GetOrigin();

		static BaseTag *Alloc(LONG type);
		static void Free(BaseTag *&bl);
};

class PluginTag : public BaseTag
{
	private:
		PluginTag();
		~PluginTag();
	public:
		static PluginTag *Alloc(LONG type);
		static void Free(PluginTag *&key);
};

class VariableTag : public BaseTag
{
	private:
		VariableTag();
		~VariableTag();
	public:
		LONG 				GetDataCount	(void);
		LONG 				GetDataSize		(void);
		const void*	GetDataAddressR(void);
		void*				GetDataAddressW(void);

		static VariableTag *Alloc(LONG type, LONG count);
		static void Free(VariableTag *&bl);
};

class SelectionTag : public BaseTag
{
	private:
		SelectionTag();
		~SelectionTag();
	public:
		BaseSelect *GetBaseSelect(void);

		static SelectionTag *Alloc(LONG type);
		static void Free(SelectionTag *&bl);
};

struct UVWStruct
{
	UVWStruct(_DONTCONSTRUCT dc) : a(DC), b(DC), c(DC), d(DC) { }

	UVWStruct(void) {}
	UVWStruct(const Vector &t_a, const Vector &t_b, const Vector &t_c, const Vector &t_d) { a=t_a; b=t_b; c=t_c; d=t_d; }
	UVWStruct(const Vector &t_a, const Vector &t_b, const Vector &t_c) { a=t_a; b=t_b; c=t_c; }

	Vector a,b,c,d;
};

class UVWTag : public VariableTag
{
	private:
		UVWTag();
		~UVWTag();
	public:
		UVWStruct Get(LONG i) { UVWStruct us; C4DOS.Tg->UvGet(this,i,&us); return us; }
		void Set(LONG i, const UVWStruct &s) { C4DOS.Tg->UvSet(this,i,(UVWStruct*) &s); }
		void Cpy(LONG dst, UVWTag *srctag, LONG src) { C4DOS.Tg->UvCpy(this,dst,srctag,src); }

		static UVWTag *Alloc(LONG count);
		static void Free(UVWTag *&bl);
};

class TextureTag : public BaseTag
{
	private:
		TextureTag();
		~TextureTag();
	public:
		Vector GetPos(void);
		Vector GetScale(void);
		Vector GetRot(void);
		Matrix GetMl(void);
		Matrix GetMln(void);
		void SetPos(const Vector &v);
		void SetScale(const Vector &v);
		void SetRot(const Vector &v);
		void SetMl(const Matrix &m);

		BaseMaterial *GetMaterial(Bool ignoredoc=FALSE);
		void SetMaterial(BaseMaterial *mat);

		static TextureTag *Alloc();
		static void Free(TextureTag *&bl);
};

class StickTextureTag : public VariableTag
{
	private:
		StickTextureTag();
		~StickTextureTag();
	public:
		Bool Record(BaseObject *op, Bool always);

		static StickTextureTag *Alloc(LONG type);
		static void Free(StickTextureTag *&bl);
};

class XPressoTag : public BaseTag
{
	private:
		XPressoTag();
		~XPressoTag();
	public:
		GvNodeMaster *GetNodeMaster(void);

		static XPressoTag *Alloc();
		static void Free(XPressoTag *&bl);
};

struct PolyWeight
{
  Real a, b, c, d; // weights of the edges, (for triangles a, b and d contain vaild data)
};

struct HNData
{
  LONG *points, *polys;
  Real **pointweight;
  PolyWeight **polyweight;
  Bool *changed;
};

struct HNSubdiv
{
  PolygonObject* op; // the polygonobject that is to be subdivided
  Real lod; // level of detail
  LONG subdiv; // subdivision level of op
};

class HNWeightTag : public PluginTag
{
  private:
    HNWeightTag();
    ~HNWeightTag();
  public:
    Bool GetTagData(HNData* data); // fills the members of this class

		static HNWeightTag *Alloc();
		static void Free(HNWeightTag *&bl);
};

#define BAKEPARTICLETAG_FROM						1001 // LONG
#define BAKEPARTICLETAG_TO							1002 // LONG
#define BAKEPARTICLETAG_STEP						1003 // LONG
#define BAKEPARTICLETAG_IGNORE					1004 // BOOL

#endif
