//
// Tools_VertexPerPoly_Selection.cpp
//
// Created by JGP 09/05/06
//
// Copyright (C) 2006 Rebellion (Derby), All Rights Reserved.
//

#include "Core/Asura.h"

// This file's header
#include "Tools_VertexPerPoly_Selection.h"

// Asura headers
#include "Rendering/Asura_Module.h"
#include "Mesh/Asura_Mesh.h"
#include "Mesh/Asura_Mesh_System.h"
#include "Interface/Asura_Overlay_System.h"
#include "Interface/Asura_Overlay.h"
#include "Interface/Asura_Dialog.h"
#include "Interface/Asura_Interface.h"
#include "Interface/Asura_Cursor.h"
#include "Core/Asura_Timers.h"
#include "Core/Asura_UserInput.h"
#include "Rendering/Asura_Viewport.h"
#include "Camera/Asura_Camera.h"
#include "Misc/Tools_Timed_Messages.h"
#include "Load&Save/Tools_ModeDataFile.h"
#include "Misc/Tools_LOS.h"
#include "Misc/Tools_Prompted_Selection.h"
#include "Debugging/Asura_Assert.h"
#include "Tools_Overlays.h"
#include "Misc/Tools_Help.h"
#include "Misc/Tools_Render.h"
#include "Misc/Tools_Render_Options.h"


// static variables


bool Tools_VertexPerPoly_Selection::s_bShowSelection; 

bool Tools_VertexPerPoly_Selection::s_bSelectionLocked;
int Tools_VertexPerPoly_Selection::s_iSelectionMode;								
int Tools_VertexPerPoly_Selection::s_iSelectionModeListOffset;						

Asura_Vector_2 Tools_VertexPerPoly_Selection::s_xSelectionOverlayPosition = Asura_Vector_2( 80.0f, 32.0f );
bool Tools_VertexPerPoly_Selection::s_bSelectionOverlayOpen;
u_int Tools_VertexPerPoly_Selection::s_uSelectionOverlayMinimised = 0;

List<ModuleVertexPerPolyTriplet> Tools_VertexPerPoly_Selection::s_xSelectionList;

VertexPerPolySelectionUndo Tools_VertexPerPoly_Selection::s_xSelectionUndo;

bool Tools_VertexPerPoly_Selection::s_bButtonDownForSelection;						
ModuleVertexPerPolyTriplet Tools_VertexPerPoly_Selection::s_xHighlitVertexPerPoly;					
PolygonID Tools_VertexPerPoly_Selection::s_xHighlitPolygon;						

bool Tools_VertexPerPoly_Selection::s_bActive;


static const char* g_aszVertexPerPolySelectionHelpStrings[] =
{
	"LMB :         Select VertexPerPoly",
	"Shift+LMB :   Deselect VertexPerPoly",
	"",
	"L :           Clear Selection",
	"",
	"Shift+Z :     Undo Selection",
	"Shift+Y :     Redo Selection",
	"Shift+< :     Undo Selection",
	"Shift+> :     Redo Selection",
	NULL,
};


///////////////////////////////////////////////////////////////////////////////////////
// VertexPerPolySelectionUndo
///////////////////////////////////////////////////////////////////////////////////////


void VertexPerPolySelectionUndo::ProcessUndoData( void* pData )
{
	VertexPerPolySelectionUndoData* pxUndoData = static_cast< VertexPerPolySelectionUndoData* >( pData );

	switch( pxUndoData->m_eUndoType )
	{

		case VertexPerPolySelectionUndoData::UndoType_Added:

			// unselect selected VertexPerPoly
			Tools_VertexPerPoly_Selection::DeselectVertexPerPoly( pxUndoData->m_iModuleIndex, pxUndoData->m_iPolyIndex, pxUndoData->m_iVertexIndex, false );

			// reverse the undo data
			pxUndoData->m_eUndoType = VertexPerPolySelectionUndoData::UndoType_Removed;

			break;

		case VertexPerPolySelectionUndoData::UndoType_Removed:

			// select unselected VertexPerPoly
			Tools_VertexPerPoly_Selection::SelectVertexPerPoly( pxUndoData->m_iModuleIndex, pxUndoData->m_iPolyIndex, pxUndoData->m_iVertexIndex, false );

			// reverse the undo data
			pxUndoData->m_eUndoType = VertexPerPolySelectionUndoData::UndoType_Added;

			break;

		default:

			Asura_Assert(0, "Unexpected undo type in VertexPerPolySelectionUndo::ProcessUndoData" );
			break;
	}
}


