/*
 * ***** BEGIN GPL LICENSE BLOCK *****
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
 * All rights reserved.
 *
 * The Original Code is: all of this file.
 *
 * Contributor(s): none yet.
 *
 * ***** END GPL LICENSE BLOCK *****
 */

/** \file KX_GameObject.h
 *  \ingroup ketsji
 *  \brief General KX game object.
 */

#ifndef __KX_GAMEOBJECT_H__
#define __KX_GAMEOBJECT_H__

#ifdef _MSC_VER
   /* get rid of this stupid "warning 'this' used in initialiser list", generated by VC when including Solid/Sumo */
#  pragma warning (disable:4355)
#endif 

#include <stddef.h>

#include "ListValue.h"
#include "SCA_IObject.h"
#include "SG_Node.h"
#include "MT_Transform.h"
#include "MT_CmMatrix4x4.h"
#include "CTR_Map.h"
#include "CTR_HashedPtr.h"
#include "KX_Scene.h"
#include "KX_KetsjiEngine.h" /* for m_anim_framerate */
#include "KX_IPhysicsController.h" /* for suspend/resume */
#include "DNA_object_types.h"
#include "SCA_LogicManager.h" /* for ConvertPythonToGameObject to search object names */
#define KX_OB_DYNAMIC 1

//Forward declarations.
struct KX_ClientObjectInfo;
class KX_RayCast;
class RAS_MeshObject;
class KX_IPhysicsController;
class PHY_IGraphicController;
class PHY_IPhysicsEnvironment;
class BL_ActionManager;
struct Object;
class KX_ObstacleSimulation;
struct bAction;

#ifdef WITH_PYTHON
/* utility conversion function */
bool ConvertPythonToGameObject(PyObject *value, KX_GameObject **object, bool py_none_ok, const char *error_prefix);
#endif

#ifdef USE_MATHUTILS
void KX_GameObject_Mathutils_Callback_Init(void);
#endif

/**
 * KX_GameObject is the main class for dynamic objects.
 */
class KX_GameObject : public SCA_IObject
{
	Py_Header
protected:

	bool								m_bDyna;
	KX_ClientObjectInfo*				m_pClient_info;
	STR_String							m_name;
	STR_String							m_text;
	int									m_layer;
	std::vector<RAS_MeshObject*>		m_meshes;
	SG_QList							m_meshSlots;	// head of mesh slots of this 
	struct Object*						m_pBlenderObject;
	struct Object*						m_pBlenderGroupObject;
	
	bool								m_bSuspendDynamics;
	bool								m_bUseObjectColor;
	bool								m_bIsNegativeScaling;
	MT_Vector4							m_objectColor;

	// Bit fields for user control over physics collisions
	short								m_userCollisionGroup;
	short								m_userCollisionMask;

	// visible = user setting
	// culled = while rendering, depending on camera
	bool       							m_bVisible; 
	bool       							m_bCulled; 
	bool								m_bOccluder;

	KX_IPhysicsController*				m_pPhysicsController1;
	PHY_IGraphicController*				m_pGraphicController;
	STR_String							m_testPropName;
	bool								m_xray;
	KX_GameObject*						m_pHitObject;

	SG_Node*							m_pSGNode;

	MT_CmMatrix4x4						m_OpenGL_4x4Matrix;

	KX_ObstacleSimulation*				m_pObstacleSimulation;

	CListValue*							m_pInstanceObjects;
	KX_GameObject*						m_pDupliGroupObject;

	// The action manager is used to play/stop/update actions
	BL_ActionManager*					m_actionManager;

	BL_ActionManager* GetActionManager();
	
public:
	bool								m_isDeformable;

