
#include "mesh.h"

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

#include "RevengeApp.h"
#include <XMessages.h>
#include "tagpick.h"
#include "markers.h"
#include <assert.h>


// ==============================  BYTE SWAPPING DATA  ========================================
byte_swap_code mesh_definition_byte_swapping_data[]=
{
	_begin_bs_array, 1,
	
	// file_tag landscape_collection_tag; // .256 tag for color and shadow maps
	// file_tag media_collection_tag;
	_4byte, _4byte,
	
	// short submesh_width, submesh_height;
	// long mesh_offset, mesh_size;
	// void *mesh;
	_2byte, _2byte,
	_4byte, _4byte,
	sizeof(void *),

	// long data_offset, data_size;
	// void *data;
	_4byte, _4byte,
	sizeof(void *),
	
	// long model_count, models_offset, models_size;
	// void *models; // new_model_data structures which reference 'mode' tags
	_4byte, _4byte, _4byte,
	sizeof(void *),
	
	// long marker_count, markers_offset, markers_size; // array of marker_data structures
	// void *markers; // combined with marker list in scenario_header
	_4byte, _4byte, _4byte,
	sizeof(void *),
	
	// file_tag mesh_lighting_tag; // shadow intensity, ambient light, etc.
	// file_tag connector_tag;
	_4byte,
	_4byte,
	
	// unsigned long flags;
	_4byte,
	
	// file_tag particle_system_tag;
	_4byte,

	// teams may be played by any number of players	
	// long team_count;
	_4byte,

	// short_fixed dark_fraction;
	// short_fixed light_fraction;
	_2byte,
	_2byte,
	// struct rgb_color dark_color;
	// struct rgb_color light_color;
	_2byte, _2byte, _2byte, _2byte,
	_2byte, _2byte, _2byte, _2byte,
	// fixed transition_point;
	_4byte,

	// short_world_distance ceiling_height;
	_2byte,
	// short unused1;
	sizeof(short),

	// rectangle2d edge_of_mesh_buffer_zones;
	_2byte, _2byte, _2byte, _2byte,

	// file_tag global_ambient_sound_tag;
	_4byte,

	// long map_action_count, map_actions_offset, map_action_buffer_size;
	_4byte, _4byte, _4byte,

	// file_tag map_description_string_list_tag;
	// file_tag postgame_collection_tag;
	// file_tag pregame_collection_tag;
	// file_tag overhead_map_collection_tag;
	_4byte,
	_4byte,
	_4byte,
	_4byte,
	// file_tag next_mesh_tags[NUMBER_OF_NEXT_MESH_TAGS];
	// file_tag cutscene_movie_tags[NUMBER_OF_CUTSCENE_MOVIE_TAGS];
	// file_tag storyline_string_tags[NUMBER_OF_STORYLINE_STRING_TAGS];
	_begin_bs_array, NUMBER_OF_NEXT_MESH_TAGS, _4byte, _end_bs_array,
	_begin_bs_array, NUMBER_OF_CUTSCENE_MOVIE_TAGS, _4byte, _end_bs_array,
	_begin_bs_array, NUMBER_OF_STORYLINE_STRING_TAGS, _4byte, _end_bs_array,

	// long media_coverage_region_offset, media_coverage_region_size;
	// short *media_coverage_region;
	_4byte, _4byte,
	sizeof(short *),
	
	// long mesh_LOD_data_offset, mesh_LOD_data_size;
	// byte *mesh_LOD_data;
	_4byte, _4byte,
	sizeof(word *),

	// struct rgb_color global_tint_color;
	// short_fixed global_tint_fraction;
	_2byte, _2byte, _2byte, _2byte,
	_2byte,
	// word pad;
	sizeof(short),

 	// file_tag wind_tag;
	_4byte,

	// file_tag screen_collection_tags[NUMBER_OF_SCREEN_COLLECTION_TAGS];
	_begin_bs_array, NUMBER_OF_SCREEN_COLLECTION_TAGS, _4byte, _end_bs_array,
	
	// struct rgb_color blood_color;
	_2byte, _2byte, _2byte, _2byte,

	// file_tag picture_caption_string_list_tag;
	// file_tag narration_sound_tag;
	// file_tag win_ambient_sound_tag;
	// file_tag loss_ambient_sound_tag;
	_4byte,
	_4byte,
	_4byte,
	_4byte,

	// For Creative's Environmental Audio Extensions
	// unsigned long reverb_environment;
	// float reverb_volume;
	// float reverb_decay_time;
	// float reverb_damping;
	_4byte,
	_4byte,
	_4byte,
	_4byte,

	// long connector_count, connectors_offset, connectors_size; // array of connectors (i.e. fences)
	// struct saved_connector_data *connectors;
	_4byte, _4byte, _4byte,
	_4byte,
	
	// char cutscene_names[NUMBER_OF_CUTSCENE_MOVIE_TAGS][64];
	64*NUMBER_OF_CUTSCENE_MOVIE_TAGS*sizeof(char),

	// file_tag hints_string_list_tag;
	_4byte,
	
	// struct rgb_color fog_color;
	// float fog_density;
	_2byte, _2byte, _2byte, _2byte,
	_4byte,

	// file_tag difficulty_level_override_string_list_tag;
	_4byte,

	// joe added these fields:
	//short new_field_block_valid_code; // must == 0xFEDC
	_2byte,
	
	// short padd;
	_2byte,

	// file_tag detail_stack_tag;
	_4byte,
	// file_tag environment_texture_tag;
	_4byte,
	// file_tag ground_sprites_tag;
	_4byte,
	// file_tag level_picture_tag;
	_4byte,
	// file_tag collapsed_detail_stack_tag;
	_4byte,
	
	_4byte, _4byte, _4byte, _4byte,
	_4byte, _4byte, _4byte, _4byte,
	_4byte, _4byte,
	_2byte, _2byte,
	_4byte, _4byte, _4byte, _4byte,
	
	//sizeof(int),
	
	// short unused[226];
	196*sizeof(short),
	
	// short connector_type;
	// short map_description_string_index;
	// short overhead_map_collection_index;
	// short landscape_collection_index;
	// short detail_textures_index;
	// short environment_texture_index;
	// short global_ambient_sound_index;
	// short media_collection_index;
	// short hints_string_list_index;
	// short padding
	10*sizeof(short),
	
	// byte editor_data[MESH_HEADER_EDITOR_DATA_SIZE];
	MESH_DEFINITION_EDITOR_DATA_SIZE,
	
	_end_bs_array
};