void VertexPerPolySelectionUndo::LogVertexPerPolySelected( int iModule, int iPoly, int iVert )
{
	VertexPerPolySelectionUndoData* pxUndo = static_cast< VertexPerPolySelectionUndoData* >( AllocateNextUndoData() );
	if ( !pxUndo ) 
	{
		return;
	}

	pxUndo->m_eUndoType = VertexPerPolySelectionUndoData::UndoType_Added;
	pxUndo->m_iModuleIndex = iModule;
	pxUndo->m_iPolyIndex = iPoly;
	pxUndo->m_iVertexIndex = iVert;

}


void VertexPerPolySelectionUndo::LogVertexPerPolyDeselected( int iModule, int iPoly, int iVert )
{
	VertexPerPolySelectionUndoData* pxUndo = static_cast< VertexPerPolySelectionUndoData* >( AllocateNextUndoData() );
	if ( !pxUndo ) 
	{
		return;
	}

	pxUndo->m_eUndoType = VertexPerPolySelectionUndoData::UndoType_Removed;
	pxUndo->m_iModuleIndex = iModule;
	pxUndo->m_iPolyIndex = iPoly;
	pxUndo->m_iVertexIndex = iVert;

}


void Tools_VertexPerPoly_Selection::Undo()
{
	if ( !s_bSelectionLocked )
	{
		if ( s_xSelectionUndo.Undo() )
		{
			Tools_Timed_Message_System::AddMessage( 0xffffff, "Selection Undo" );
		}
	}
}


void Tools_VertexPerPoly_Selection::Redo()
{
	if ( !s_bSelectionLocked )
	{
		if( s_xSelectionUndo.Redo() )
		{
			Tools_Timed_Message_System::AddMessage( 0xffffff, "Selection Redo" );
		}
	}
}


///////////////////////////////////////////////////////////////////////////////////////
// Tools_VertexPerPoly_Selection Initialise / Shutdown
///////////////////////////////////////////////////////////////////////////////////////


void Tools_VertexPerPoly_Selection::Initialise()
{

	s_bSelectionLocked = false;
	s_bShowSelection = true;
	s_iSelectionMode = VPSelectionMode_VertexPerPoly;
	s_iSelectionModeListOffset = 0;
	s_bButtonDownForSelection = false;
	s_xHighlitVertexPerPoly.m_iModuleIndex = -1;
	s_xHighlitPolygon.ModuleIndex = -1;

	//load values from .dat file
	TransferModeData( TOOLSMODEDATAFILE_LOAD );
	
	s_bSelectionOverlayOpen = true;

	s_xSelectionUndo.Initialise();

}


void Tools_VertexPerPoly_Selection::Shutdown()
{

	//save values to .dat file
	TransferModeData(TOOLSMODEDATAFILE_SAVE);

    s_xSelectionList.empty();	

	s_xSelectionUndo.Shutdown();

}


void Tools_VertexPerPoly_Selection::Activate()
{
	s_bActive = true;

	s_xHighlitVertexPerPoly.m_iModuleIndex = -1;
	s_xHighlitPolygon.ModuleIndex = -1;

	CreateSelectionOverlay();

	Tools_Help::AddHelpTopic( "VertexPerPoly Selection", g_aszVertexPerPolySelectionHelpStrings );
}


void Tools_VertexPerPoly_Selection::Deactivate()
{
	
	// currently it is reset every time it is deactivated
	DeselectAll();

	Tools_Help::RemoveHelpTopic( "VertexPerPoly Selection" );
	CloseSelectionOverlay();

	s_bActive = false;
}


