#include common_scripts\utility;
#include common_scripts\_createfx;


//---------------------------------------------------------
// Menu init/loop section
//---------------------------------------------------------
init_menu()
{
	level._createfx.options = [];
	// each option has a type, a name its stored under, a description, a default, and a mask it uses to determine
	// which types of fx can have this option
	addOption( "vector", "origin", "Origin", (0,0,0), "fx", 1 );
	addOption( "vector", "angles", "Angles", (0,0,0), "fx", 1 );
	addOption( "string", "fxid", "FX id", "nil", "fx" );
	addOption( "float", "delay", "Repeat rate/start delay", 0.5, "fx" );
	addOption( "string", "flag", "Flag", "nil", "exploder" );
	addOption( "string", "platform", "Platform", "all", "all" );
	
	if ( !level.mp_createfx )
	{
	addOption( "string", "firefx", "2nd FX id", "nil", "exploder" );
	addOption( "float", "firefxdelay", "2nd FX id repeat rate", 0.5, "exploder" );
	addOption( "float", "firefxtimeout", "2nd FX timeout", 5, "exploder" );
	addOption( "string", "firefxsound", "2nd FX soundalias", "nil", "exploder" );
	addOption( "float", "damage", "Radius damage", 150, "exploder" );
	addOption( "float", "damage_radius", "Radius of radius damage", 250, "exploder" );
		addOption( "string", "earthquake", "Earthquake", "nil", "exploder" );
		addOption( "string", "ender", "Level notify for ending 2nd FX", "nil", "exploder" );
	}

	addOption( "float", "delay_min", "Minimimum time between repeats", 1, "soundfx_interval" );
	addOption( "float", "delay_max", "Maximum time between repeats", 2, "soundfx_interval" );
	addOption( "int", "repeat", "Number of times to repeat", 5, "exploder" );
	addOption( "string", "exploder", "Exploder", "1", "exploder" );
	setup_help_keys();
	

	addOption( "string", "soundalias", "Soundalias", "nil", "all" );
	addOption( "string", "loopsound", "Loopsound", "nil", "exploder" );

	addOption( "int", "reactive_radius", "Reactive Radius", 100, "reactive_fx", undefined, ::input_reactive_radius );

	addOption( "string", "ambiencename", "Ambience Name", "nil", "soundfx_dynamic" );
	addOption( "int", "dynamic_distance", "Dynamic Max Distance", 1000, "soundfx_dynamic" );

	if( !level.mp_createfx )
	{
		addOption( "string", "rumble", "Rumble", "nil", "exploder" );
		addOption( "int", "stoppable", "Can be stopped from script", "1", "all" );
	}

	level.effect_list_offset = 0;
	level.effect_list_offset_max = 10;
	level.effect_list_current_size = 0;
	
	level.help_list_offset = 0;
	level.help_list_offset_max = 20;
	
	level.createfx_help_active = false;
	
	level.createfx_menu_list_active = false;

	// creates mask groups. For example if the above says its mask is "fx", then all the types under "fx" can use the option
	level.createfxMasks = [];
	level.createfxMasks[ "all" ] = [];
	level.createfxMasks[ "all" ][ "exploder" ] = true;
	level.createfxMasks[ "all" ][ "oneshotfx" ] = true;
	level.createfxMasks[ "all" ][ "loopfx" ] = true;
	level.createfxMasks[ "all" ][ "soundfx" ] = true;
	level.createfxMasks[ "all" ][ "soundfx_interval" ] = true;
	level.createfxMasks[ "all" ][ "reactive_fx" ] = true;
	level.createfxMasks[ "all" ][ "soundfx_dynamic" ] = true;

	level.createfxMasks[ "fx" ] = [];
	level.createfxMasks[ "fx" ][ "exploder" ] = true;
	level.createfxMasks[ "fx" ][ "oneshotfx" ] = true;
	level.createfxMasks[ "fx" ][ "loopfx" ] = true;

	level.createfxMasks[ "exploder" ] = [];
	level.createfxMasks[ "exploder" ][ "exploder" ] = true;

	level.createfxMasks[ "loopfx" ] = [];
	level.createfxMasks[ "loopfx" ][ "loopfx" ] = true;

	level.createfxMasks[ "oneshotfx" ] = [];
	level.createfxMasks[ "oneshotfx" ][ "oneshotfx" ] = true;

	level.createfxMasks[ "soundfx" ] = [];
	level.createfxMasks[ "soundfx" ][ "soundalias" ] = true;
	
	level.createfxMasks[ "soundfx_interval" ] = [];
	level.createfxMasks[ "soundfx_interval" ][ "soundfx_interval" ] = true;

	level.createfxMasks[ "reactive_fx" ] = [];
	level.createfxMasks[ "reactive_fx" ][ "reactive_fx" ] = true;

	level.createfxMasks[ "soundfx_dynamic" ] = [];
	level.createfxMasks[ "soundfx_dynamic" ][ "soundfx_dynamic" ] = true;

	// Mainly used for input of a menu
	menus = [];
	menus[ "creation" ] = 		::menu_create_select;
	menus[ "create_oneshot" ] = ::menu_create;
	menus[ "create_loopfx" ] = 	::menu_create;
	menus[ "change_fxid" ] = 	::menu_create;
	menus[ "none" ] = 			::menu_none;
	menus[ "add_options" ] = 	::menu_add_options;
	menus[ "select_by_name" ] = ::menu_select_by_name;
	
	level._createfx.menus = menus;
}

