
#include "phys.h"

#ifndef PandaWave_RESOURCES
#include "RevengeResources.h"
#endif

#include "RevengeApp.h"
#include <XMessages.h>
#include "tagpick.h"
#include <assert.h>
#include <XPopup.h>
#include <XWindow.h>
#include <XDialog.h>
#include "formatters.h"

// FIXME: move to myth_defs.h
#define ANGLE_TO_FLOAT(a) (((float)(a))/(float)FULL_CIRCLE*360)
#define FLOAT_TO_ANGLE(f) (angle)(((f)/360.0)*FULL_CIRCLE)

// ==============================  BYTE SWAPPING DATA  ========================================
static byte_swap_code physics_definition_byte_swapping_data[]=
{
	_begin_bs_array, 1,

	// short type; // type of physics model to use
	// word pad;
	_2byte,
	sizeof(short),
	
	// short buffer[SIZEOF_PHYSICS_BUFFER];
	SIZEOF_PHYSICS_BUFFER*sizeof(short),
	
	_end_bs_array
};

static byte_swap_code linear_physics_definition_byte_swapping_data[]=
{
	_begin_bs_array, 1,

	//unsigned long flags;
	_4byte,
	
	// fixed_vector3d linear_acceleration;
	_4byte,	_4byte,	_4byte,
	// fixed_vector3d initial_linear_velocity_min, initial_linear_velocity_delta;
	_4byte,	_4byte,	_4byte,
	_4byte,	_4byte,	_4byte,
	
	// fixed_vector3d random_acceleration;
	_4byte,	_4byte,	_4byte,

	// short unused[4];
	4*sizeof(short),
	
	_end_bs_array
};

static byte_swap_code cylindrical_physics_definition_byte_swapping_data[]=
{
	_begin_bs_array, 1,

	//unsigned long flags;
	_4byte,
	
	// angle angular_acceleration;
	// angle initial_angular_velocity_min, initial_angular_velocity_delta;
	_2byte,
	_2byte, _2byte,

	// short_world_distance initial_z_deviation;
	_2byte,

	// fixed attraction_constant;	
	// fixed radial_velocity;
	_4byte,
	_4byte,

	// fixed z_acceleration;
	_4byte,
	
	// short unused[18];
	18*sizeof(short),
	
	_end_bs_array
};

static byte_swap_code spherical_spring_physics_definition_byte_swapping_data[]=
{
	_begin_bs_array, 1,

	//unsigned long flags;
	_4byte,
	
	// angle initial_angular_velocity_min, initial_angular_velocity_delta;
	_2byte, _2byte,

	// fixed attraction_constant;
	_4byte,

	// short unused[24];
	24*sizeof(short),
	
	_end_bs_array
};

static byte_swap_code point_attractor_physics_definition_byte_swapping_data[]=
{
	_begin_bs_array, 1,

	//unsigned long flags;
	_4byte,

	// fixed maximum_velocity;
	// fixed radial_velocity;
	// fixed attraction_constant;	
	_4byte,
	_4byte,	
	_4byte,	

	// short_world_distance minimum_height_above_mesh;
	_2byte,

	// short unused[21];
	21*sizeof(short),
	
	_end_bs_array
};

static byte_swap_code converging_physics_definition_byte_swapping_data[]=
{
	_begin_bs_array, 1,

	//unsigned long flags;
	_4byte,
	
	// angle initial_angular_velocity_min, initial_angular_velocity_delta;
	_2byte, _2byte,

	// angle phi_min, phi_delta;
	_2byte, _2byte,

	// short unused[24];
	24*sizeof(short),
	
	_end_bs_array
};

static byte_swap_code explosive_gas_physics_definition_byte_swapping_data[]=
{
	_begin_bs_array, 1,
	
	//unsigned long flags;
	_4byte,
	
	//fixed starting_velocity_min, starting_velocity_delta;
	_4byte, _4byte,
	
	//fixed radial_acceleration;
	_4byte,
	
	//fixed_vector3d linear_acceleration;
	_4byte, _4byte, _4byte,
	
	//fixed_fraction drag;
	_2byte,
	
	//short unused[15];
	15 * sizeof(short),
	
	_end_bs_array
};