void Tools_VertexPerPoly_Selection::TransferModeData( int iMode )
{
	//open the file
	Tools_ModeDataFile xFile( "VertexPerPolySelection.dat", iMode );

	bool bJunk = false;
	if( false == xFile.GetError())
	{
		// order is important here
		xFile.Transfer( s_xSelectionOverlayPosition );
		xFile.Transfer(bJunk);
		xFile.Transfer( s_uSelectionOverlayMinimised );
	}
}


void Tools_VertexPerPoly_Selection::Update( int eUpdateMode )
{

	//Flag the selection undo to start a new undo batch
	s_xSelectionUndo.MarkUndoStart();

	//if the mouse button has been release , reset the ButtonHeldForSelection flag
	if( !Asura_UserInput::KeyPressed( ASURA_KEYID_MOUSEBUTTON1 ) )
	{
		s_bButtonDownForSelection = false;
	}

	//reset the highlit vertex
	s_xHighlitVertexPerPoly.m_iModuleIndex = -1;
	s_xHighlitPolygon.ModuleIndex = -1;
	
	if( eUpdateMode != VertexPerPolySelectionUpdate_NoSelection && !Tools_Prompted_Selection::IsSelecting() )
	{
		//act upon keyboard input
		HandleKeyboard();

		if ( eUpdateMode == VertexPerPolySelectionUpdate_Standard )
		{
			//and handle selection using the mouse
			HandleMouseSelection();
		}
	}
	
}


void Tools_VertexPerPoly_Selection::Render()
{
	//Show the currently selected polygons
	if( s_bShowSelection )
	{
		HighlightSelection();
	}

	if ( s_iSelectionMode == VPSelectionMode_Polygon )
	{
		if( s_xHighlitPolygon.ModuleIndex >= 0 )
		{
			HighlightPolygon( s_xHighlitPolygon );
		}
	}
	else
	{
		if( s_xHighlitVertexPerPoly.m_iModuleIndex >= 0 )
		{
			HighlightVertexPerPoly( s_xHighlitVertexPerPoly );
		}
	}

}


///////////////////////////////////////////////////////////////////////////////////////
// Tools_VertexPerPoly_Selection Overlay
///////////////////////////////////////////////////////////////////////////////////////


void Tools_VertexPerPoly_Selection::ToggleSelectionOverlay()
{
	s_bSelectionOverlayOpen = !s_bSelectionOverlayOpen;

	if ( s_bSelectionOverlayOpen )
	{
		s_uSelectionOverlayMinimised = 0;
		CreateSelectionOverlay();
	}
	else
	{
		CloseSelectionOverlay();
	}
}


bool Tools_VertexPerPoly_Selection::IsSelectionOverlayOn()
{
	return s_bSelectionOverlayOpen;
}