menu( name )
{
	return level.create_fx_menu == name;
}

setmenu( name )
{
	level.create_fx_menu = name;
}

create_fx_menu()
{
	if ( button_is_clicked( "escape", "x" ) )
	{
		_exit_menu();
		return;
	}
	
	if ( IsDefined( level._createfx.menus[ level.create_fx_menu ] ) )
	{
		[[ level._createfx.menus[ level.create_fx_menu ] ]]();
	}
}

menu_create_select()
{
	if ( button_is_clicked( "1" ) )
	{
		setmenu( "create_oneshot" );
		draw_effects_list();
		return;
	}
	else if ( button_is_clicked( "2" ) )
	{
		setmenu( "create_loopfx" );
		draw_effects_list();
		return;
	}
	else if ( button_is_clicked( "3" ) )
	{
		setmenu( "create_loopsound" );
		ent = createLoopSound();
		finish_creating_entity( ent );
		return;
	}
	else if ( button_is_clicked( "4" ) )
	{
		setmenu( "create_exploder" );
		ent = createNewExploder();
		finish_creating_entity( ent );
		return;
	}
	else if ( button_is_clicked( "5" ) )
	{
		setmenu( "create_interval_sound" );
		ent = createIntervalSound();
		finish_creating_entity( ent );
		return;
	}
	else if ( button_is_clicked( "6" ) )
	{
		ent = createReactiveEnt();
		finish_creating_entity( ent );
		return;
}
	else if ( button_is_clicked( "7" ) )
	{
		ent = createDynamicAmbience();
		finish_creating_entity( ent );
		return;
	}
}

menu_create()
{
	level.createfx_menu_list_active = true;
	if ( next_button() )
	{
		increment_list_offset();
		draw_effects_list();
	}
	else if ( previous_button() )
	{
		decrement_list_offset();
		draw_effects_list();
	}

	menu_fx_creation();
}

menu_none()
{
	if ( button_is_clicked( "m" ) )
		increment_list_offset();

	// change selected entities
	menu_change_selected_fx();

	// if there's a selected ent then display the info on the last one to be selected
	if ( entities_are_selected() )
	{
		last_selected_ent = get_last_selected_ent();
		
		// only update hudelems when we have new info
		if ( !IsDefined( level.last_displayed_ent ) || last_selected_ent != level.last_displayed_ent || level._createfx.justConvertedOneshot == 1 )
		{
			display_fx_info( last_selected_ent );
			level.last_displayed_ent = last_selected_ent;
			level._createfx.justConvertedOneshot = 0;
		}

		if ( button_is_clicked( "a" ) )
		{
			clear_settable_fx();
			setMenu( "add_options" );
		}
	}
	else
	{
		level.last_displayed_ent = undefined;
}
}