static long LinearDlogProc( XGDialog *dlog, void *data, long msg, long arg, void *parg )
{
	linear_physics_definition *linear = (linear_physics_definition *)data;
	int ii;
	
	switch( msg )
	{
		case KXGDialogMessage:
		{
			switch( arg )
			{
				case KXGDMInitDialog:
				{
					// linear
					SetFixed( dlog, 101, linear->linear_acceleration.i );
					SetFixed( dlog, 102, linear->linear_acceleration.j );
					SetFixed( dlog, 103, linear->linear_acceleration.k );
					SetFixed( dlog, 104, linear->random_acceleration.i );
					SetFixed( dlog, 105, linear->random_acceleration.j );
					SetFixed( dlog, 106, linear->random_acceleration.k );
					SetFixed( dlog, 107, linear->initial_linear_velocity_min.i );
					SetFixed( dlog, 108, get_upper_bound( linear->initial_linear_velocity_min.i, linear->initial_linear_velocity_delta.i ) );
					SetFixed( dlog, 109, linear->initial_linear_velocity_min.j );
					SetFixed( dlog, 110, get_upper_bound( linear->initial_linear_velocity_min.j, linear->initial_linear_velocity_delta.j ) );
					SetFixed( dlog, 111, linear->initial_linear_velocity_min.k );
					SetFixed( dlog, 112, get_upper_bound( linear->initial_linear_velocity_min.k, linear->initial_linear_velocity_delta.k ) );

					for( ii = 201; ii < 203; ii++ )
					{
						dlog->SetValue( ii, (bool)(linear->flags & (1 << (ii - 201) )) );
					}
					
					return 0;
				}
				
				default:
					break;
			}
		}
		case KXGControlClick:
		{
			switch( arg )
			{
				case 1001: // ok
				{
					linear->linear_acceleration.i = GetFixed( dlog, 101 );
					linear->linear_acceleration.j = GetFixed( dlog, 102 );
					linear->linear_acceleration.k = GetFixed( dlog, 103 );
					linear->random_acceleration.i = GetFixed( dlog, 104 );
					linear->random_acceleration.j = GetFixed( dlog, 105 );
					linear->random_acceleration.k = GetFixed( dlog, 106 );
					linear->initial_linear_velocity_min.i = GetFixed( dlog, 107 );
					linear->initial_linear_velocity_delta.i = get_delta( GetFixed( dlog, 107 ), GetFixed( dlog, 108 ) );
					linear->initial_linear_velocity_min.j = GetFixed( dlog, 109 );
					linear->initial_linear_velocity_delta.j = get_delta( GetFixed( dlog, 109 ), GetFixed( dlog, 110 ) );
					linear->initial_linear_velocity_min.k = GetFixed( dlog, 111 );
					linear->initial_linear_velocity_delta.k = get_delta( GetFixed( dlog, 111 ), GetFixed( dlog, 112 ) );

					for( ii = 201; ii < 203; ii++ )
					{
						(dlog->GetValue( ii )) ? linear->flags |= (1 << (ii - 201)) : linear->flags &= ~(1 << (ii - 201));
					}
					
					dlog->EndDialog( 1 );
					return 0;
				}
				case 1002: // cancel
				{
					dlog->EndDialog( 0 );
					return 0;
				}
				
				case 201:
				case 202: // flags
				{
					dlog->SetValue( arg, !dlog->GetValue( arg ) );
					return 0;
				}
				
				default:
					break;
			}
		}
		
		default:
			break;
	}
	
	return -1;
}

