// phys.h
#ifndef __phys_h__
#define __phys_h__

#ifndef __tags_h__
#include "tags.h"
#endif

#ifndef __BYTE_SWAPPING_H__
#include "byte_swapping.h"
#endif

#ifndef __ttageditform_h__
#include "TTagEditForm.h"
#endif

#ifndef __myth_defs_h__
#include "myth_defs.h"
#endif

/* ---------- constants */

enum
{
	LOCAL_PHYSICS_DEFINITION_GROUP_TAG= 0x70687973, // 'phys' (looks like text)
	LOCAL_PHYSICS_DEFINITION_VERSION_NUMBER= 1,

	MAXIMUM_LOCAL_PHYSICS_DEFINITIONS_PER_MAP= 128
};

/* ---------- definition */

enum // linear physics flags
{
	_linear_projectiles_originate_within_bounds_bit,
	_linear_projectiles_respect_group_yaw_bit,
	NUMBER_OF_LINEAR_PHYSICS_DEFINITION_FLAGS,
	
	_linear_projectiles_originate_within_bounds_flag= FLAG(_linear_projectiles_originate_within_bounds_bit),
	_linear_projectiles_respect_group_yaw_flag= FLAG(_linear_projectiles_respect_group_yaw_bit)
};

enum // spherical_spring physics flags
{
	_spherical_spring_random_time_offsets_bit,
	NUMBER_OF_SPHERICAL_SPRING_PHYSICS_DEFINITION_FLAGS,
	
	_spherical_spring_random_time_offsets_flag= FLAG(_spherical_spring_random_time_offsets_bit)
};

enum // point_attractor physics flags
{
	_point_attractor_maintain_minimum_height_above_mesh_bit,
	NUMBER_OF_POINT_ATTRACTOR_PHYSICS_DEFINITION_FLAGS,
	
	_point_attractor_maintain_minimum_height_above_mesh_flag= FLAG(_point_attractor_maintain_minimum_height_above_mesh_bit)
};

enum // converging physics flags
{
	_converging_particles_diverge_bit,
	NUMBER_OF_CONVERGING_PHYSICS_DEFINITION_FLAGS,
	
	_converging_particles_diverge_flag= FLAG(_converging_particles_diverge_bit)
};

enum {
	_linear,
	_cylindrical,
	_spherical_spring,
	_point_attractor,
	_converging,
	_explosive_gas
};

/* ---------- definitions */

enum {
	SIZEOF_STRUCT_LOCAL_PHYSICS_DEFINITION= 64,
	SIZEOF_PHYSICS_BUFFER= 30 // 60 bytes
};

struct linear_physics_definition
{
	unsigned long flags;	

	fixed_vector3d linear_acceleration;
	fixed_vector3d initial_linear_velocity_min, initial_linear_velocity_delta;
	fixed_vector3d random_acceleration;

	short unused[4];
};

struct cylindrical_physics_definition
{
	unsigned long flags;	

	angle angular_acceleration;
	angle initial_angular_velocity_min, initial_angular_velocity_delta;
	short_world_distance initial_z_deviation;
	fixed attraction_constant;	
	fixed radial_velocity;

	fixed z_acceleration;

	short unused[18];
};

struct spherical_spring_physics_definition
{
	unsigned long flags;

	angle initial_angular_velocity_min, initial_angular_velocity_delta;
	fixed attraction_constant;	

	short unused[24];
};

struct converging_physics_definition
{
	unsigned long flags;

	angle initial_angular_velocity_min, initial_angular_velocity_delta;
	angle phi_min, phi_delta;

	short unused[24];
};

struct point_attractor_physics_definition
{
	unsigned long flags;

	fixed maximum_velocity;
	fixed radial_velocity;
	fixed attraction_constant;	
	short_world_distance minimum_height_above_mesh;
	
	short unused[21];
};

struct explosive_gas_physics_definition
{
	unsigned long flags;
	fixed starting_velocity_min, starting_velocity_delta;
	fixed radial_acceleration;
	fixed_vector3d linear_acceleration;
	short_fixed drag;
	
	short unused[15];
};

struct local_physics_definition
{
	short type; // type of physics model to use
	word pad;
	
	union 
	{
		linear_physics_definition linear;
		cylindrical_physics_definition cylindrical;
		spherical_spring_physics_definition spherical;
		point_attractor_physics_definition attractor;
		converging_physics_definition converging;
		explosive_gas_physics_definition explosive_gas;
	};
};



//=====================================================================================================
bool read_local_physics_definition( local_physics_definition* def, tag id );
bool save_local_physics_definition( local_physics_definition* def, tag id );

bool read_local_physics_definition( local_physics_definition* def, tag_entry* e );
bool save_local_physics_definition( local_physics_definition* def, tag_entry* e );

class TphysEditForm: public TTagEditForm {
	public:
							TphysEditForm( struct tag_entry *e );
				
		DECLAREDISPATCH
		virtual long		DoControlClick( long arg, void *ptr );
		
		virtual void		CommitToTag();
		virtual void		ReloadTag();
		virtual bool		NeedCommit();
		virtual void		DoFormInitialize();
		
	protected:
		void				SetValues();
		void				GetValues();
		local_physics_definition	def;
};


#endif