menu_add_options()
{
	if ( !entities_are_selected() )
	{
		clear_fx_hudElements();
		setMenu( "none" );
		return;
	}

	display_fx_add_options( get_last_selected_ent() );
	if ( next_button() )
	{
		increment_list_offset();
//			draw_effects_list();		
	}
}

menu_select_by_name()
{
	if ( next_button() )
	{
		increment_list_offset();
		draw_effects_list( "Select by name" );
	}
	else if ( previous_button() )
	{
		decrement_list_offset();
		draw_effects_list( "Select by name" );
	}
	
	select_by_name();
}

next_button()
{
	return button_is_clicked( "rightarrow" );
}

previous_button()
{
	return button_is_clicked( "leftarrow" );	
}

_exit_menu()
{
	clear_fx_hudElements();
	clear_entity_selection();
	update_selected_entities();
	setmenu( "none" );
}

//---------------------------------------------------------
// Create FX Section (button presses)
//---------------------------------------------------------
menu_fx_creation()
{
	count = 0;
	picked_fx = undefined;
	keys = func_get_level_fx();

	for ( i = level.effect_list_offset; i < keys.size; i++ )
	{
		count = count + 1;
		button_to_check = count;
		if ( button_to_check == 10 )
			button_to_check	 = 0;
		if ( button_is_clicked( button_to_check + "" ) )
		{
			picked_fx = keys[ i ];
			break;
		}

		if ( count > level.effect_list_offset_max )
			break;
	}

	if ( !isdefined( picked_fx ) )
		return;

	if ( menu( "change_fxid" ) )
	{
		apply_option_to_selected_fx( get_option( "fxid" ), picked_fx );
		level.effect_list_offset = 0;
		clear_fx_hudElements();
		setMenu( "none" );
		level.createfx_menu_list_active = false;
		level.createfx_last_movement_timer = 0;
		return;
	}


	ent = undefined;
	if ( menu( "create_loopfx" ) )
		ent = createLoopEffect( picked_fx );
	if ( menu( "create_oneshot" ) )
		ent = createOneshotEffect( picked_fx );

	finish_creating_entity( ent );
}

finish_creating_entity( ent )
{
	assert( isdefined( ent ) );
	ent.v[ "angles" ] = vectortoangles( ( ent.v[ "origin" ] + ( 0, 0, 100 ) ) - ent.v[ "origin" ] );
	ent post_entity_creation_function();// for createfx dev purposes
	clear_entity_selection();
	select_last_entity();
	move_selection_to_cursor();
	update_selected_entities();
	setMenu( "none" );
	level.createfx_menu_list_active = false;
}

entities_are_selected()
{
	return level._createfx.selected_fx_ents.size > 0;
}

menu_change_selected_fx()
{
	if ( !level._createfx.selected_fx_ents.size )
	{
		return;
	}

	count = 0;
	drawnCount = 0;
	ent = get_last_selected_ent();

	for ( i = 0; i < level._createfx.options.size; i++ )
	{
		option = level._createfx.options[ i ];
		if ( !isdefined( ent.v[ option[ "name" ] ] ) )
			continue;
		count++ ;
		if ( count < level.effect_list_offset )
			continue;

		drawnCount++ ;
		button_to_check = drawnCount;
		if ( button_to_check == 10 )
			button_to_check = 0;

		if ( button_is_clicked( button_to_check + "" ) )
		{
			prepare_option_for_change( option, drawnCount );
			break;
		}

		if ( drawnCount > level.effect_list_offset_max )
		{
			more = true;
			break;
		}
	}
}