static long CylindricalDlogProc( XGDialog *dlog, void *data, long msg, long arg, void *parg )
{
	cylindrical_physics_definition *cylindrical = (cylindrical_physics_definition *)data;
	
	switch( msg )
	{
		case KXGDialogMessage:
		{
			switch( arg )
			{
				case KXGDMInitDialog:
				{
					SetInt( dlog, 101, cylindrical->angular_acceleration );
					SetInt( dlog, 102, cylindrical->initial_angular_velocity_min );
					SetInt( dlog, 103, get_upper_bound( cylindrical->initial_angular_velocity_min, cylindrical->initial_angular_velocity_delta ) );
					SetWorldDistance( dlog, 104, cylindrical->initial_z_deviation );
					SetFixed( dlog, 105, cylindrical->attraction_constant );
					SetFixed( dlog, 106, cylindrical->radial_velocity );
					SetFixed( dlog, 107, cylindrical->z_acceleration );
					return 0;
				}
				
				default:
					break;
			}
		}
		case KXGControlClick:
		{
			switch( arg )
			{
				case 1001: // ok
				{
					cylindrical->angular_acceleration = GetInt( dlog, 101 );
					cylindrical->initial_angular_velocity_min = GetInt( dlog, 102 );
					cylindrical->initial_angular_velocity_delta = get_delta( (long)GetInt( dlog, 102 ), (long)GetInt( dlog, 103 ) );
					cylindrical->initial_z_deviation = GetWorldDistance( dlog, 104 );
					cylindrical->attraction_constant = GetFixed( dlog, 105 );						
					cylindrical->radial_velocity = GetFixed( dlog, 106 );						
					cylindrical->z_acceleration = GetFixed( dlog, 107 );						
					
					dlog->EndDialog( 1 );
					return 0;
				}
				case 1002: // cancel
				{
					dlog->EndDialog( 0 );
					return 0;
				}
				
				default:
					break;
			}
		}
		
		default:
			break;
	}
	
	return -1;
}

static long SphericalSpringDlogProc( XGDialog *dlog, void *data, long msg, long arg, void *parg )
{
	spherical_spring_physics_definition *spherical = (spherical_spring_physics_definition *)data;
	int ii;
	
	switch( msg )
	{
		case KXGDialogMessage:
		{
			switch( arg )
			{
				case KXGDMInitDialog:
				{
					SetInt( dlog, 101, spherical->initial_angular_velocity_min );
					SetInt( dlog, 102, get_upper_bound( spherical->initial_angular_velocity_min, spherical->initial_angular_velocity_delta ) );
					SetFixed( dlog, 103, spherical->attraction_constant );
					
					// flags
					for( ii = 201; ii < 202; ii++ )
					{
						dlog->SetValue( ii, (bool)(spherical->flags & (1 << (ii - 201) )) );
					}
					
					return 0;
				}
				
				default:
					break;
			}
		}
		case KXGControlClick:
		{
			switch( arg )
			{
				case 1001: // ok
				{
					spherical->initial_angular_velocity_min = GetInt( dlog, 101 );
					spherical->initial_angular_velocity_delta = get_delta( (long)GetInt( dlog, 101 ), (long)GetInt( dlog, 102 ) );
					spherical->attraction_constant = GetFixed( dlog, 103 );					

					for( ii = 201; ii < 202; ii++ )
					{
						(dlog->GetValue( ii )) ? spherical->flags |= (1 << (ii - 201)) : spherical->flags &= ~(1 << (ii - 201));
					}
					
					dlog->EndDialog( 1 );
					return 0;
				}
				case 1002: // cancel
				{
					dlog->EndDialog( 0 );
					return 0;
				}
				
				case 201: // flags
				{
					dlog->SetValue( arg, !dlog->GetValue( arg ) );
					return 0;
				}
				
				default:
					break;
			}
		}
		
		default:
			break;
	}
	
	return -1;
}

