
#include "part.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>


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

//	unsigned long flags;
	_4byte,

//	file_tag collection_reference_tag;
	_4byte,

//	world_distance minimum_view_distance;
//	world_distance transparency_rolloff_point;
//	world_distance transparency_cutoff_point;
	_4byte,
	_4byte,
	_4byte,
	
// short sequence_index;
	_2byte,

//	short number_of_particles;
//	short maximum_particle_number_delta;
	_2byte,
	_2byte,

//	short_fixed scale;
	_2byte,	

//	fixed_vector3d velocity_lower_bound;
//	fixed_vector3d velocity_delta;
	_4byte, _4byte, _4byte,
	_4byte, _4byte, _4byte,
	
//	short_fixed x0_particle_number;
//	short_fixed x1_particle_number; 
//	short_fixed y0_particle_number;
//	short_fixed y1_particle_number; 
	_2byte,
	_2byte,
	_2byte,
	_2byte,

//	struct state_variables state[NUMBER_OF_SNOWING_STATES];

		_begin_bs_array, NUMBER_OF_SNOWING_STATES,

		// short duration_lower_bound, duration_delta;
		// fixed_fraction value_lower_bound, value_delta;
		// short transition_lower_bound, transition_delta;
		_2byte, _2byte,
		_2byte, _2byte,
		_2byte, _2byte,
		
		_end_bs_array,

	// file_tag ambient_sound_tag;
	_4byte,

	// file_tag splash_local_projectile_group_tag;
	_4byte,

	// short box_width;
	// short_world_distance box_top_height;
	// short_world_distance box_bottom_height;
	_2byte,
	_2byte,
	_2byte,
	
	// short max_splashes_per_cell;
	// short time_between_building_effects;
	_2byte,
	_2byte,

//	short unused[8];
	10*sizeof(short),
	
	//------- postprocessed stuff
//	short sprite_definition_index;
//  short ambient_sound_index;
//	short splash_local_projectile_group_type;
	3*sizeof(short),
	
	_end_bs_array
};

particle_system_definition default_part =
{
	0,
	-1,
	0,
	0,
	0,
	0,
	0,
	0,
	0,
	0, 0, 0,
	0, 0, 0,
	0,
	0,
	0,
	0,
	// state variables
	0, 0,
	0, 0,
	0, 0,
	//end state variables
	-1,
	-1,
	0,
	0,
	0,
	0,
	0,
	0, 0, 0, 0, 0, 0, 0, 0,
	0,
	0,
	0,
	0,
	0,
};


// ==============================  EDIT WINDOW  ========================================
void edit_part( tag_entry* e )
{
	TpartEditForm* form = new TpartEditForm( e );
	form->AttachWindow( 1018 );
}

void defaultnew_part( tag_entry *e )
{
	particle_system_definition def;
	byte_swap_move_be( "part", &def, &default_part, sizeof(particle_system_definition), 1, particle_system_byte_swapping_data );
	set_entry_data( e, &def, sizeof(def), false );
}


void dependency_part( tag_entry *e )
{
	particle_system_definition def;
	read_particle_system_definition( &def, e );
	add_tag_dependency( 'spri', def.sprite_tag );
	add_tag_dependency( 'amso', def.ambient_sound_tag );
	add_tag_dependency( 'lpgr', def.splash_local_projectile_group_tag );
}

// ==============================  READ TAG DATA  ========================================
bool read_particle_system_definition( particle_system_definition* def, tag_entry* e )
{
	return load_tag_data_into_struct( "part", e, def, sizeof(particle_system_definition), 1, particle_system_byte_swapping_data);
}


// ==============================  SAVE TAG DATA  ========================================
bool save_particle_system_definition( particle_system_definition* def, tag_entry* e )
{
	return save_tag_data_from_struct( "part", e, def, sizeof(particle_system_definition), 1, particle_system_byte_swapping_data);
}


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


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

	return save_particle_system_definition( def, e );
}


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


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

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

}