prepare_option_for_change( option, drawnCount )
{
	if ( option[ "name" ] == "fxid" )
	{
		setMenu( "change_fxid" );
		draw_effects_list();
		return;
	}

	level.createfx_inputlocked = true;
	level._createfx.hudelems[ drawnCount + 1 ][ 0 ].color = ( 1, 1, 0 );
	
	if ( IsDefined( option[ "input_func" ] ) )
	{
		thread [[ option[ "input_func" ] ]]( drawnCount + 1 );
	}
	else
	{
		createfx_centerprint( "To set " + option[ "description" ] + ", type /fx newvalue. To remove "+ option[ "description" ] +", type /fx del" );
	}
	
	set_option_index( option[ "name" ] );
	setdvar( "fx", "nil" );
}

menu_fx_option_set()
{
	if ( getdvar( "fx" ) == "nil" )
		return;
	
	if ( getdvar( "fx" ) == "del" )
	{
		remove_selected_option();
		return;
	}

	option = get_selected_option();
	setting = undefined;
	if ( option[ "type" ] == "string" )
		setting = getdvar( "fx" );
	if ( option[ "type" ] == "int" )
		setting = getdvarint( "fx" );
	if ( option[ "type" ] == "float" )
		setting = getdvarfloat( "fx" );
	if ( option[ "type" ] == "vector" )
		setting = getdvarvector( "fx" );

	if(isDefined(setting))
		apply_option_to_selected_fx( option, setting );
	else
		setdvar( "fx" , "nil");
}

apply_option_to_selected_fx( option, setting )
{
	save_undo_buffer();
	for ( i = 0; i < level._createfx.selected_fx_ents.size; i++ )
	{
		ent = level._createfx.selected_fx_ents[ i ];

		if ( mask( option[ "mask" ], ent.v[ "type" ] ))
			ent.v[ option[ "name" ] ] = setting;
	}

	level.last_displayed_ent = undefined; // needed to force a redraw of the last display ent
	update_selected_entities();
	clear_settable_fx();
	//if we moved it, restart and focus camera on new position
	if( option[ "name" ] == "origin")
   	{
	   	level.createfx_last_movement_timer = 0;
	   	frame_selected();
   	}
	//if we changed angles, restart fx
	if( option[ "name" ] == "angles")
   	{
	   	level.createfx_last_movement_timer = 0;
   	}
	save_redo_buffer();
}

set_option_index( name )
{
	for ( i = 0; i < level._createfx.options.size; i++ )
	{
		if ( level._createfx.options[ i ][ "name" ] != name )
			continue;

		level._createfx.selected_fx_option_index = i;
		return;
	}
}

get_selected_option()
{
	return level._createfx.options[ level._createfx.selected_fx_option_index ];
}

mask( type, name )
{
	return isdefined( level.createfxMasks[ type ][ name ] );
}

addOption( type, name, description, defaultSetting, mask, nowrite, input_func )
{
	option = [];
	option[ "type" ] = type;
	option[ "name" ] = name;
	option[ "description" ] = description;
	option[ "default" ] = defaultSetting;
	option[ "mask" ] = mask;
	
	if ( isdefined(nowrite) && nowrite )
		option[ "nowrite" ] = 1;
	else
		option[ "nowrite" ] = 0;
	
	if ( IsDefined( input_func ) )
	{
		option[ "input_func" ] = input_func;
	}
	
	level._createfx.options[ level._createfx.options.size ] = option;
}

get_option( name )
{
	for ( i = 0; i < level._createfx.options.size; i++ )
	{
		if ( level._createfx.options[ i ][ "name" ] == name )
			return level._createfx.options[ i ];
	}
}