byte_swap_code mesh_cell_bs_data[]=
{
	_begin_bs_array, 1,
	
	// short_world_distance physical_height; // (might have a few free bits here)
	// word normal; // two 8-bit indexes into the precalculated normal table
	// word flags; // includes terrain type (for pathfinding)
	_2byte,
	_2byte,
	_2byte,

	// short first_object_index; // postprocessed
	sizeof(short),
	
	// short_world_distance media_height;
	_2byte,

	// short_world_distance render_height;
	_2byte,
	
	_end_bs_array
};


// ==============================  READ TAG DATA  ========================================
bool read_mesh_definition( mesh_definition* def, tag_entry* e )
{
	assert( sizeof(mesh_definition) == 1024 );
	return load_tag_data_into_struct( "mesh", e, def, SIZEOF_STRUCT_MESH_DEFINITION, 1, mesh_definition_byte_swapping_data);
}


// ==============================  SAVE TAG DATA  ========================================
bool save_mesh_definition( mesh_definition* def, tag_entry* e )
{
	return save_tag_data_from_struct( "mesh", e, def, SIZEOF_STRUCT_MESH_DEFINITION, 1, mesh_definition_byte_swapping_data);
}


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


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

	return save_mesh_definition( def, e );
}


static bool update_dlog_text( XGDialog *dlog )
{
	bool valid = true;
	int x = dlog->GetValue( 100 );
	if (x < 32 || x > 512 || (x & 31)) valid = false;
	int y = dlog->GetValue( 101 );
	if (y < 32 || y > 512 || (y & 31)) valid = false;
	char buf[256];
	if (valid)
	{
		sprintf( buf, "A %d x %d mesh will require a colormap measuring %d x %d pixels.",
				x, y, (x / 16) * 126, (y / 16) * 126 );
		dlog->SetEnabled( 200, true );
	}
	else
	{
		sprintf( buf, "The mesh sizes must be multiples of 32, between 32 and 512." );
		dlog->SetEnabled( 200, false );
	}
	dlog->SetText( 110, buf );
	
	return valid;
}


// ==============================  EDIT WINDOW  ========================================
void edit_mesh_header( tag_entry* e )
{
	TmeshEditForm* form = new TmeshEditForm( e );
	form->AttachWindow( 1013 );
}


static long NewMeshDlogProc( XGDialog *dlog, void *data, long msg, long arg, void * /*parg*/ )
{
	switch (msg) {
		case KXGDialogMessage:
			switch (arg) {
				case KXGDMInitDialog: {
						update_dlog_text( dlog );
					} return 0;
			} break;
		case KXGKeyClick:
			switch (arg) {
				case 100:
				case 101:
					update_dlog_text( dlog );
					return 0;
			} break;
		case KXGControlClick:
			switch (arg) {
				case 200:
					if (update_dlog_text( dlog ))
					{
						XPoint *pt = (XPoint *)data;
						pt->h = dlog->GetValue( 100 );
						pt->v = dlog->GetValue( 101 );
						dlog->EndDialog( 1 );
					}
					return 0;
				case 201:
					dlog->EndDialog( 0 );
					return 0;
			}
	}
	
	return -1;
}