void Tools_VertexPerPoly_Selection::CreateSelectionOverlay()
{
	if ( ( !s_bSelectionOverlayOpen ) || ( Asura_Overlay_System::DoesOverlayExist( TOOLS_OVERLAY_VERTEXPERPOLY_SELECTION ) ) )
	{
		return;
	}

	//strings for selection mode options
	static char* s_aszSelectionModeStrings[] =
	{
		"VertexPerPoly",
		"Polygon",
		"Object",
	};

	static char* s_aszSelectionModeHelpStrings[] =
	{
		"Selects a single VertexPerPoly.",
		"Selects all the VertexPerPolys in a polygon.",
		"Selects all the VertexPerPolys in a module.",
	};


	Asura_Overlay* pxOverlay;
	pxOverlay = new Asura_Overlay( "Selection", false, &s_xSelectionOverlayPosition, &s_uSelectionOverlayMinimised );
	
	Asura_Dialog* pxDialog;
	Asura_Vector_2 xOffset = Asura_Vector_2( 1.0f, 3.0f );

	//heading for selection mode list box
	pxDialog = new Asura_Dialog( "Selection Mode :", xOffset );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += 1.0f;

	//selection mode list box
	Asura_List_Dialog* pxList = new Asura_List_Dialog( xOffset, s_aszSelectionModeStrings, &s_iSelectionModeListOffset, &s_iSelectionMode, 3, 3, NULL );
	pxDialog = pxList;
	pxList->SetListHelpStrings( s_aszSelectionModeHelpStrings );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += 4.2f;
	
	pxDialog = new Asura_Tickbox_Dialog( "Lock Selection", xOffset, &s_bSelectionLocked );
	pxDialog->SetHelpText( "Disables all controls for changing the current selection." );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Tickbox_Dialog( "Show Selection", xOffset, &s_bShowSelection );
	pxDialog->SetHelpText( "Highlight currently selected VertexPerPolys with a red outline." );
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::LargeSpacing();

	pxDialog = new Asura_Function_Dialog( "Select All", xOffset, SelectAll);
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Function_Dialog( "Clear Selection (L)", xOffset, DeselectAll);
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::DefaultSpacing();
	
	pxDialog = new Asura_Function_Dialog( "Undo (Shift+Z)", xOffset, Undo);
	pxDialog->SetHelpText( "VertexPerPoly selection undo." );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Function_Dialog( "Redo (Shift+Y)", xOffset, Redo);
	pxDialog->SetHelpText( "VertexPerPoly selection redo." );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::DefaultSpacing();
	
	pxOverlay->m_uID = TOOLS_OVERLAY_VERTEXPERPOLY_SELECTION;

	Asura_Overlay_System::SubmitNewOverlay( pxOverlay, false );
}


void Tools_VertexPerPoly_Selection::CloseSelectionOverlay()
{
	if ( Asura_Overlay_System::DoesOverlayExist( TOOLS_OVERLAY_VERTEXPERPOLY_SELECTION ) ) 
	{
		Asura_Overlay_System::CloseOverlays( TOOLS_OVERLAY_VERTEXPERPOLY_SELECTION );
	}
}


///////////////////////////////////////////////////////////////////////////////////////
// Tools_VertexPerPoly_Selection Overlay
///////////////////////////////////////////////////////////////////////////////////////


const int Tools_VertexPerPoly_Selection::CountSelectedVertexPerPolys()
{
	int iCount = 0;
	for( LIF<ModuleVertexPerPolyTriplet> xLIF( &s_xSelectionList ); !xLIF.done(); xLIF.next() )
	{
		iCount++;
	}
	return iCount;
}


void Tools_VertexPerPoly_Selection::SelectVertexPerPoly( int iModule, int iPoly, int iVert, bool bAllowUndo )
{
	ModuleVertexPerPolyTriplet xVertexPerPoly( iModule, iPoly, iVert );
	if ( !s_xSelectionList.contains( xVertexPerPoly ) )
	{
		s_xSelectionList.add_entry( xVertexPerPoly );
		if ( bAllowUndo )
		{
			s_xSelectionUndo.LogVertexPerPolySelected( iModule, iPoly, iVert );
		}
	}
}


void Tools_VertexPerPoly_Selection::DeselectVertexPerPoly( int iModule, int iPoly, int iVert, const bool bAllowUndo )
{
	ModuleVertexPerPolyTriplet xVertexPerPoly( iModule, iPoly, iVert );
	
	if ( s_xSelectionList.contains( xVertexPerPoly ) )
	{
		s_xSelectionList.delete_entry( xVertexPerPoly );
		if ( bAllowUndo )
		{
			s_xSelectionUndo.LogVertexPerPolyDeselected( iModule, iPoly, iVert );
		}
	}
}