	/**
	 * Helper function for modules that can't include KX_ClientObjectInfo.h
	 */
	static KX_GameObject* GetClientObject(KX_ClientObjectInfo* info);

#ifdef WITH_PYTHON
	// Python attributes that wont convert into CValue
	// 
	// there are 2 places attributes can be stored, in the CValue,
	// where attributes are converted into BGE's CValue types
	// these can be used with property actuators
	//
	// For the python API, For types that cannot be converted into CValues (lists, dicts, GameObjects)
	// these will be put into "m_attr_dict", logic bricks cannot access them.
	// 
	// rules for setting attributes.
	// 
	// * there should NEVER be a CValue and a m_attr_dict attribute with matching names. get/sets make sure of this.
	// * if CValue conversion fails, use a PyObject in "m_attr_dict"
	// * when assigning a value, first see if it can be a CValue, if it can remove the "m_attr_dict" and set the CValue
	// 
	PyObject*							m_attr_dict; 
#endif

	virtual void	/* This function should be virtual - derived classed override it */
	Relink(
		CTR_Map<CTR_HashedPtr, void*> *map
	);

	/**
	 * Compute an OpenGl compatible 4x4 matrix. Has the
	 * side effect of storing the result internally. The
	 * memory for the matrix remains the property of this class.
	 */ 
		double *
	GetOpenGLMatrix(
	);

	/**
	 * Return a pointer to a MT_CmMatrix4x4 storing the 
	 * opengl transformation for this object. This is updated
	 * by a call to GetOpenGLMatrix(). This class owns the 
	 * memory for the returned matrix.
	 */

		MT_CmMatrix4x4 *
	GetOpenGLMatrixPtr(
	) { 
		return &m_OpenGL_4x4Matrix;
	};

	/**
	 * Update the blender object obmat field from the object world position
	 * if blendobj is NULL, update the object pointed by m_pBlenderObject
	 * The user must take action to restore the matrix before leaving the GE.
	 * Used in Armature evaluation
	 */
		void
	UpdateBlenderObjectMatrix(Object* blendobj=NULL);

	/** 
	 * Get a pointer to the game object that is the parent of 
	 * this object. Or NULL if there is no parent. The returned
	 * object is part of a reference counting scheme. Calling
	 * this function ups the reference count on the returned 
	 * object. It is the responsibility of the caller to decrement
	 * the reference count when you have finished with it.
	 */
		KX_GameObject*
	GetParent(
	);

	/** 
	 * Sets the parent of this object to a game object
	 */
	void SetParent(KX_Scene *scene, KX_GameObject *obj, bool addToCompound=true, bool ghost=true);

	/** 
	 * Removes the parent of this object to a game object
	 */
	void RemoveParent(KX_Scene *scene);

	/*********************************
	 * group reference API
	 *********************************/

		KX_GameObject*
	GetDupliGroupObject(
	);

		CListValue*
	GetInstanceObjects(
	);

		void
	SetDupliGroupObject(KX_GameObject*
	);

		void
	AddInstanceObjects(KX_GameObject*
	);
		
		void 
	RemoveDupliGroupObject(
	);

		void
	RemoveInstanceObject(KX_GameObject*
	);
	/*********************************
	 * Animation API
	 *********************************/

	/**
	 * Adds an action to the object's action manager
	 */
	bool PlayAction(const char* name,
					float start,
					float end,
					short layer=0,
					short priority=0,
					float blendin=0.f,
					short play_mode=0,
					float layer_weight=0.f,
					short ipo_flags=0,
					float playback_speed=1.f);

	/**
	 * Gets the current frame of an action
	 */
	float GetActionFrame(short layer);

	/**
	 * Sets the current frame of an action
	 */
	void SetActionFrame(short layer, float frame);

	/**
	 * Gets the currently running action on the given layer
	 */
	bAction *GetCurrentAction(short layer);

	/**
	 * Sets play mode of the action on the given layer
	 */
	void SetPlayMode(short layer, short mode);

	/**
	 * Sets the start and end times of the action on the given layer
	 */
	void SetTimes(short layer, float start, float end);

	/**
	 * Stop playing the action on the given layer
	 */
	void StopAction(short layer);

	/**
	 * Check if an action has finished playing
	 */
	bool IsActionDone(short layer);

	/**
	 * Kick the object's action manager
	 */
	void UpdateActionManager(float curtime);