void new_mesh( tag_entry *e )
{
	XPoint size;
	if (XGDialog::ModalDialog( 169, NewMeshDlogProc, &size ))
	{
		mesh_definition h;
		int i;
		
		memset( &h, 0, sizeof(h) );
		
		h.landscape_texturestack_tag = -1;
		h.media_tag = -1;
		
		h.submesh_width = size.h / 32;
		h.submesh_height = size.v / 32;
		
		h.mesh_offset = 0;
		h.mesh_size = size.h * size.v * sizeof(mesh_cell);
		
		// write data_offset and data.size last
		
		h.marker_palette_entries = 0;
		h.marker_palette_offset = h.mesh_offset + h.mesh_size;
		h.marker_palette_size = h.marker_palette_entries * sizeof(marker_palette_entry);
		
		h.marker_count = 0;
		h.markers_offset = h.marker_palette_offset + h.marker_palette_size;
		h.markers_size = h.marker_count * sizeof(marker_data);
		
		h.mesh_lighting_tag = -1;
		h.connector_tag = -1;
		
		h.flags = 0;
		
		h.particle_system_tag = -1;
		h.team_count = 2;
		
		h.ceiling_height = FLOAT_TO_WORLD(32.0);
		
		h.edge_of_mesh_buffer_zones.top = 32;
		h.edge_of_mesh_buffer_zones.left = 32;
		h.edge_of_mesh_buffer_zones.bottom = 32;
		h.edge_of_mesh_buffer_zones.right = 32;
		
		h.global_ambient_sound_tag = -1;
		h.map_action_count = 0;
		h.map_actions_offset = h.markers_offset + h.markers_size;
		h.map_action_buffer_size = 0;
		
		h.map_description_string_list_tag = -1;
		h.postgame_collection_tag = -1;
		h.pregame_collection_tag = -1;
		h.overhead_map_collection_tag = -1;
		for (i = 0; i < NUMBER_OF_NEXT_MESH_TAGS; ++i)
		{
			h.next_mesh_tags[i] = -1;
		}
		for (i = 0; i < NUMBER_OF_CUTSCENE_MOVIE_TAGS; ++i)
		{
			h.cutscene_movie_tags[i] = -1;
		}
		for (i = 0; i < NUMBER_OF_STORYLINE_STRING_TAGS; ++i)
		{
			h.storyline_string_tags[i] = -1;
		}
		
		h.media_coverage_region_offset = h.map_actions_offset + h.map_action_buffer_size;
		h.media_coverage_region_size = 0;
		
		h.mesh_LOD_data_offset = h.media_coverage_region_offset + h.media_coverage_region_size;
		h.mesh_LOD_data_size = 0;
		
		h.wind_tag = -1;
		
		for (i = 0; i < NUMBER_OF_SCREEN_COLLECTION_TAGS; ++i)
		{
			h.screen_collection_tags[i] = -1;
		}
		
		h.picture_caption_string_list_tag = -1;
		h.narration_sound_tag = -1;
		h.win_ambient_sound_tag = -1;
		h.loss_ambient_sound_tag = -1;
		
		h.connector_count = 0;
		h.connectors_offset = h.mesh_LOD_data_offset + h.mesh_LOD_data_size;
		h.connectors_size = 0;
		
		h.hints_string_list_tag = -1;
		h.difficulty_level_override_string_list_tag = -1;
		
		h.new_field_block_valid_code = 0xFEDC;
		h.detail_stack_tag = -1;
		h.environment_texture_tag = -1;
		h.ground_sprites_tag = -1;
		h.level_picture_tag = -1;
		h.collapsed_detail_stack_tag = -1;
		
		h.postgame_pics[0] = h.postgame_pics[1] = -1;
		h.postgame_text[0] = h.postgame_text[1] = -1;
		h.postgame_mp3[0] = h.postgame_mp3[1] = -1;
		h.postgame_speed[0] = h.postgame_speed[1] = 1;
		h.prologue_quik[0] = h.prologue_quik[1] = h.prologue_quik[0] = h.prologue_quik[1] = -1;
		
		// write this last
		h.data_offset = sizeof(mesh_definition);
		h.data_size = h.connectors_offset + h.connectors_size;
		
		mesh_cell c;
		memset( &c, 0, sizeof(c) );
		
		c.physical_height = FLOAT_TO_WORLD(0.0f);
		c.normal = 00;
		c.flags = (_terrain_grass << 0) + (_terrain_grass << TERRAIN_TYPE_BITS);
		c.first_object_index = -1;
		c.media_height = FLOAT_TO_WORLD(0.0f);
		c.render_height = 0xffff;
		
		
		byte *b = (byte *)malloc( sizeof(h) + h.data_size );
		byte_swap_move_be( "mesh_header", b, &h, sizeof(h), 1, mesh_definition_byte_swapping_data );
		
		for (i = 0; i < size.h * size.v; ++i)
		{
			byte_swap_move_be( "mesh_cell", b + h.data_offset + h.mesh_offset + i * sizeof(c),
								&c, sizeof(c), 1, mesh_cell_bs_data );
		}
		
		set_entry_data( e, b, sizeof(h) + h.data_size, false );
		
		free( b );
		
		{
			edit_mesh_header( e );
			TTagEditForm *form = get_entry_form( e );
			if (form)
			{
				form->TagInfoChanged();
				form->ReloadTag();
			}
		}
	}
}


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


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