void Tools_VertexPerPoly_Selection::SelectPolygon( int iModuleIndex, int iPolygonIndex )
{
	const Asura_Mesh* const pxMesh = Asura_Module_System::GetMeshForModule( iModuleIndex );
	Asura_Assert( iPolygonIndex >= 0 && iPolygonIndex < pxMesh->NumberOfPolygons, "" );

	const Asura_Mesh_Polygon* const pxPoly = &pxMesh->PolygonDataPtr[ iPolygonIndex ];
	const int iNumVerts = pxPoly->NumberOfVertices();

	for( int i = 0; i < iNumVerts; i++ )
	{
		SelectVertexPerPoly( iModuleIndex, iPolygonIndex, i );
	}
}


void Tools_VertexPerPoly_Selection::DeselectPolygon( int iModuleIndex, int iPolygonIndex )
{
	const Asura_Mesh* const pxMesh = Asura_Module_System::GetMeshForModule( iModuleIndex );
	Asura_Assert( iPolygonIndex >= 0 && iPolygonIndex < pxMesh->NumberOfPolygons, "" );

	const Asura_Mesh_Polygon* const pxPoly = &pxMesh->PolygonDataPtr[ iPolygonIndex ];
	const int iNumVerts = pxPoly->NumberOfVertices();

	for( int i = 0; i < iNumVerts; i++ )
	{
		DeselectVertexPerPoly( iModuleIndex, iPolygonIndex, i );
	}
}


void Tools_VertexPerPoly_Selection::SelectObject( int iModuleIndex )
{
	const Asura_Mesh* const pxMesh = Asura_Module_System::GetMeshForModule( iModuleIndex );
	for ( int i = 0; i < pxMesh->NumberOfPolygons; i++ )
	{
		SelectPolygon( iModuleIndex, i );
	}
}



void Tools_VertexPerPoly_Selection::DeselectObject( int iModuleIndex )
{
	const Asura_Mesh* const pxMesh = Asura_Module_System::GetMeshForModule( iModuleIndex );
	for ( int i = 0; i < pxMesh->NumberOfPolygons; i++ )
	{
		DeselectPolygon( iModuleIndex, i );
	}
}


void Tools_VertexPerPoly_Selection::SelectAll()
{
	const int iNumberOfModules = Asura_Module_System::GetNumberOfModules();
	for ( int i = 0; i < iNumberOfModules; i++ )
	{
		SelectObject( i );
	}
}


void Tools_VertexPerPoly_Selection::DeselectAll()
{
	while ( s_xSelectionList.size() > 0 )
	{
		ModuleVertexPerPolyTriplet& xVertexPerPoly = s_xSelectionList.first_entry();
		DeselectVertexPerPoly( xVertexPerPoly.m_iModuleIndex, xVertexPerPoly.m_iPolyIndex, xVertexPerPoly.m_iVertexIndex );
	}
}


///////////////////////////////////////////////////////////////////////////////////////
// Tools_VertexPerPoly_Selection Update functions
///////////////////////////////////////////////////////////////////////////////////////


void Tools_VertexPerPoly_Selection::HandleKeyboard()
{

	if ( ( Asura_Overlay_System::OverlaysHaveKeyboardFocus() ) || ( Asura_UserInput::KeyPressed( ASURA_KEYID_ALT ) ) )
	{
		return;
	}
	
	if( Asura_UserInput::KeyPressed( ASURA_KEYID_CTRL ) )
	{
	}
	else if( Asura_UserInput::KeyPressed( ASURA_KEYID_SHIFT ) )
	{
		if( Asura_UserInput::DebouncedKeyPressed( 'z' ) || Asura_UserInput::DebouncedKeyPressed( ',' )) // 'shift+z' or 'shift+<' for selection undo
		{
			Undo();
		}
		if ( Asura_UserInput::DebouncedKeyPressed( 'y' ) || Asura_UserInput::DebouncedKeyPressed( '.' )) // 'shift+y' or 'shift+>' for selection redo
		{
			Redo();
		}
	}
	else
	{
		if ( Asura_UserInput::DebouncedKeyPressed( 'l' ) ) // 'L' for clear selection
		{
			DeselectAll();
		}
	}
}