	/*********************************
	 * End Animation API
	 *********************************/

	/**
	 * Construct a game object. This class also inherits the 
	 * default constructors - use those with care!
	 */

	KX_GameObject(
		void* sgReplicationInfo,
		SG_Callbacks callbacks
	);

	virtual 
	~KX_GameObject(
	);

	/** 
	 * \section Stuff which is here due to poor design.
	 * Inherited from CValue and needs an implementation. 
	 * Do not expect these functions do to anything sensible.
	 */

	/**
	 * Inherited from CValue -- does nothing!
	 */
		CValue*
	Calc(
		VALUE_OPERATOR op,
		CValue *val
	);

	/**
	 * Inherited from CValue -- does nothing!
	 */
		CValue*
	CalcFinal(
		VALUE_DATA_TYPE dtype,
		VALUE_OPERATOR op,
		CValue *val
	);

	/**
	 * Inherited from CValue -- does nothing!
	 */
	const 
		STR_String &
	GetText(
	);

	/**
	 * Inherited from CValue -- does nothing!
	 */
		double
	GetNumber(
	);

	/**
	 * \section Inherited from CValue. These are the useful
	 * part of the CValue interface that this class implements. 
	 */

	/**
	 * Inherited from CValue -- returns the name of this object.
	 */
		STR_String&
	GetName(
	);

	/**
	 * Inherited from CValue -- set the name of this object.
	 */
		void
	SetName(
		const char *name
	);

	/** 
	 * Inherited from CValue -- return a new copy of this
	 * instance allocated on the heap. Ownership of the new 
	 * object belongs with the caller.
	 */
	virtual	CValue*
	GetReplica(
	);
	
	/**
	 * Inherited from CValue -- Makes sure any internal 
	 * data owned by this class is deep copied. Called internally
	 */
	virtual	void
	ProcessReplica();

	/** 
	 * Return the linear velocity of the game object.
	 */
		MT_Vector3 
	GetLinearVelocity(
		bool local=false
	);

	/** 
	 * Return the linear velocity of a given point in world coordinate
	 * but relative to center of object ([0,0,0]=center of object)
	 */
		MT_Vector3 
	GetVelocity(
		const MT_Point3& position
	);

	/**
	 * Return the mass of the object
	 */
		MT_Scalar
	GetMass();

	/**
	 * Return the local inertia vector of the object
	 */
		MT_Vector3
	GetLocalInertia();

	/** 
	 * Return the angular velocity of the game object.
	 */
		MT_Vector3 
	GetAngularVelocity(
		bool local=false
	);

	/** 
	 * Align the object to a given normal.
	 */
		void 
	AlignAxisToVect(
		const MT_Vector3& vect,
		int axis = 2,
		float fac = 1.0
	);

	/** 
	 * Quick'n'dirty obcolor ipo stuff
	 */

		void
	SetObjectColor(
		const MT_Vector4& rgbavec
	);

		const MT_Vector4&
	GetObjectColor();


		void 
	ResolveCombinedVelocities(
		const MT_Vector3 & lin_vel,
		const MT_Vector3 & ang_vel,
		bool lin_vel_local,
		bool ang_vel_local
	);

	/**
	 * \return a pointer to the physics controller owned by this class.
	 */

	KX_IPhysicsController* GetPhysicsController();

	void	SetPhysicsController(KX_IPhysicsController*	physicscontroller,bool isDynamic) 
	{ 
		m_bDyna = isDynamic;
		m_pPhysicsController1 = physicscontroller;
	}

	virtual class RAS_Deformer* GetDeformer()
	{
		return 0;
	}
	virtual void	SetDeformer(class RAS_Deformer* deformer)
	{

	}

	/**
	 * \return a pointer to the graphic controller owner by this class 
	 */
	PHY_IGraphicController* GetGraphicController()
	{
		return m_pGraphicController;
	}

	void SetGraphicController(PHY_IGraphicController* graphiccontroller) 
	{ 
		m_pGraphicController = graphiccontroller;
	}
	/*
	 * @add/remove the graphic controller to the physic system
	 */
	void ActivateGraphicController(bool recurse);