// ==============================  INPUT HANDLING  ========================================
long TmeshEditForm::DoControlClick( long arg, void *ptr )
{
	tag new_tag;
	tag_entry* e;
	
#ifdef __MWERKS__
	#pragma unused(ptr)
#endif

	switch( arg )
	{
		case 11301:
		
			new_tag = pick_tag_of_type('txst', GetTag( arg ), fEntry  );
			if(new_tag != 0)
				SetTag( arg, 'txst', new_tag); 		
		
		break;
		
		case 11302:
		
			e = get_entry( 'txst', GetTag( arg-1 ) );
			if(e)
				TRevengeApp::OpenItem( e );
				
		break;
			
		case 11303:
			new_tag = pick_tag_of_type('medi', GetTag( arg ), fEntry  );
			if (new_tag != 0) {
				SetTag( arg, 'medi', new_tag);
				//assert( GetTag( arg ) == new_tag );
			}
			break;
		case 11304:
			e = get_entry( 'medi', GetTag( arg-1 ) );
			if (e) {
				TRevengeApp::OpenItem( e );
			}
			break;
			
		case 11305:
			new_tag = pick_tag_of_type('glli', GetTag( arg ), fEntry  );
			if (new_tag != 0) {
				SetTag( arg, 'glli', new_tag);
			}
			break;
		case 11306:
			e = get_entry( 'glli', GetTag( arg-1 ) );
			if (e) {
				TRevengeApp::OpenItem( e );
			}
			break;
			
		case 11307:
			new_tag = pick_tag_of_type('part', GetTag( arg ), fEntry  );
			if (new_tag != 0) {
				SetTag( arg, 'part', new_tag);
			}
			break;
		case 11308:
			e = get_entry( 'part', GetTag( arg-1 ) );
			if (e) {
				TRevengeApp::OpenItem( e );
			}
			break;
			
		case 11309:
			new_tag = pick_tag_of_type('amso', GetTag( arg ), fEntry  );
			if (new_tag != 0) {
				SetTag( arg, 'amso', new_tag);
			}
			break;
		case 11310:
			e = get_entry( 'amso', GetTag( arg-1 ) );
			if (e) {
				TRevengeApp::OpenItem( e );
			}
			break;
			
		case 11311:
			new_tag = pick_tag_of_type('stli', GetTag( arg ), fEntry  );
			if (new_tag != 0) {
				SetTag( arg, 'stli', new_tag);
			}
			break;
		case 11312:
			e = get_entry( 'stli', GetTag( arg-1 ) );
			if (e) {
				TRevengeApp::OpenItem( e );
			}
			break;
			
		case 11313:
			new_tag = pick_tag_of_type('wind', GetTag( arg ), fEntry  );
			if (new_tag != 0) {
				SetTag( arg, 'wind', new_tag);
			}
			break;
		case 11314:
			e = get_entry( 'wind', GetTag( arg-1 ) );
			if (e) {
				TRevengeApp::OpenItem( e );
			}
			break;
			
		case 11315:
			new_tag = pick_tag_of_type('soun', GetTag( arg ), fEntry  );
			if (new_tag != 0) {
				SetTag( arg, 'soun', new_tag);
			}
			break;
		case 11316:
			e = get_entry( 'soun', GetTag( arg-1 ) );
			if (e) {
				TRevengeApp::OpenItem( e );
			}
			break;
			
		case 11317:
			new_tag = pick_tag_of_type('conn', GetTag( arg ), fEntry  );
			if (new_tag != 0) {
				SetTag( arg, 'conn', new_tag);
			}
			break;
		case 11318:
			e = get_entry( 'conn', GetTag( arg-1 ) );
			if (e) {
				TRevengeApp::OpenItem( e );
			}
			break;
			
		case 11319:
			new_tag = pick_tag_of_type('stli', GetTag( arg ), fEntry  );
			if (new_tag != 0) {
				SetTag( arg, 'stli', new_tag);
			}
			break;
		case 11320:
			e = get_entry( 'stli', GetTag( arg-1 ) );
			if (e) {
				TRevengeApp::OpenItem( e );
			}
			break;
			
		case 11321:
			new_tag = pick_tag_of_type('.256', GetTag( arg ), fEntry  );
			if (new_tag != 0) {
				SetTag( arg, '.256', new_tag);
			}
			break;
		case 11322:
			e = get_entry( '.256', GetTag( arg-1 ) );
			if (e) {
				TRevengeApp::OpenItem( e );
			}
			break;
			
		case 11323:
			new_tag = pick_tag_of_type('.256', GetTag( arg ), fEntry  );
			if (new_tag != 0) {
				SetTag( arg, '.256', new_tag);
			}
			break;
		case 11324:
			e = get_entry( '.256', GetTag( arg-1 ) );
			if (e) {
				TRevengeApp::OpenItem( e );
			}
			break;
			
		case 11325:
			new_tag = pick_tag_of_type('.256', GetTag( arg ), fEntry  );
			if (new_tag != 0) {
				SetTag( arg, '.256', new_tag);
			}
			break;
		case 11326:
			e = get_entry( '.256', GetTag( arg-1 ) );
			if (e) {
				TRevengeApp::OpenItem( e );
			}
			break;
			
		case 11327:
			new_tag = pick_tag_of_type('mesh', GetTag( arg ), fEntry  );
			if (new_tag != 0) {
				SetTag( arg, 'mesh', new_tag);
			}
			break;
		case 11328:
			e = get_entry( 'mesh', GetTag( arg-1 ) );
			if (e) {
				TRevengeApp::OpenItem( e );
			}
			break;
			
		case 11329:
			new_tag = pick_tag_of_type('mesh', GetTag( arg ), fEntry  );
			if (new_tag != 0) {
				SetTag( arg, 'mesh', new_tag);
			}
			break;
		case 11330:
			e = get_entry( 'mesh', GetTag( arg-1 ) );
			if (e) {
				TRevengeApp::OpenItem( e );
			}
			break;
			
		case 11346:
			new_tag = pick_tag_of_type('text', GetTag( arg ), fEntry  );
			if (new_tag != 0) {
				SetTag( arg, 'text', new_tag);
			}
			break;
		case 11347:
			e = get_entry( 'text', GetTag( arg-1 ) );
			if (e) {
				TRevengeApp::OpenItem( e );
			}
			break;
			
		case 11348:
			new_tag = pick_tag_of_type('stli', GetTag( arg ), fEntry  );
			if (new_tag != 0) {
				SetTag( arg, 'stli', new_tag);
			}
			break;
		case 11349:
			e = get_entry( 'stli', GetTag( arg-1 ) );
			if (e) {
				TRevengeApp::OpenItem( e );
			}
			break;
			
		case 11405:
			new_tag = pick_tag_of_type('txst', GetTag( arg ), fEntry  );
			if (new_tag != 0) {
				SetTag( arg, 'txst', new_tag);
			}
			break;
		case 11406:
			e = get_entry( 'txst', GetTag( arg-1 ) );
			if (e) {
				TRevengeApp::OpenItem( e );
			}
			break;
			
		case 11450:
		
			new_tag = pick_tag_of_type('txst', GetTag( 11450 ), fEntry  );
			if(new_tag != 0)
			{
				def.new_field_block_valid_code = 0xFEDC;
				SetTag( 11450, 'txst', new_tag );
			}
				
		break;
		
		case 11451:
		
			e = get_entry( 'txst', GetTag( 11450 ) );
			if(e)
				TRevengeApp::OpenItem( e );
				
			break;
		
		case 11501:
		
			new_tag = pick_tag_of_type('txst', GetTag( 11501 ), fEntry  );
			if(new_tag != 0)
			{
				def.new_field_block_valid_code = 0xFEDC;
				SetTag( 11501, 'txst', new_tag );
			}
				
		break;
		
		case 11502:
		
			e = get_entry( 'txst', GetTag( 11501 ) );
			if(e)
				TRevengeApp::OpenItem( e );
				
			break;
		
		case 11452:
			new_tag = pick_tag_of_type('grsp', GetTag( arg ), fEntry  );
			if (new_tag != 0) {
				SetTag( arg, 'grsp', new_tag);
			}
			break;
		case 11453:
			e = get_entry( 'grsp', GetTag( arg-1 ) );
			if (e) {
				TRevengeApp::OpenItem( e );
			}
			break;
		
		case 11500:
			new_tag = pick_tag_of_type('.256', GetTag( arg ), fEntry );
			if( new_tag != 0 )
				SetTag( arg, '.256', new_tag );
		break;
		
		case 11700:
			new_tag = pick_tag_of_type('jpeg', GetTag( arg ), fEntry  );
			if (new_tag != 0) {
				SetTag( arg, 'jpeg', new_tag);
			}
			break;
			
		case 11701:
			e = get_entry( 'jpeg', GetTag( arg-1 ) );
			if (e) {
				TRevengeApp::OpenItem( e );
			}
			break;
			
		case 11702:
			new_tag = pick_tag_of_type('jpeg', GetTag( arg ), fEntry  );
			if (new_tag != 0) {
				SetTag( arg, 'jpeg', new_tag);
			}
			break;
			
		case 11703:
			e = get_entry( 'jpeg', GetTag( arg-1 ) );
			if (e) {
				TRevengeApp::OpenItem( e );
			}
			break;
			
		case 11704:
			new_tag = pick_tag_of_type('text', GetTag( arg ), fEntry  );
			if (new_tag != 0) {
				SetTag( arg, 'text', new_tag);
			}
			break;
			
		case 11705:
			e = get_entry( 'text', GetTag( arg-1 ) );
			if (e) {
				TRevengeApp::OpenItem( e );
			}
			break;
			
		case 11706:
			new_tag = pick_tag_of_type('text', GetTag( arg ), fEntry  );
			if (new_tag != 0) {
				SetTag( arg, 'text', new_tag);
			}
			break;
			
		case 11707:
			e = get_entry( 'text', GetTag( arg-1 ) );
			if (e) {
				TRevengeApp::OpenItem( e );
			}
			break;
		
		case 11710:
			new_tag = pick_tag_of_type('quik', GetTag( arg ), fEntry  );
			if (new_tag != 0) {
				SetTag( arg, 'quik', new_tag);
			}
			break;
			
		case 11711:
			e = get_entry( 'quik', GetTag( arg-1 ) );
			if (e) {
				TRevengeApp::OpenItem( e );
			}
			break;
			
		case 11712:
			new_tag = pick_tag_of_type('quik', GetTag( arg ), fEntry  );
			if (new_tag != 0) {
				SetTag( arg, 'quik', new_tag);
			}
			break;
			
		case 11713:
			e = get_entry( 'quik', GetTag( arg-1 ) );
			if (e) {
				TRevengeApp::OpenItem( e );
			}
			break;		
			
		default:
			return -1;
	}
	
	return 0;
}

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


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