// ==============================  INPUT HANDLING  ========================================
long TpartEditForm::DoControlClick( long arg, void *ptr )
{
#ifdef __MWERKS__
	#pragma unused(ptr)
#endif
	tag_entry* e;
	tag new_id;
	
	switch( arg )
	{
		case 11801:	// Choose a tag
			new_id = pick_tag_of_type('spri', GetTag( 11801 ), fEntry );
			if(new_id != 0) SetTag( 11801, 'spri', new_id );
		break; 
		
		case 11802:	// Open tag window
			e = get_entry('spri', GetTag( 11801 ) );
			if(e) TRevengeApp::OpenItem( e );
		break;
		
		case 11805:	// Choose a tag
			new_id = pick_tag_of_type('amso', GetTag( 11805 ), fEntry );
			if(new_id != 0) SetTag( 11805, 'amso', new_id );
		break; 
		
		case 11806:	// Open tag window
			e = get_entry('amso', GetTag( 11805 ) );
			if(e) TRevengeApp::OpenItem( e );
		break;
		
		case 11807:	// Choose a tag
			new_id = pick_tag_of_type('lpgr', GetTag( 11807 ), fEntry );
			if(new_id != 0) SetTag( 11807, 'lpgr', new_id );
		break; 
		
		case 11808:	// Open tag window
			e = get_entry('lpgr', GetTag( 11807 ) );
			if(e) TRevengeApp::OpenItem( e );
		break;
		
		default:
			return -1;
	}
	return 0;
}

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


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


// ========================================  TAG NEEDS UPDATING  ==================================================
bool TpartEditForm::NeedCommit()
{
	GetValues();
	return tag_data_needs_update( "part", fEntry, &def, sizeof(particle_system_definition), 1, particle_system_byte_swapping_data, false);
}

		
// ========================================  SET INTERFACE VALUES  ==================================================
void TpartEditForm::SetValues()
{
	int i;

	SetTag( 11801, 'spri', def.sprite_tag );

	SetTag( 11805, 'amso', def.ambient_sound_tag );
	SetTag( 11807, 'lpgr', def.splash_local_projectile_group_tag );

	SetWorldDistance( 11809, def.minimum_view_distance );
	SetWorldDistance( 11810, def.transparency_rolloff_point );
	SetWorldDistance( 11811, def.transparency_cutoff_point );
	SetInt( 11812, def.number_of_particles );
	SetShortFixed( 11813, def.scale );
	SetShortWorldDistance( 11901, def.box_bottom_height );
	SetShortWorldDistance( 11902, def.box_top_height );

	if(def.flags&_particle_system_states_last_indefinitely_flag ) {
		SetFlag( 11814, TRUE );
	} else {
		SetFlag( 11814, FALSE );
	}
	if(def.flags&_particle_system_does_not_affect_projectiles_flag ) {
		SetFlag( 11815, TRUE );
	} else {
		SetFlag( 11815, FALSE );
	}
	if(def.flags&_particle_system_transparency_varies_with_distance_flag ) {
		SetFlag( 11816, TRUE );
	} else {
		SetFlag( 11816, FALSE );
	}
	if(def.flags&_particle_system_aligns_to_direction_flag ) {
		SetFlag( 11900, TRUE );
	} else {
		SetFlag( 11900, FALSE );
	}

	SetShortFixed (11817, def.y1_particle_number);
	SetShortFixed (11818, def.x1_particle_number);
	SetShortFixed (11819, def.x0_particle_number);
	SetShortFixed (11820, def.y0_particle_number);
	
	SetFixed( 11821, def.velocity_lower_bound.i );
	SetFixed( 11822, def.velocity_lower_bound.i + def.velocity_delta.i );
	SetFixed( 11823, def.velocity_lower_bound.j );
	SetFixed( 11824, def.velocity_lower_bound.j + def.velocity_delta.j );
	SetFixed( 11825, def.velocity_lower_bound.k );
	SetFixed( 11826, def.velocity_lower_bound.k + def.velocity_delta.k );
	
	SetInt( 11827, def.state[_not_snowing].duration_lower_bound / TICKS_PER_SECOND);
	SetInt( 11828, (def.state[_not_snowing].duration_lower_bound + def.state[_not_snowing].duration_delta) / TICKS_PER_SECOND );
	SetPercentage( 11829, def.state[_not_snowing].value_lower_bound );
	SetPercentage( 11830, def.state[_not_snowing].value_lower_bound + def.state[_not_snowing].value_delta );
	SetInt( 11831, def.state[_not_snowing].transition_lower_bound / TICKS_PER_SECOND );
	SetInt( 11832, (def.state[_not_snowing].transition_lower_bound + def.state[_not_snowing].transition_delta) / TICKS_PER_SECOND );

	SetInt( 11833, def.state[_snowing].duration_lower_bound / TICKS_PER_SECOND );
	SetInt( 11834, (def.state[_snowing].duration_lower_bound + def.state[_snowing].duration_delta) / TICKS_PER_SECOND );
	SetPercentage( 11835, def.state[_snowing].value_lower_bound );
	SetPercentage( 11836, def.state[_snowing].value_lower_bound + def.state[_snowing].value_delta );
	SetInt( 11837, def.state[_snowing].transition_lower_bound / TICKS_PER_SECOND );
	SetInt( 11838, (def.state[_snowing].transition_lower_bound + def.state[_snowing].transition_delta) / TICKS_PER_SECOND );

}