static long PointAttractorDlogProc( XGDialog *dlog, void *data, long msg, long arg, void *parg )
{
	point_attractor_physics_definition *attractor = (point_attractor_physics_definition *)data;
	int ii;
	
	switch( msg )
	{
		case KXGDialogMessage:
		{
			switch( arg )
			{
				case KXGDMInitDialog:
				{
					SetFixed( dlog, 101, attractor->maximum_velocity );
					SetFixed( dlog, 102, attractor->radial_velocity );
					SetFixed( dlog, 103, attractor->attraction_constant );
					SetShortWorldDistance( dlog, 104, attractor->minimum_height_above_mesh );
					
					for( ii = 201; ii < 202; ii++ )
					{
						dlog->SetValue( ii, (bool)(attractor->flags & (1 << (ii - 201) )) );
					}
					
					return 0;
				}
				
				default:
					break;
			}
		}
		case KXGControlClick:
		{
			switch( arg )
			{
				case 1001: // ok
				{
					attractor->maximum_velocity = GetFixed( dlog, 101 );
					attractor->radial_velocity = GetFixed( dlog, 102 );
					attractor->attraction_constant = GetFixed( dlog, 103 );
					attractor->minimum_height_above_mesh = GetShortWorldDistance( dlog, 103 );

					for( ii = 201; ii < 202; ii++ )
					{
						(dlog->GetValue( ii )) ? attractor->flags |= (1 << (ii - 201)) : attractor->flags &= ~(1 << (ii - 201));
					}
					
					dlog->EndDialog( 1 );
					return 0;
				}
				case 1002: // cancel
				{
					dlog->EndDialog( 0 );
					return 0;
				}
				
				case 201: // flags
				{
					dlog->SetValue( arg, !dlog->GetValue( arg ) );
					return 0;
				}
				
				default:
					break;
			}
		}
		
		default:
			break;
	}
	
	return -1;
}

static long ConvergingDlogProc( XGDialog *dlog, void *data, long msg, long arg, void *parg )
{
	converging_physics_definition *converging = (converging_physics_definition *)data;
	int ii;
	
	switch( msg )
	{
		case KXGDialogMessage:
		{
			switch( arg )
			{
				case KXGDMInitDialog:
				{
					SetInt( dlog, 101, converging->initial_angular_velocity_min );
					SetInt( dlog, 102, get_upper_bound( converging->initial_angular_velocity_min, converging->initial_angular_velocity_delta ) );
					SetAngle( dlog, 103, converging->phi_min );
//					SetFloat( dlog, 103, incremental_round( angle_to_float( converging->phi_min ), 1.0 );
					SetAngle( dlog, 104, converging->phi_delta );
//					SetFloat( dlog, 104, incremental_round( angle_to_float( converging->phi_delta ), 1.0 );

					for( ii = 201; ii < 202; ii++ )
					{
						dlog->SetValue( ii, (bool)(converging->flags & (1 << (ii - 201) )) );
					}
					
					return 0;
				}
				
				default:
					break;
			}
		}
		case KXGControlClick:
		{
			switch( arg )
			{
				case 1001: // ok
				{
					converging->initial_angular_velocity_min = GetInt( dlog, 101 );
					converging->initial_angular_velocity_delta = get_delta( (long)GetInt( dlog, 101 ), (long)GetInt( dlog, 102 ) );
					converging->phi_min = GetAngle( dlog, 103 );
					converging->phi_delta = GetAngle( dlog, 104 );

					for( ii = 201; ii < 202; ii++ )
					{
						(dlog->GetValue( ii )) ? converging->flags |= (1 << (ii - 201)) : converging->flags &= ~(1 << (ii - 201));
					}
					
					dlog->EndDialog( 1 );
					return 0;
				}
				case 1002: // cancel
				{
					dlog->EndDialog( 0 );
					return 0;
				}
				
				case 201: // flags
				{
					dlog->SetValue( arg, !dlog->GetValue( arg ) );
					return 0;
				}
				
				default:
					break;
			}
		}
		
		default:
			break;
	}
	
	return -1;
}