void Tools_VertexPerPoly_Selection::HandleMouseSelection()
{
	// If the user is doing anything with overlays or menus,
	// ignore any mousebutton/key presses etc. 
	// or locked
	if ( ( Asura_Interface::UsingMenusOrOverlays() ) || ( s_bSelectionLocked ) )
	{
		return;
	}
	
	//see if the mouse is over a vertex
	ModuleVertexPerPolyTriplet xVertexPerPoly;
	const bool bOverVertexPerPoly = GetVertexPerPolyUnderMouse( xVertexPerPoly );

	PolygonID xPoly;
	const bool bOverPoly = Tools_Polygon_Selection::GetPolygonUnderMouse( xPoly );

	if ( bOverVertexPerPoly ) 		
	{
		s_xHighlitVertexPerPoly = xVertexPerPoly;
	}

	if ( bOverPoly ) 		
	{
		s_xHighlitPolygon = xPoly;
	}

	if ( ( !Asura_UserInput::DebouncedKeyPressed( ASURA_KEYID_MOUSEBUTTON1 ) ) && ( !s_bButtonDownForSelection ) )
	{
		return;
	}

	s_bButtonDownForSelection = true;

	if (
		( ( s_iSelectionMode + s_iSelectionModeListOffset == VPSelectionMode_VertexPerPoly ) && ( !bOverVertexPerPoly ) ) ||
		( ( s_iSelectionMode + s_iSelectionModeListOffset != VPSelectionMode_VertexPerPoly ) && ( !bOverPoly ) )
		)
	{
		return;
	}

	if ( Asura_UserInput::KeyPressed( ASURA_KEYID_SHIFT ) )
	{
		switch( s_iSelectionMode + s_iSelectionModeListOffset )
		{
			case VPSelectionMode_VertexPerPoly :
				DeselectVertexPerPoly( xVertexPerPoly.m_iModuleIndex, xVertexPerPoly.m_iPolyIndex, xVertexPerPoly.m_iVertexIndex );
				break;
			case VPSelectionMode_Polygon :
				DeselectPolygon( xPoly.ModuleIndex, xPoly.PolyIndex );
				break;
			case VPSelectionMode_Object :
				DeselectObject( xPoly.ModuleIndex );
				break;
		}
	}
	else
	{
		switch( s_iSelectionMode + s_iSelectionModeListOffset )
		{
			case VPSelectionMode_VertexPerPoly :
				SelectVertexPerPoly( xVertexPerPoly.m_iModuleIndex, xVertexPerPoly.m_iPolyIndex, xVertexPerPoly.m_iVertexIndex );
				break;
			case VPSelectionMode_Polygon :
				SelectPolygon( xPoly.ModuleIndex, xPoly.PolyIndex );
				break;
			case VPSelectionMode_Object :
				SelectObject( xPoly.ModuleIndex );
				break;
		}
	}
}


bool Tools_VertexPerPoly_Selection::GetVertexPerPolyUnderMouse( ModuleVertexPerPolyTriplet& xVertexPerPoly )
{
	Asura_Vector_3 xPosition;
	int iModule;
	int iVertModule;
	int iPoly;
	int iVert;

	const bool bDonePoly = Tools_LOS::FindPolyAndPositionUnderCursor( iPoly, iModule, xPosition );
	if ( !bDonePoly )
	{
		return false;
	}

	const bool bDoneVert = Tools_LOS::FindVertUnderCursor( iVert, iVertModule );
	if ( !bDoneVert )
	{
		return false;
	}

	if ( iVertModule != iModule )
	{
		return false;
	}

	int iVertIndex = -1;

	Asura_Mesh* pxMesh = Asura_Module_System::GetMeshForModule( iModule );
	for ( int i = 0; i < pxMesh->PolygonDataPtr[ iPoly ].NumberOfVertices(); i++ )
	{
		if ( pxMesh->PolygonDataPtr[ iPoly ].VertexID[ i ] == iVert )
		{
			iVertIndex = i;
		}
	}

	if ( iVertIndex < 0 )
	{
		return false;
	}

	xVertexPerPoly.m_iModuleIndex = iModule;
	xVertexPerPoly.m_iPolyIndex = iPoly;
	xVertexPerPoly.m_iVertexIndex = iVertIndex;
	return true;
}