// ========================================  TAG NEEDS UPDATING  ==================================================
bool TmeshEditForm::NeedCommit()
{
	GetValues();
	return tag_data_needs_update( "mesh", fEntry, &def, SIZEOF_STRUCT_MESH_DEFINITION, 1, mesh_definition_byte_swapping_data, 0);
}

		
// ========================================  SET INTERFACE VALUES  ==================================================
void TmeshEditForm::SetValues()
{
	SetTag( 11301, 'txst', def.landscape_texturestack_tag );
	
	if( def.new_field_block_valid_code == 0xFEDC )
	{
		SetTag( 11450, 'txst', def.detail_stack_tag );
		SetTag( 11501, 'txst', def.collapsed_detail_stack_tag );
	}
	else
	{
		SetTag( 11450, 'txst', 0 );
		SetTag( 11501, 'txst', 0 );
	}
		
	SetTag( 11303, 'medi', def.media_tag );
	SetTag( 11305, 'glli', def.mesh_lighting_tag );
	SetTag( 11452, 'grsp', def.ground_sprites_tag );
	SetTag( 11405, 'txst', def.environment_texture_tag );
	SetTag( 11307, 'part', def.particle_system_tag );
	SetTag( 11309, 'amso', def.global_ambient_sound_tag );
	SetTag( 11311, 'stli', def.map_description_string_list_tag );
	SetTag( 11313, 'wind', def.wind_tag );
	SetTag( 11315, 'soun', def.narration_sound_tag );
	SetTag( 11317, 'conn', def.connector_tag );
	SetTag( 11319, 'stli', def.hints_string_list_tag );
	SetTag( 11321, '.256', def.pregame_collection_tag );
	SetTag( 11323, '.256', def.overhead_map_collection_tag );
	SetTag( 11325, '.256', def.postgame_collection_tag );
	SetTag( 11327, 'mesh', def.next_mesh_tags[_next_mesh_success] );
	SetTag( 11329, 'mesh', def.next_mesh_tags[_next_mesh_failure] );
	
	SetInt( 11601, def.prologue_parms[0] );
	SetInt( 11602, def.prologue_parms[1] );
	SetFixed( 11603, def.prologue_parms[2] );
	SetInt( 11604, def.prologue_parms[3] );

	SetTag( 11700, 'jpeg', def.postgame_pics[0] );
	SetTag( 11702, 'jpeg', def.postgame_pics[1] );
	SetTag( 11704, 'text', def.postgame_text[0] );
	SetTag( 11706, 'text', def.postgame_text[1] );
	
	SetInt( 11708, def.postgame_speed[0] );
	SetInt( 11709, def.postgame_speed[1] );
	
	SetText( 11800, tagstr(def.prologue_quik[0]) );
	SetText( 11801, tagstr(def.prologue_quik[1]) );
	SetText( 11802, tagstr(def.prologue_quik[2]) );

	SetText( 11710, tagstr(def.postgame_mp3[0]) );
	SetText( 11711, tagstr(def.postgame_mp3[1]) );
	
	SetFlag( 11331, def.flags & _mesh_is_single_player_entry_point_flag );
	SetFlag( 11332, def.flags & _mesh_supports_unit_trading_flag );
	SetFlag( 11333, def.flags & _mesh_supports_veterans_flag );
	SetFlag( 11334, def.flags & _mesh_has_limited_terrain_visibility_flag );
	SetFlag( 11335, def.flags & _mesh_is_complete_flag );
	SetFlag( 11336, def.flags & _mesh_can_catch_fire_flag );
	SetFlag( 11337, def.flags & _mesh_leaves_overhead_map_closed_flag );
	SetFlag( 11338, def.flags & _mesh_is_training_map_flag );
	SetFlag( 11339, def.flags & _mesh_is_indoor_map_flag );
	SetFlag( 11340, def.flags & _mesh_has_terrain_following_camera_flag );
	SetFlag( 11341, def.flags & _mesh_can_be_used_by_demo_flag );
	SetFlag( 11342, def.flags & _mesh_overhead_map_doesnt_scroll_flag );
	
	SetInt( 11364, def.team_count );	
	SetShortWorldDistance( 11365, def.ceiling_height );
	
	SetTag( 11346, 'text', def.storyline_string_tags[_storyline_pregame] );
	SetTag( 11348, 'stli', def.picture_caption_string_list_tag );
	SetTag( 11500, '.256', def.level_picture_tag );
	
	SetFlag( 11350, def.flags & (1 << _game_scoring_attrition) );
	SetFlag( 11351, def.flags & (1 << _game_scoring_steal_the_bacon) );
	SetFlag( 11352, def.flags & (1 << _game_scoring_last_man_on_the_hill) );
	SetFlag( 11353, def.flags & (1 << _game_scoring_scavenger_hunt) );
	SetFlag( 11354, def.flags & (1 << _game_scoring_flag_rally) );
	SetFlag( 11355, def.flags & (1 << _game_scoring_capture_the_flag) );
	SetFlag( 11356, def.flags & (1 << _game_scoring_balls_on_parade) );
	SetFlag( 11357, def.flags & (1 << _game_scoring_territories) );
	SetFlag( 11358, def.flags & (1 << _game_scoring_captures) );
	SetFlag( 11359, def.flags & (1 << _game_scoring_king_of_the_hill) );
	SetFlag( 11360, def.flags & (1 << _game_scoring_cattle_drive) );
	SetFlag( 11361, def.flags & (1 << _game_scoring_assassination) );
	SetFlag( 11362, def.flags & (1 << _game_scoring_hunting) );
	SetFlag( 11363, def.flags & (1 << _game_scoring_custom) );
	
	SetInt( 11366, def.edge_of_mesh_buffer_zones.top );
	SetInt( 11367, def.edge_of_mesh_buffer_zones.left );
	SetInt( 11368, def.edge_of_mesh_buffer_zones.right );
	SetInt( 11369, def.edge_of_mesh_buffer_zones.bottom );
}