static long ExplosiveGasDlogProc( XGDialog *dlog, void *data, long msg, long arg, void *parg )
{
	explosive_gas_physics_definition *eg = (explosive_gas_physics_definition *)data;
	int ii;
	
	switch( msg )
	{
		case KXGDialogMessage:
		{
			switch( arg )
			{
				case KXGDMInitDialog:
				{
					SetWorldDistance( dlog, 101, eg->starting_velocity_min );
					SetWorldDistance( dlog, 102, get_upper_bound( eg->starting_velocity_min, eg->starting_velocity_delta ) );
					SetWorldDistance( dlog, 103, eg->linear_acceleration.i );
					SetWorldDistance( dlog, 104, eg->linear_acceleration.j );
					SetWorldDistance( dlog, 105, eg->linear_acceleration.k );
					SetWorldDistance( dlog, 106, eg->radial_acceleration );
					SetShortFixed( dlog, 107, eg->drag );
					
					return 0;
				}
				
				default:
					break;
			}
		}
		case KXGControlClick:
		{
			switch( arg )
			{
				case 1001: // ok
				{
					eg->starting_velocity_min = GetWorldDistance( dlog, 101 );
					eg->starting_velocity_delta = get_delta( GetWorldDistance( dlog, 101 ), GetWorldDistance( dlog, 102 ) );
					eg->linear_acceleration.i = GetWorldDistance( dlog, 103 );
					eg->linear_acceleration.j = GetWorldDistance( dlog, 104 );
					eg->linear_acceleration.k = GetWorldDistance( dlog, 105 );
					eg->radial_acceleration = GetWorldDistance( dlog, 106 );
					eg->drag = GetShortFixed( dlog, 107 );
					
					dlog->EndDialog( 1 );
					return 0;
				}
				case 1002: // cancel
				{
					dlog->EndDialog( 0 );
					return 0;
				}
				
				default:
					break;
			}
		}
		
		default:
			break;
	}
	
	return -1;
}




// ==============================  EDIT WINDOW  ========================================
void edit_phys( tag_entry* e )
{
	TphysEditForm* form = new TphysEditForm( e );
	form->AttachWindow( 1008 );
}

void dependency_phys( tag_entry *e )
{
#if 0 // no dependencies
	local_physics_definition def;
	read_local_physics_definition( &def, e );
#endif	// no dependencies
}


// ==============================  READ TAG DATA  ========================================
bool read_local_physics_definition( local_physics_definition* def, tag_entry* e )
{
	if( load_tag_data_into_struct( "phys", e, def, sizeof(local_physics_definition), 1, physics_definition_byte_swapping_data ) )
	{
		switch( def->type )
		{
			case _linear:
				byte_swap_data_be( "linear physics", &def->linear, sizeof(linear_physics_definition), 1, linear_physics_definition_byte_swapping_data );
				break;
				
			case _cylindrical:
				byte_swap_data_be( "cylindrical physics", &def->cylindrical, sizeof(cylindrical_physics_definition), 1, cylindrical_physics_definition_byte_swapping_data );
				break;
				
			case _spherical_spring:
				byte_swap_data_be( "spherical sptring physics", &def->spherical, sizeof(spherical_spring_physics_definition), 1, spherical_spring_physics_definition_byte_swapping_data );
				break;
				
			case _point_attractor:
				byte_swap_data_be( "point attractor physics", &def->attractor, sizeof(point_attractor_physics_definition), 1, point_attractor_physics_definition_byte_swapping_data );
				break;
				
			case _converging:
				byte_swap_data_be( "converging physics", &def->converging, sizeof(converging_physics_definition), 1, converging_physics_definition_byte_swapping_data );
				break;
				
			case _explosive_gas:
				byte_swap_data_be( "explosive gas physics", &def->converging, sizeof(explosive_gas_physics_definition), 1, explosive_gas_physics_definition_byte_swapping_data );
				break;
				
			default:
				return FALSE;
		}
	
		return TRUE;
	}
	return FALSE;
}

local_physics_definition default_phys =
{
	0,
	0,
	{ 0 }
};