//---------------------------------------------------------
// Reactive Radius
//---------------------------------------------------------
input_reactive_radius( menu_index )
{
	level._createfx.hudelems[ menu_index ][ 0 ] SetDevText( "Reactive Radius, Press: + OR -" );

	while ( 1 )
	{
		wait( 0.05 );
		if ( level.player ButtonPressed( "escape" ) || level.player ButtonPressed( "x" ) )
			break;
			
		val = 0;
		if ( level.player ButtonPressed( "-" ) )
			val = -10;
		else if ( level.player ButtonPressed( "=" ) )
			val = 10;
		
		
		if ( val != 0 )
		{
			foreach ( ent in level._createfx.selected_fx_ents )
			{
				if ( IsDefined( ent.v[ "reactive_radius" ] ) )
				{
					ent.v[ "reactive_radius" ] += val;
					ent.v[ "reactive_radius" ] = Clamp( ent.v[ "reactive_radius" ], 10, 1000 );
				}
			}
		}
	}

	level.last_displayed_ent = undefined; // needed to force a redraw of the last display ent
	update_selected_entities();
	clear_settable_fx();
}

//---------------------------------------------------------
// Display FX Add Options
//---------------------------------------------------------
display_fx_add_options( ent )
{
	// are we doing the create fx menu right now?
	assert( menu( "add_options" ) );
	assert( entities_are_selected() );

	level.createfx_menu_list_active = true;
	
	clear_fx_hudElements();
	set_fx_hudElement( "Name: " + ent.v[ "fxid" ] );
	set_fx_hudElement( "Type: " + ent.v[ "type" ] );
	set_fx_hudElement( "Origin: " + ent.v[ "origin" ] );
	set_fx_hudElement( "Angles: " + ent.v[ "angles" ] );

	// if entities are selected then we make the entity stats modifiable
	count = 0;
	drawnCount = 0;
	more = false;

	if ( level.effect_list_offset >= level._createfx.options.size )
		level.effect_list_offset = 0;

	for ( i = 0; i < level._createfx.options.size; i++ )
	{
		option = level._createfx.options[ i ];
		if ( isdefined( ent.v[ option[ "name" ] ] ) )
			continue;

		// does this type of effect get this kind of option?
		if ( !mask( option[ "mask" ], ent.v[ "type" ] ) )
			continue;

		count++ ;
		if ( count < level.effect_list_offset )
			continue;
		if ( drawnCount >= level.effect_list_offset_max )
			continue;

		drawnCount++ ;
		button_to_check = drawnCount;
		if ( button_to_check == 10 )
			button_to_check = 0;
		if ( button_is_clicked( button_to_check + "" ) )
		{
			add_option_to_selected_entities( option );
//			prepare_option_for_change( option, drawnCount );
			menuNone();
			level.last_displayed_ent = undefined; // needed to force a redraw of the last display ent
			return;
		}

		set_fx_hudElement( button_to_check + ". " + option[ "description" ] );
	}

	if ( count > level.effect_list_offset_max )
	{
		level.effect_list_current_size = count;
		set_fx_hudElement( "(->) More >" );
	}

	set_fx_hudElement( "(x) Exit >" );
}

add_option_to_selected_entities( option )
{
	setting = undefined;
	for ( i = 0; i < level._createfx.selected_fx_ents.size; i++ )
	{
		ent = level._createfx.selected_fx_ents[ i ];

		if ( mask( option[ "mask" ], ent.v[ "type" ] ) )
			ent.v[ option[ "name" ] ] = option[ "default" ];
	}
}

menuNone()
{
	level.effect_list_offset = 0;
	clear_fx_hudElements();
	setMenu( "none" );
}