bool Tools_VertexPerPoly_Selection::GetHighlitVertexPerPoly( ModuleVertexPerPolyTriplet& xVertexPerPoly )
{
	if ( s_xHighlitVertexPerPoly.m_iModuleIndex < 0 )
	{
		return false;
	}
	
	xVertexPerPoly = s_xHighlitVertexPerPoly;
	return true;
}


///////////////////////////////////////////////////////////////////////////////////////
// Tools_Vertex_Selection render
///////////////////////////////////////////////////////////////////////////////////////


void Tools_VertexPerPoly_Selection::HighlightSelection()
{
	for( LIF<ModuleVertexPerPolyTriplet> xLIF( &s_xSelectionList ); !xLIF.done(); xLIF.next() )
	{
		ModuleVertexPerPolyTriplet& xVertexPerPoly = xLIF();
		Tools_Render::RenderVertexPerPoly( xVertexPerPoly.m_iModuleIndex, xVertexPerPoly.m_iPolyIndex, xVertexPerPoly.m_iVertexIndex, 0xffff0000 );
	}
}


void Tools_VertexPerPoly_Selection::HighlightVertexPerPoly( ModuleVertexPerPolyTriplet& xVertexPerPoly )
{
	if ( !Tools_Render::HighlightPolyOrObjectUnderCursor ) 
	{
		return;
	}

	float fAlpha = Asura_Maths::Sine( Asura_Timers::GetLocalUnscaledTime() * 2.0f );
	fAlpha = 255.0f * fAlpha * fAlpha;
	const unsigned int uColour = 0x00ffffff | ( Asura_Maths::FloatToInt( fAlpha ) << 24 );
	
	Tools_Render::RenderVertexPerPoly( xVertexPerPoly.m_iModuleIndex, xVertexPerPoly.m_iPolyIndex, xVertexPerPoly.m_iVertexIndex, uColour );
}


void Tools_VertexPerPoly_Selection::HighlightPolygon( PolygonID& xPolygon )
{
	if ( !Tools_Render::HighlightPolyOrObjectUnderCursor ) 
	{
		return;
	}

	Asura_Mesh* pxMesh = Asura_Module_System::GetMeshForModule( xPolygon.ModuleIndex );
	if ( xPolygon.PolyIndex >= pxMesh->NumberOfPolygons ) 
	{
		return;
	}

	float fAlpha = Asura_Maths::Sine( Asura_Timers::GetLocalUnscaledTime() * 2.0f );
	fAlpha = 255.0f * fAlpha * fAlpha;
	const unsigned int uColour = 0x00ffffff | ( Asura_Maths::FloatToInt( fAlpha ) << 24 );
	
	Tools_Render::RenderPolygonOutline( xPolygon.PolyIndex, xPolygon.ModuleIndex, uColour, true );

	for ( int i = 0; i < pxMesh->PolygonDataPtr[ xPolygon.PolyIndex ].NumberOfVertices(); i++ )
	{
		Tools_Render::RenderVertexPerPoly( xPolygon.ModuleIndex, xPolygon.PolyIndex, i, uColour );
	}

}

void Tools_VertexPerPoly_Selection::HandleMeshChange(int iModuleIndex)
{
	//Just going to clear the selection and undo for now. RAR 14/03/2007
	while(s_xSelectionList.size()) s_xSelectionList.delete_first_entry();
	s_xSelectionUndo.FlushUndoBuffer();
	s_xHighlitVertexPerPoly.m_iModuleIndex = -1;
	
}

void Tools_VertexPerPoly_Selection::DeleteModule(int iModuleIndex)
{
	//Just going to clear the selection and undo for now. RAR 14/03/2007
	while(s_xSelectionList.size()) s_xSelectionList.delete_first_entry();
	s_xSelectionUndo.FlushUndoBuffer();
	s_xHighlitVertexPerPoly.m_iModuleIndex = -1;
}