	void SetUserCollisionGroup(short filter);
	void SetUserCollisionMask(short mask);
	/**
	 * Extra broadphase check for user controllable collisions
	 */
	bool CheckCollision(KX_GameObject *other);

	/**
	 * \section Coordinate system manipulation functions
	 */

	void	NodeSetLocalPosition(const MT_Point3& trans	);

	void	NodeSetLocalOrientation(const MT_Matrix3x3& rot	);
	void	NodeSetGlobalOrientation(const MT_Matrix3x3& rot	);

	void	NodeSetLocalScale(	const MT_Vector3& scale	);
	void	NodeSetWorldScale(	const MT_Vector3& scale );

	void	NodeSetRelativeScale(	const MT_Vector3& scale	);

	// adapt local position so that world position is set to desired position
	void	NodeSetWorldPosition(const MT_Point3& trans);

		void
	NodeUpdateGS(
		double time
	);

	const MT_Matrix3x3& NodeGetWorldOrientation(  ) const;
	const MT_Vector3& NodeGetWorldScaling(  ) const;
	const MT_Point3& NodeGetWorldPosition(  ) const;

	const MT_Matrix3x3& NodeGetLocalOrientation(  ) const;
	const MT_Vector3& NodeGetLocalScaling(  ) const;
	const MT_Point3& NodeGetLocalPosition(  ) const;

	/**
	 * \section scene graph node accessor functions.
	 */

	SG_Node*	GetSGNode(	) 
	{ 
		return m_pSGNode;
	}

	const 	SG_Node* GetSGNode(	) const
	{ 
		return m_pSGNode;
	}

	/**
	 * \section blender object accessor functions.
	 */

	struct Object* GetBlenderObject( )
	{
		return m_pBlenderObject;
	}

	void SetBlenderObject(struct Object* obj)
	{
		m_pBlenderObject = obj;
	}

	struct Object* GetBlenderGroupObject( )
	{
		return m_pBlenderGroupObject;
	}

	void SetBlenderGroupObject(struct Object* obj)
	{
		m_pBlenderGroupObject = obj;
	}
	
	bool IsDupliGroup()
	{ 
		return (m_pBlenderObject &&
				(m_pBlenderObject->transflag & OB_DUPLIGROUP) &&
				m_pBlenderObject->dup_group != NULL) ? true : false;
	}

	/**
	 * Set the Scene graph node for this game object.
	 * warning - it is your responsibility to make sure
	 * all controllers look at this new node. You must
	 * also take care of the memory associated with the
	 * old node. This class takes ownership of the new
	 * node.
	 */
		void	SetSGNode(SG_Node* node	)
		{ 
			m_pSGNode = node; 
		}
	
	//Is it a dynamic/physics object ?
	bool	IsDynamic() const 
	{ 
		return m_bDyna; 
	}

	/**
	 * Check if this object has a vertex parent relationship
	 */
	bool IsVertexParent( )
	{
		return (m_pSGNode && m_pSGNode->GetSGParent() && m_pSGNode->GetSGParent()->IsVertexParent());
	}