//---------------------------------------------------------
// Display FX info
//---------------------------------------------------------
display_fx_info( ent )
{
	// are we doing the create fx menu right now?
	if ( !menu( "none" ) )
		return;
	
	if ( level.createfx_help_active )
		return;

	clear_fx_hudElements();
	set_fx_hudElement( "Name: " + ent.v[ "fxid" ] );
	set_fx_hudElement( "Type: " + ent.v[ "type" ] );

	if ( entities_are_selected() )
	{
		// if entities are selected then we make the entity stats modifiable
		count = 0;
		drawnCount = 0;
		more = false;
		for ( i = 0; i < level._createfx.options.size; i++ )
		{
			option = level._createfx.options[ i ];
			if ( !isdefined( ent.v[ option[ "name" ] ] ) )
				continue;
			count++ ;
			if ( count < level.effect_list_offset )
				continue;

			drawnCount++ ;
			set_fx_hudElement( drawnCount + ". " + option[ "description" ] + ": " + ent.v[ option[ "name" ] ] );
			if ( drawnCount > level.effect_list_offset_max )
			{
				more = true;
				break;
			}
		}
		if ( count > level.effect_list_offset_max )
		{
			level.effect_list_current_size = count;
			set_fx_hudElement( "(->) More >" );
		}
		set_fx_hudElement( "(a) Add >" );
		set_fx_hudElement( "(x) Exit >" );
	}
	else
	{
		count = 0;
		more = false;
		for ( i = 0; i < level._createfx.options.size; i++ )
		{
			option = level._createfx.options[ i ];
			if ( !isdefined( ent.v[ option[ "name" ] ] ) )
				continue;
			count++ ;
			set_fx_hudElement( option[ "description" ] + ": " + ent.v[ option[ "name" ] ] );
			if ( count > level._createfx.hudelem_count )
				break;
		}
	}
}

display_current_translation()
{
	ent = get_last_selected_ent();
	if(isdefined(ent))
		display_fx_info(ent);
}

//---------------------------------------------------------
// Draw Effects Section
//---------------------------------------------------------
draw_effects_list( title )
{
	clear_fx_hudElements();

	count = 0;
	more = false;

	keys = func_get_level_fx();
	level.effect_list_current_size = keys.size;
	
	if( !IsDefined( title ) )
	{
		title = "Pick an effect";
	}

	set_fx_hudElement( title + " [" + level.effect_list_offset + " - " + keys.size + "]:" );

//	if ( level.effect_list_offset >= keys.size )
//		level.effect_list_offset = 0;

	for ( i = level.effect_list_offset; i < keys.size; i++ )
	{
		count = count + 1;
		set_fx_hudElement( count + ". " + keys[ i ] );
		if ( count >= level.effect_list_offset_max )
		{
			more = true;
			break;
		}
	}

	if ( keys.size > level.effect_list_offset_max )
	{
		set_fx_hudElement( "(->) More >" );
		set_fx_hudElement( "(<-) Previous >" );
	}
}

increment_list_offset()
{
	if ( level.effect_list_offset >= level.effect_list_current_size - level.effect_list_offset_max )
	{
		level.effect_list_offset = 0;
	}
	else
	{
		level.effect_list_offset += level.effect_list_offset_max;
	}
}

decrement_list_offset()
{
	if ( level.effect_list_current_size < level.effect_list_offset_max )
	{
		level.effect_list_offset = 0;
	}
	else
	{
		level.effect_list_offset -= level.effect_list_offset_max;
		if ( level.effect_list_offset < 0 )
		{
			//keys = func_get_level_fx();
			level.effect_list_offset = level.effect_list_current_size - level.effect_list_offset_max;
		}
	}
}

//---------------------------------------------------------
// Draw Help
//---------------------------------------------------------
draw_help_list( title )
{
	clear_fx_hudElements();
	
	count = 0;

	keys = 	level.createfx_help_keys;
	
	if( !IsDefined( title ) )
	{
		title = "Help";
	}

	set_fx_hudElement( "[" + title + "]");// + " [" + level.help_list_offset + " - " + keys.size + "]:" );

//	if ( level.effect_list_offset >= keys.size )
//		level.effect_list_offset = 0;

	for ( i = level.help_list_offset; i < keys.size; i++ )
	{
		count = count + 1;
		set_fx_hudElement( keys[ i ] );
		if ( count >= level.help_list_offset_max )
		{
			more = true;
			break;
		}
	}

	if ( keys.size > level.help_list_offset_max )
	{
		level.effect_list_current_size = keys.size;
		set_fx_hudElement( "(->) More >" );
		set_fx_hudElement( "(<-) Previous >" );
	}
}