// ========================================  GET INTERFACE VALUES  ==================================================
void TmeshEditForm::GetValues()
{
	def.media_tag = GetTag( 11303 );
	def.mesh_lighting_tag = GetTag( 11305 );
	def.environment_texture_tag = GetTag( 11405 );
	def.particle_system_tag = GetTag( 11307 );
	def.global_ambient_sound_tag = GetTag( 11309 );
	def.map_description_string_list_tag = GetTag( 11311 );
	def.wind_tag = GetTag( 11313 );
	def.narration_sound_tag = GetTag( 11315 );
	def.connector_tag = GetTag( 11317 );
	def.hints_string_list_tag = GetTag( 11319 );
	def.pregame_collection_tag = GetTag( 11321 );
	def.overhead_map_collection_tag = GetTag( 11323 );
	def.postgame_collection_tag = GetTag( 11325 );
	def.next_mesh_tags[_next_mesh_success] = GetTag( 11327 );
	def.next_mesh_tags[_next_mesh_failure] = GetTag( 11329 );
	def.storyline_string_tags[_storyline_pregame] = GetTag( 11346 );
	def.picture_caption_string_list_tag = GetTag( 11348 );
	
	def.landscape_texturestack_tag = GetTag( 11301 );
	def.detail_stack_tag = GetTag( 11450 );
	def.collapsed_detail_stack_tag = GetTag( 11501 );
	def.ground_sprites_tag = GetTag( 11452 );
	def.level_picture_tag = GetTag( 11500 );
	
	def.team_count = GetInt( 11364 );
	def.ceiling_height = GetWorldDistance( 11365 );
	
	def.prologue_parms[0] = GetInt(11601);
	def.prologue_parms[1] = GetInt(11602);
	def.prologue_parms[2] = GetFixed(11603);
	def.prologue_parms[3] = GetInt(11604);
	
	def.postgame_pics[0] = GetTag(11700);
	def.postgame_pics[1] = GetTag(11702);
	def.postgame_text[0] = GetTag(11704);
	def.postgame_text[1] = GetTag(11706);
	
	def.postgame_speed[0] = GetInt(11708);
	def.postgame_speed[1] = GetInt(11709);
	
	{
		char name[5];
		
		GetText(11800, name, 5);
		def.prologue_quik[0] = tag_type_from_string(name);
		
		GetText(11801, name, 5);
		def.prologue_quik[1] = tag_type_from_string(name);
		
		GetText(11802, name, 5);
		def.prologue_quik[2] = tag_type_from_string(name);
		
		GetText(11710, name, 5);
		def.postgame_mp3[0] = tag_type_from_string(name);
		
		GetText(11711, name, 5);
		def.postgame_mp3[1] = tag_type_from_string(name);
	}
	
	GetFlag( 11331 ) ? def.flags |= _mesh_is_single_player_entry_point_flag : def.flags &= ~_mesh_is_single_player_entry_point_flag;
	GetFlag( 11332 ) ? def.flags |= _mesh_supports_unit_trading_flag : def.flags &= ~_mesh_supports_unit_trading_flag;
	GetFlag( 11333 ) ? def.flags |= _mesh_supports_veterans_flag : def.flags &= ~_mesh_supports_veterans_flag;
	GetFlag( 11334 ) ? def.flags |= _mesh_has_limited_terrain_visibility_flag : def.flags &= ~_mesh_has_limited_terrain_visibility_flag;
	GetFlag( 11335 ) ? def.flags |= _mesh_is_complete_flag : def.flags &= ~_mesh_is_complete_flag;
	GetFlag( 11336 ) ? def.flags |= _mesh_can_catch_fire_flag : def.flags &= ~_mesh_can_catch_fire_flag;
	GetFlag( 11337 ) ? def.flags |= _mesh_leaves_overhead_map_closed_flag : def.flags &= ~_mesh_leaves_overhead_map_closed_flag;
	GetFlag( 11338 ) ? def.flags |= _mesh_is_training_map_flag : def.flags &= ~_mesh_is_training_map_flag;
	GetFlag( 11339 ) ? def.flags |= _mesh_is_indoor_map_flag : def.flags &= ~_mesh_is_indoor_map_flag;
	GetFlag( 11340 ) ? def.flags |= _mesh_has_terrain_following_camera_flag : def.flags &= ~_mesh_has_terrain_following_camera_flag;
	GetFlag( 11341 ) ? def.flags |= _mesh_can_be_used_by_demo_flag : def.flags &= ~_mesh_can_be_used_by_demo_flag;
	GetFlag( 11342 ) ? def.flags |= _mesh_overhead_map_doesnt_scroll_flag : def.flags &= ~_mesh_overhead_map_doesnt_scroll_flag;

	GetFlag( 11350 ) ? def.flags |= (1 << _game_scoring_attrition) : def.flags &= ~(1 << _game_scoring_attrition);
	GetFlag( 11351 ) ? def.flags |= (1 << _game_scoring_steal_the_bacon) : def.flags &= ~(1 << _game_scoring_steal_the_bacon);
	GetFlag( 11352 ) ? def.flags |= (1 << _game_scoring_last_man_on_the_hill) : def.flags &= ~(1 << _game_scoring_last_man_on_the_hill);
	GetFlag( 11353 ) ? def.flags |= (1 << _game_scoring_scavenger_hunt) : def.flags &= ~(1 << _game_scoring_scavenger_hunt);
	GetFlag( 11354 ) ? def.flags |= (1 << _game_scoring_flag_rally) : def.flags &= ~(1 << _game_scoring_flag_rally);
	GetFlag( 11355 ) ? def.flags |= (1 << _game_scoring_capture_the_flag) : def.flags &= ~(1 << _game_scoring_capture_the_flag);
	GetFlag( 11356 ) ? def.flags |= (1 << _game_scoring_balls_on_parade) : def.flags &= ~(1 << _game_scoring_balls_on_parade);
	GetFlag( 11357 ) ? def.flags |= (1 << _game_scoring_territories) : def.flags &= ~(1 << _game_scoring_territories);
	GetFlag( 11358 ) ? def.flags |= (1 << _game_scoring_captures) : def.flags &= ~(1 << _game_scoring_captures);
	GetFlag( 11359 ) ? def.flags |= (1 << _game_scoring_king_of_the_hill) : def.flags &= ~(1 << _game_scoring_king_of_the_hill);
	GetFlag( 11360 ) ? def.flags |= (1 << _game_scoring_cattle_drive) : def.flags &= ~(1 << _game_scoring_cattle_drive);
	GetFlag( 11361 ) ? def.flags |= (1 << _game_scoring_assassination) : def.flags &= ~(1 << _game_scoring_assassination);
	GetFlag( 11362 ) ? def.flags |= (1 << _game_scoring_hunting) : def.flags &= ~(1 << _game_scoring_hunting);
	GetFlag( 11363 ) ? def.flags |= (1 << _game_scoring_custom) : def.flags &= ~(1 << _game_scoring_custom);
	
	def.edge_of_mesh_buffer_zones.top = GetInt( 11366 );
	def.edge_of_mesh_buffer_zones.left = GetInt( 11367 );
	def.edge_of_mesh_buffer_zones.right = GetInt( 11368 );
	def.edge_of_mesh_buffer_zones.bottom = GetInt( 11369 );
}