	bool RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data);
	bool NeedRayCast(KX_ClientObjectInfo* client);


	/**
	 * \section Physics accessors for this node.
	 *
	 * All these calls get passed directly to the physics controller 
	 * owned by this object.
	 * This is real interface bloat. Why not just use the physics controller
	 * directly? I think this is because the python interface is in the wrong
	 * place.
	 */

		void
	ApplyForce(
		const MT_Vector3& force,	bool local
	);

		void
	ApplyTorque(
		const MT_Vector3& torque,
		bool local
	);

		void
	ApplyRotation(
		const MT_Vector3& drot,
		bool local
	);

		void
	ApplyMovement(
		const MT_Vector3& dloc,
		bool local
	);

		void
	addLinearVelocity(
		const MT_Vector3& lin_vel,
		bool local
	);

		void
	setLinearVelocity(
		const MT_Vector3& lin_vel,
		bool local
	);

		void
	setAngularVelocity(
		const MT_Vector3& ang_vel,
		bool local
	);

	/**
	 * Update the physics object transform based upon the current SG_Node
	 * position.
	 */
		void
	UpdateTransform(
	);

	static void UpdateTransformFunc(SG_IObject* node, void* gameobj, void* scene);

	/**
	 * only used for sensor objects
	 */
	void SynchronizeTransform();

	static void SynchronizeTransformFunc(SG_IObject* node, void* gameobj, void* scene);

	/**
	 * Function to set IPO option at start of IPO
	 */ 
		void
	InitIPO(
		bool ipo_as_force,
		bool ipo_add,
		bool ipo_local
	);

	/**
	 * Odd function to update an ipo. ???
	 */ 
		void
	UpdateIPO(
		float curframetime,
		bool recurse
	);
	/**
	 * Updates Material Ipo data 
	 */
		void 
	UpdateMaterialData(
		dword matname_hash,
		MT_Vector4 rgba,
		MT_Vector3 specrgb,
		MT_Scalar hard,
		MT_Scalar spec,
		MT_Scalar ref,
		MT_Scalar emit,
		MT_Scalar alpha
	);

	/**
	 * \section Mesh accessor functions.
	 */

	/**
	 * Update buckets to indicate that there is a new
	 * user of this object's meshes.
	 */
		void
	AddMeshUser(
	);
	
	/**
	 * Update buckets with data about the mesh after
	 * creating or duplicating the object, changing
	 * visibility, object color, .. .
	 */
		void
	UpdateBuckets(
		bool recursive
	);

	/**
	 * Clear the meshes associated with this class
	 * and remove from the bucketing system.
	 * Don't think this actually deletes any of the meshes.
	 */
		void
	RemoveMeshes(
	);

	/**
	 * Add a mesh to the set of meshes associated with this
	 * node. Meshes added in this way are not deleted by this class.
	 * Make sure you call RemoveMeshes() before deleting the
	 * mesh though,
	 */
		void
	AddMesh(
		RAS_MeshObject* mesh
	) {
		m_meshes.push_back(mesh);
	}

	/**
	 * Pick out a mesh associated with the integer 'num'.
	 */
		RAS_MeshObject*
	GetMesh(
		int num
	) const { 
		return m_meshes[num]; 
	}

	/**
	 * Return the number of meshes currently associated with this
	 * game object.
	 */
		int
	GetMeshCount(
	) const { 
		return m_meshes.size(); 
	}
	
	/**
	 * Set the debug color of the meshes associated with this
	 * class. Does this still work?
	 */
		void
	SetDebugColor(
		unsigned int bgra
	);

	/** 
	 * Reset the debug color of meshes associated with this class.
	 */
		void
	ResetDebugColor(
	);

	/**
	 * Was this object marked visible? (only for the explicit
	 * visibility system).
	 */
		bool
	GetVisible(
		void
	);

	/**
	 * Set visibility flag of this object
	 */
		void
	SetVisible(
		bool b,
		bool recursive
	);

	/**
	 * Was this object culled?
	 */
	inline bool
	GetCulled(
		void
	) { return m_bCulled; }

	/**
	 * Set culled flag of this object
	 */
	inline void
	SetCulled(
		bool c
	) { m_bCulled = c; }
	
	/**
	 * Is this object an occluder?
	 */
	inline bool
	GetOccluder(
		void
	) { return m_bOccluder; }

	/**
	 * Set occluder flag of this object
	 */
	void
	SetOccluder(
		bool v,
		bool recursive
	);
	
	/**
	 * Change the layer of the object (when it is added in another layer
	 * than the original layer)
	 */
		void
	SetLayer(
		int l
	);

	/**
	 * Get the object layer
	 */
		int
	GetLayer(
		void
	);
		
	/**
	 * Get the negative scaling state
	 */
		bool
	IsNegativeScaling(
		void
	) { return m_bIsNegativeScaling; }

	/**
	 * \section Logic bubbling methods.
	 */

	/**
	 * Stop making progress
	 */
	void Suspend(void);

	/**
	 * Resume making progress
	 */
	void Resume(void);
	
	void SuspendDynamics(void) {
		if (m_bSuspendDynamics)
		{
			return;
		}
	
		if (m_pPhysicsController1)
		{
			m_pPhysicsController1->SuspendDynamics();
		}
		m_bSuspendDynamics = true;
	}
	
	void RestoreDynamics(void) {
		if (!m_bSuspendDynamics)
		{
			return;
		}
	
		if (m_pPhysicsController1)
		{
			m_pPhysicsController1->RestoreDynamics();
		}
		m_bSuspendDynamics = false;
	}

	void RegisterObstacle(KX_ObstacleSimulation* obstacleSimulation)
	{
		m_pObstacleSimulation = obstacleSimulation;
	}

	void UnregisterObstacle()
	{
		m_pObstacleSimulation = NULL;
	}
	
	KX_ClientObjectInfo* getClientInfo() { return m_pClient_info; }
	
	CListValue* GetChildren();
	CListValue* GetChildrenRecursive();

	KX_Scene*	GetScene();