// ========================================  GET INTERFACE VALUES  ==================================================
void TpartEditForm::GetValues()
{
	def.sprite_tag = GetTag( 11801 );

	def.ambient_sound_tag = GetTag( 11805 );
	def.splash_local_projectile_group_tag = GetTag( 11807 );

	def.minimum_view_distance = GetWorldDistance( 11809 );
	def.transparency_rolloff_point = GetWorldDistance( 11810 );
	def.transparency_cutoff_point = GetWorldDistance( 11811 );
	def.number_of_particles = GetInt( 11812 );
	def.scale = GetShortFixed( 11813 );
	def.box_bottom_height = GetShortWorldDistance( 11901 );
	def.box_top_height = GetShortWorldDistance( 11902 );

	def.flags = 0;
	if(GetFlag( 11814 )) def.flags |= _particle_system_states_last_indefinitely_flag;
	if(GetFlag( 11815 )) def.flags |= _particle_system_does_not_affect_projectiles_flag;
	if(GetFlag( 11816 )) def.flags |= _particle_system_transparency_varies_with_distance_flag;
	if(GetFlag( 11900 )) def.flags |= _particle_system_aligns_to_direction_flag;

	def.y1_particle_number = GetShortFixed( 11817 );
	def.x1_particle_number = GetShortFixed( 11818 );
	def.x0_particle_number = GetShortFixed( 11819 );
	def.y0_particle_number = GetShortFixed( 11820 );
	
	def.velocity_lower_bound.i = GetFixed( 11821 );
	def.velocity_delta.i = GetFixed( 11822) - def.velocity_lower_bound.i;
	def.velocity_lower_bound.j = GetFixed( 11823 );
	def.velocity_delta.j = GetFixed( 11824 ) - def.velocity_lower_bound.j;
	def.velocity_lower_bound.k = GetFixed( 11825 );
	def.velocity_delta.k = GetFixed( 11826 ) - def.velocity_lower_bound.k;
	
	def.state[_not_snowing].duration_lower_bound = GetInt( 11827 ) * TICKS_PER_SECOND;
	def.state[_not_snowing].duration_delta = (GetInt( 11828 ) * TICKS_PER_SECOND) - def.state[_not_snowing].duration_lower_bound;
	def.state[_not_snowing].value_lower_bound = GetPercentage( 11829 );
	def.state[_not_snowing].value_delta = GetPercentage( 11830 ) - def.state[_not_snowing].value_lower_bound;
	def.state[_not_snowing].transition_lower_bound = GetInt( 11831 ) * TICKS_PER_SECOND;
	def.state[_not_snowing].transition_delta = (GetInt( 11832 ) * TICKS_PER_SECOND) - def.state[_not_snowing].transition_lower_bound;

	def.state[_snowing].duration_lower_bound = GetInt( 11833 ) * TICKS_PER_SECOND;
	def.state[_snowing].duration_delta = (GetInt( 11834 ) * TICKS_PER_SECOND) - def.state[_snowing].duration_lower_bound;
	def.state[_snowing].value_lower_bound = GetPercentage( 11835 );
	def.state[_snowing].value_delta = GetPercentage( 11836 ) - def.state[_snowing].value_lower_bound;
	def.state[_snowing].transition_lower_bound = GetInt( 11837 ) * TICKS_PER_SECOND;
	def.state[_snowing].transition_delta = (GetInt( 11838 ) * TICKS_PER_SECOND) - def.state[_snowing].transition_lower_bound;
}