increment_help_list_offset()
{
	keys = level.createfx_help_keys;

	if ( level.help_list_offset >= keys.size - level.help_list_offset_max )
	{
		level.help_list_offset = 0;
	}
	else
	{
		level.help_list_offset += level.help_list_offset_max;
	}
}

decrement_help_list_offset()
{
	level.help_list_offset -= level.help_list_offset_max;

	if ( level.help_list_offset < 0 )
	{
		keys = level.createfx_help_keys;
		level.help_list_offset = keys.size - level.help_list_offset_max;
	}
}

help_navigation_buttons()
{
	while(level.createfx_help_active == true)
	{
		if ( next_button() )
		{
			increment_help_list_offset();
			draw_help_list();
			wait 0.1;
		}
		else if ( previous_button() )
		{
			decrement_help_list_offset();
			draw_help_list();
			wait 0.1;
		}
		waitframe();
	}
}

setup_help_keys()
{
	level.createfx_help_keys = 	 [
			"Insert             Insert entity",
			"F2                 Toggle createfx dot and text drawing",
			"F5                 SAVES your work",
			"Z                  Undo",
			"Shift-Z            Redo",
			"F                  Frames currently selected entities in camera view",
			"END                Drop selected entities to the ground",
			"A                  Add option to the selected entities",
			"P                  Reset the rotation of the selected entities",
			"V                  Copy the angles from the most recently selected fx onto all selected fx.",
			"O                  Orient all selected fx to point at most recently selected fx.",
			"S                  Toggle Snap2Normal mode.",
			"L                  Toggle 90deg Snap mode.",
			"G                  Select all effects in level of same exploder or flag as selected.",
			"U                  Select by name list.",
			"C                  Convert One-Shot to Exploder.",
			"Delete             Kill the selected entities",
			"ESCAPE             Cancel out of option-modify-mode, must have console open",
			"SPACE or ->        Turn on exploders",
			"<-                 Turn off exploders",
			"Dpad               Move selected entities on X/Y or rotate pitch/yaw",
			"A button           Toggle the selection of the current entity",
			"X button           Toggle entity rotation mode",
			"Y button           Move selected entites up or rotate roll",
			"B button           Move selected entites down or rotate roll",
			"R Shoulder         Move selected entities to the cursor",
			"L Shoulder         Hold to select multiple entites",
			"L JoyClick         Copy",
			"R JoyClick         Paste",
			"Ctrl-C             Copy",
			"Ctrl-V             Paste",
			"N                  UFO",
			"T                  Toggle Timescale FAST",
			"Y                  Toggle Timescale SLOW",
			"[                  Toggle FX Visibility",
			"]                  Toggle ShowTris",
			"F11                Toggle FX Profile"];
}

//---------------------------------------------------------
// Select by Name Section
//---------------------------------------------------------
select_by_name()
{
	count = 0;
	picked_fx = undefined;
	keys = func_get_level_fx();

	for ( i = level.effect_list_offset; i < keys.size; i++ )
	{
		count = count + 1;
		button_to_check = count;
		if ( button_to_check == 10 )
			button_to_check	 = 0;
		if ( button_is_clicked( button_to_check + "" ) )
		{
			picked_fx = keys[ i ];
			break;
		}

		if ( count > level.effect_list_offset_max )
			break;
	}

	if ( !IsDefined( picked_fx ) )
		return;
		
	index_array = [];
	foreach ( i, ent in level.createFXent )
	{
		if ( IsSubStr( ent.v[ "fxid" ], picked_fx ) )
		{
			index_array[ index_array.size ] = i;
		}
	}
	
	deselect_all_ents();
	select_index_array( index_array );
	
	level._createfx.select_by_name = true;
}

//---------------------------------------------------------
// Utility Section
//---------------------------------------------------------
get_last_selected_ent()
{
	return level._createfx.selected_fx_ents[ level._createfx.selected_fx_ents.size - 1 ];
}