#ifdef WITH_PYTHON
	/**
	 * \section Python interface functions.
	 */
	virtual PyObject *py_repr(void)
	{
		return PyUnicode_From_STR_String(GetName());
	}

	KX_PYMETHOD_O(KX_GameObject,SetWorldPosition);
	KX_PYMETHOD_VARARGS(KX_GameObject, ApplyForce);
	KX_PYMETHOD_VARARGS(KX_GameObject, ApplyTorque);
	KX_PYMETHOD_VARARGS(KX_GameObject, ApplyRotation);
	KX_PYMETHOD_VARARGS(KX_GameObject, ApplyMovement);
	KX_PYMETHOD_VARARGS(KX_GameObject,GetLinearVelocity);
	KX_PYMETHOD_VARARGS(KX_GameObject,SetLinearVelocity);
	KX_PYMETHOD_VARARGS(KX_GameObject,GetAngularVelocity);
	KX_PYMETHOD_VARARGS(KX_GameObject,SetAngularVelocity);
	KX_PYMETHOD_VARARGS(KX_GameObject,GetVelocity);

	KX_PYMETHOD_NOARGS(KX_GameObject,GetReactionForce);


	KX_PYMETHOD_NOARGS(KX_GameObject,GetVisible);
	KX_PYMETHOD_VARARGS(KX_GameObject,SetVisible);
	KX_PYMETHOD_VARARGS(KX_GameObject,SetOcclusion);
	KX_PYMETHOD_NOARGS(KX_GameObject,GetState);
	KX_PYMETHOD_O(KX_GameObject,SetState);
	KX_PYMETHOD_VARARGS(KX_GameObject,AlignAxisToVect);
	KX_PYMETHOD_O(KX_GameObject,GetAxisVect);
	KX_PYMETHOD_NOARGS(KX_GameObject,SuspendDynamics);
	KX_PYMETHOD_NOARGS(KX_GameObject,RestoreDynamics);
	KX_PYMETHOD_NOARGS(KX_GameObject,EnableRigidBody);
	KX_PYMETHOD_NOARGS(KX_GameObject,DisableRigidBody);
	KX_PYMETHOD_VARARGS(KX_GameObject,ApplyImpulse);
	KX_PYMETHOD_O(KX_GameObject,SetCollisionMargin);
	KX_PYMETHOD_NOARGS(KX_GameObject,GetParent);
	KX_PYMETHOD_VARARGS(KX_GameObject,SetParent);
	KX_PYMETHOD_NOARGS(KX_GameObject,RemoveParent);
	KX_PYMETHOD_NOARGS(KX_GameObject,GetChildren);
	KX_PYMETHOD_NOARGS(KX_GameObject,GetChildrenRecursive);
	KX_PYMETHOD_VARARGS(KX_GameObject,GetMesh);
	KX_PYMETHOD_NOARGS(KX_GameObject,GetPhysicsId);
	KX_PYMETHOD_NOARGS(KX_GameObject,GetPropertyNames);
	KX_PYMETHOD_VARARGS(KX_GameObject,ReplaceMesh);
	KX_PYMETHOD_NOARGS(KX_GameObject,EndObject);
	KX_PYMETHOD_DOC(KX_GameObject,rayCastTo);
	KX_PYMETHOD_DOC(KX_GameObject,rayCast);
	KX_PYMETHOD_DOC_O(KX_GameObject,getDistanceTo);
	KX_PYMETHOD_DOC_O(KX_GameObject,getVectTo);
	KX_PYMETHOD_DOC_VARARGS(KX_GameObject, sendMessage);
	KX_PYMETHOD_VARARGS(KX_GameObject, ReinstancePhysicsMesh);

	KX_PYMETHOD_DOC(KX_GameObject, playAction);
	KX_PYMETHOD_DOC(KX_GameObject, stopAction);
	KX_PYMETHOD_DOC(KX_GameObject, getActionFrame);
	KX_PYMETHOD_DOC(KX_GameObject, setActionFrame);
	KX_PYMETHOD_DOC(KX_GameObject, isPlayingAction);
	
	/* Dict access */
	KX_PYMETHOD_VARARGS(KX_GameObject,get);
	
	/* attributes */
	static PyObject*	pyattr_get_name(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
	static PyObject*	pyattr_get_parent(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);

	static PyObject*	pyattr_get_group_object(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
	static PyObject*	pyattr_get_group_members(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
	static PyObject*	pyattr_get_scene(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);

	static PyObject*	pyattr_get_life(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
	static PyObject*	pyattr_get_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
	static int			pyattr_set_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
	static PyObject*	pyattr_get_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
	static int			pyattr_set_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
	static PyObject*	pyattr_get_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
	static int			pyattr_set_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
	static PyObject*	pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
	static int			pyattr_set_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
	static PyObject*	pyattr_get_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
	static int			pyattr_set_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
	static PyObject*	pyattr_get_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
	static int			pyattr_set_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
	static PyObject*	pyattr_get_localInertia(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
	static int			pyattr_set_localInertia(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
	static PyObject*	pyattr_get_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
	static int			pyattr_set_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
	static PyObject*	pyattr_get_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
	static int			pyattr_set_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
	static PyObject*	pyattr_get_worldScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
	static int			pyattr_set_worldScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
	static PyObject*	pyattr_get_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
	static int			pyattr_set_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
	static PyObject*	pyattr_get_localTransform(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
	static int			pyattr_set_localTransform(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
	static PyObject*	pyattr_get_worldTransform(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
	static int			pyattr_set_worldTransform(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
	static PyObject*	pyattr_get_worldLinearVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
	static int			pyattr_set_worldLinearVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
	static PyObject*	pyattr_get_localLinearVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
	static int			pyattr_set_localLinearVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
	static PyObject*	pyattr_get_worldAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
	static int			pyattr_set_worldAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
	static PyObject*	pyattr_get_localAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
	static int			pyattr_set_localAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
	static PyObject*	pyattr_get_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
	static int			pyattr_set_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
	static PyObject*	pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
	static int			pyattr_set_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
	static PyObject*	pyattr_get_meshes(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
	static PyObject*	pyattr_get_children(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
	static PyObject*	pyattr_get_children_recursive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
	static PyObject*	pyattr_get_attrDict(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
	static PyObject*	pyattr_get_obcolor(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef);
	static int			pyattr_set_obcolor(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
	
	/* Experimental! */
	static PyObject*	pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
	static PyObject*	pyattr_get_controllers(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
	static PyObject*	pyattr_get_actuators(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
	
	/* getitem/setitem */
	static PyMappingMethods	Mapping;
	static PySequenceMethods	Sequence;
#endif
};



#endif  /* __KX_GAMEOBJECT_H__ */