void defaultnew_phys( tag_entry *e )
{
	local_physics_definition def;
	byte_swap_move_be( "phys", &def, &default_phys, sizeof(local_physics_definition), 1, physics_definition_byte_swapping_data );
	set_entry_data( e, &def, sizeof(def), false );
}


// ==============================  SAVE TAG DATA  ========================================
bool save_local_physics_definition( local_physics_definition* def, tag_entry* e )
{
	local_physics_definition *physics = (local_physics_definition *)malloc( sizeof(local_physics_definition) );
	
	byte_swap_move_be( "phys", physics, def, sizeof(local_physics_definition), 1, physics_definition_byte_swapping_data );
	switch( def->type )
	{
		case _linear:
			byte_swap_data_be( "linear physics", &physics->linear, sizeof(linear_physics_definition), 1, linear_physics_definition_byte_swapping_data );
			break;
			
		case _cylindrical:
			byte_swap_data_be( "cylindrical physics", &physics->cylindrical, sizeof(cylindrical_physics_definition), 1, cylindrical_physics_definition_byte_swapping_data );
			break;
			
		case _spherical_spring:
			byte_swap_data_be( "spherical sptring physics", &physics->spherical, sizeof(spherical_spring_physics_definition), 1, spherical_spring_physics_definition_byte_swapping_data );
			break;
			
		case _point_attractor:
			byte_swap_data_be( "point attractor physics", &physics->attractor, sizeof(point_attractor_physics_definition), 1, point_attractor_physics_definition_byte_swapping_data );
			break;
			
		case _converging:
			byte_swap_data_be( "converging physics", &physics->converging, sizeof(converging_physics_definition), 1, converging_physics_definition_byte_swapping_data );
			break;
			
		case _explosive_gas:
			byte_swap_data_be( "explosive gas physics", &physics->explosive_gas, sizeof(explosive_gas_physics_definition), 1, explosive_gas_physics_definition_byte_swapping_data );
			break;
			
		default:
			free( physics );
			return FALSE;
		
	}
	
	set_entry_data( e, physics, sizeof(local_physics_definition), TRUE );
	return TRUE;
}


// ==============================  READ TAG DATA (WITH ID) ========================================
bool read_local_physics_definition( local_physics_definition* def, tag id )
{
	tag_entry* e;
	
	assert( def );
	
	e = get_entry( 'phys', id );
	if( 0 == e ) {
		return FALSE;
	}
	
	return read_local_physics_definition( def, e );	
}


// ==============================  SAVE TAG DATA (WITH ID) ========================================
bool save_local_physics_definition( local_physics_definition* def, tag id )
{
	tag_entry* e;
	
	assert( def );
	
	e = get_entry( 'phys', id );
	if( 0 == e ) {
		return FALSE;
	}

	return save_local_physics_definition( def, e );
}


// ==============================  DISPATCH  ========================================
BEGINDISPATCH(TphysEditForm,TTagEditForm)
	DISPATCHTABLE(KXGControlClick,TphysEditForm::DoControlClick)
ENDDISPATCH


TphysEditForm::TphysEditForm( struct tag_entry *e ) : TTagEditForm( e )
{
}

// ==============================  INITIALIZE FORM =======================================
void TphysEditForm::DoFormInitialize()
{
	TTagEditForm::DoFormInitialize();

}


// ==============================  INPUT HANDLING  ========================================
long TphysEditForm::DoControlClick( long arg, void *ptr )
{
#ifdef __MWERKS__
	#pragma unused(ptr)
#endif

//	tag_entry* e;
	bool ok;

	switch( arg )
	{
		case 20802:	// Open Physics Type Window
			switch( def.type )
			{
				case 0:
					linear_physics_definition linear = def.linear;
					
					ok = XGDialog::ModalDialog( KWindowPhysicsLinear, LinearDlogProc, &linear );
					if( ok )
						def.linear = linear;
					
					break;
					
				case 1:
					cylindrical_physics_definition cylindrical = def.cylindrical;
					
					ok = XGDialog::ModalDialog( KWindowPhysicsCylindrical, CylindricalDlogProc, &cylindrical );
					if( ok )
						def.cylindrical = cylindrical;
						
					break;
					
				case 2:
					spherical_spring_physics_definition spherical = def.spherical;

					ok = XGDialog::ModalDialog( KWindowPhysicsSphericalSpring, SphericalSpringDlogProc, &spherical );
					if( ok )
						def.spherical = spherical;
						
					break;
					
				case 3:
					converging_physics_definition converging = def.converging;

					ok = XGDialog::ModalDialog( KWindowPhysicsPointAttractor, PointAttractorDlogProc, &converging );
					if( ok )
						def.converging = converging;
						
					break;
					
				case 4:
					point_attractor_physics_definition attractor = def.attractor;
					
					ok = XGDialog::ModalDialog( KWindowPhysicsConverging, ConvergingDlogProc, &attractor );
					if( ok )
						def.attractor = attractor;
						
					break;
				
				case 5:
					explosive_gas_physics_definition explosive_gas = def.explosive_gas;
					
					ok = XGDialog::ModalDialog( KWindowPhysicsExplosiveGas, ExplosiveGasDlogProc, &explosive_gas );
					if( ok )
						def.explosive_gas = explosive_gas;
						
					break;
				
				default:
					assert( 0 );
			}
			
		break;
		
		default:
			return -1;
	}

	return 0;
}

		
// ========================================  SAVE TO TAG  ==================================================
void TphysEditForm::CommitToTag()
{
	GetValues();
	save_local_physics_definition( &def, fEntry );
}


// ========================================  RELOAD TAG  ==================================================
void TphysEditForm::ReloadTag()
{
	read_local_physics_definition( &def, fEntry );
	SetValues();
}


// ========================================  TAG NEEDS UPDATING  ==================================================
bool TphysEditForm::NeedCommit()
{
	local_physics_definition original;
	int ret_val;
	
	GetValues();
	read_local_physics_definition( &original, fEntry );

	if( original.type != def.type )
		return TRUE;

	switch( def.type )
	{
		case 0:
			ret_val = memcmp( &def.linear, &original.linear, sizeof(linear_physics_definition) );
			break;
		
		case 1:
			ret_val = memcmp( &def.cylindrical, &original.cylindrical, sizeof(cylindrical_physics_definition) );
			break;
			
		case 2:
			ret_val = memcmp( &def.spherical, &original.spherical, sizeof(spherical_spring_physics_definition) );
			break;
			
		case 3:
			ret_val = memcmp( &def.attractor, &original.attractor, sizeof(point_attractor_physics_definition) );
			break;
			
		case 4:
			ret_val = memcmp( &def.converging, &original.converging, sizeof(converging_physics_definition) );
			break;
		
		case 5:
			ret_val = memcmp( &def.explosive_gas, &original.explosive_gas, sizeof(explosive_gas_physics_definition) );
			break;
		
		default:
			assert( 0 );
	}
	
	if( ret_val )
		return TRUE;
		
	return FALSE;
}

		
// ========================================  SET INTERFACE VALUES  ==================================================
void TphysEditForm::SetValues()
{
	XGPopControl* pList;
	
	pList = dynamic_cast<XGPopControl*>(GetWindow()->FindViewByID( 20801 ));
	assert(pList);
	pList->DeleteAll();
	pList->Insert(0, "Linear");
	pList->Insert(1, "Cylindrical");
	pList->Insert(2, "Spherical Spring");
	pList->Insert(3, "Point Attractor");
	pList->Insert(4, "Converging");
	pList->Insert(5, "Jay's Explosive Gas");
	pList->SetValue( def.type );

}


// ========================================  GET INTERFACE VALUES  ==================================================
void TphysEditForm::GetValues()
{
	XGPopControl* pList;

	pList = dynamic_cast<XGPopControl*>(GetWindow()->FindViewByID( 20801 ));
	assert(pList);
	def.type = pList->GetValue();
}

