
//////////////////////////////////////////////////////////////////////////////
//
// Tools_EntityNode_LiftSpline.cpp
//
// Copyright (c) 2006 Rebellion. All rights reserved.
//
// Description:
//
//     spline class for lift entities to follow
//
//////////////////////////////////////////////////////////////////////////////

// I N C L U D E S ///////////////////////////////////////////////////////////

#include "Core/Asura.h"

// This file's header.
#include "Entity/Locations/Spline/LiftSpline/Tools_EntityNode_LiftSpline.h"

// asura
#include "Camera/Asura_Camera.h"
#include "Core/Asura_Timers.h"
#include "Entity/Asura_Entity_Classification.h"
#include "Interface/Asura_Dialog.h"
#include "Interface/Asura_Graph_Dialog.h"
#include "Interface/Asura_Overlay.h"
#include "Interface/Asura_Overlay_System.h"
#include "Rendering/Asura_Render.h"

//platform asura
#include "Rendering/Asura_PlatformRenderObject.h"

//tools
#include "Entity/Locations/OrientedNode/Asura_ServerNode_OrientedNode.h"
#include "Entity/Locations/OrientedNode/LiftNode/Tools_EntityNode_LiftNode.h"
#include "Entity/Locations/Spline/Tools_EntityNode_Spline.h"
#include "Entity/Locations/Spline/Tools_Object_SplinePoint.h"
#include "Entity/Locations/Spline/LiftSpline/Tools_Object_LiftSplinePoint.h"
#include "Load&Save/Tools_SaveAsura.h"
#include "Misc/Tools_Timed_Messages.h"
#include "Objects/Tools_Object_System.h"

//////////////////////////////////////////////////////////////////////////////
//
// Tools_EntityNode_LiftSpline
//
//////////////////////////////////////////////////////////////////////////////

bool                         Tools_EntityNode_LiftSpline::s_bChangedSpeedGraph = false;
Tools_EntityNode_LiftSpline* Tools_EntityNode_LiftSpline::s_pxThisToolsLiftSpline = NULL;

Tools_EntityNode_LiftSpline::Tools_EntityNode_LiftSpline(Asura_Entity* pxEntity)
: PARENT(pxEntity)
{
	Type = TOT_Entity_LiftSpline;

    Asura_ServerNode_LiftSpline* pxLiftSplineNode = GetGameLiftSpline();
    Asura_Assert( pxLiftSplineNode->IsBaseOrDerivativeOf( AsuraEntityClass_LiftSpline ),
        "Tools_EntityNode_LiftSpline::Tools_EntityNode_LiftSpline - wrong entity type" );

    // Fill in the data from Asura.
    m_bTakeOrientationFromPoints = pxLiftSplineNode->TakeOrientationFromPoints();
	m_bOverrideDuration = pxLiftSplineNode->GetOverrideDurationFlag();
	m_fDurationOverride = pxLiftSplineNode->GetTotalLinkTime();
	m_fLength = pxLiftSplineNode->GetTotalLength();
	m_bDistanceVsTimeGraph = pxLiftSplineNode->GetDistanceVsTimeGraph();
    CreateAllToolsPathObjects( -1, false );

    m_bChanged = false;
}

bool Tools_EntityNode_LiftSpline::IsBaseOrDerivativeOf( int iToolsObjectType ) const
{
    if ( iToolsObjectType == TOT_Entity_LiftSpline )
    {
        return true;
    }
    else
    {
        return PARENT::IsBaseOrDerivativeOf( iToolsObjectType );
    }
}

void Tools_EntityNode_LiftSpline::OnSelection()
{
    s_pxThisToolsLiftSpline = this;

	Asura_ServerNode_LiftSpline* pxGameSpline = GetGameLiftSpline();
	// seems to be the only place I can tell if one of tyhe spline points have moved
	if (pxGameSpline && m_fLength != pxGameSpline->GetTotalLength())
	{
		m_fLength = pxGameSpline->GetTotalLength();

		m_fDurationOverride = pxGameSpline->GetTotalLinkTime();

	}
	CreateOverlay();


    PARENT::OnSelection();
}

void Tools_EntityNode_LiftSpline::OnDeselection()
{
	PARENT::OnDeselection();

    s_pxThisToolsLiftSpline = NULL;
}

void Tools_EntityNode_LiftSpline::UpdateWhileSelected()
{
    PARENT::UpdateWhileSelected();

    Asura_ServerNode_LiftSpline* pxGameSpline = GetGameLiftSpline();

    if ( m_bChanged || s_bChangedSpeedGraph)
    {
        //update the asura data
        if (pxGameSpline->TakeOrientationFromPoints() && !m_bTakeOrientationFromPoints)
        {
        	YesNo_Overlay xAreYouSure("Point orientation data will be lost. Are you sure?");
        	if (!xAreYouSure.DoModal())
        	{
        		m_bTakeOrientationFromPoints = true;
        	}
        }
		if (pxGameSpline->TakeOrientationFromPoints() != m_bTakeOrientationFromPoints)
		{
			CreateOverlay();
		}
        pxGameSpline->EnableTakeOrientationFromPoints( m_bTakeOrientationFromPoints );
		if (pxGameSpline->GetOverrideDurationFlag() != m_bOverrideDuration)
		{
			CreateOverlay();
		}
		if (pxGameSpline->GetDistanceVsTimeGraph() != m_bDistanceVsTimeGraph)
		{
			pxGameSpline->SetDistanceVsTimeGraph(m_bDistanceVsTimeGraph);
			;
			CreateOverlay();
		}

		pxGameSpline->SetOverrideDurationFlag( m_bOverrideDuration );
		if (m_bOverrideDuration || m_bDistanceVsTimeGraph)
			pxGameSpline->SetOverrideDurationValue( m_fDurationOverride );
		else
			m_fDurationOverride = pxGameSpline->GetTotalLinkTime();

		m_fLength = pxGameSpline->GetTotalLength();

        m_bChanged = false;
        SetEntityModified();
    }

    if ( s_bChangedSpeedGraph )
    {
		s_bChangedSpeedGraph = false;

		pxGameSpline->OnChanged();

		m_fDurationOverride = pxGameSpline->GetTotalLinkTime();
		m_fLength = pxGameSpline->GetTotalLength();

        SetEntityModified();

		if (m_pxGraphDialog)
		{
			u_int uNumLinks = pxGameSpline->GetNumberOfPoints() - 2;
			m_pxGraphDialog->m_pxGraphGadget->SetUseCustomXGridLines(uNumLinks);
			Asura_Graph_Gadget< float >::CustomGridline* pxGridLines = m_pxGraphDialog->m_pxGraphGadget->GetCustomXGridlines();

			for(int i = 1; i < (int)(uNumLinks) - 1 ; ++i)
			{
				float fDistance = pxGameSpline->GetCumulativeLength(i);
				float fProp = pxGameSpline->GetProportionAlongSpline(fDistance);
				float fTime = pxGameSpline->GetTimeFromProportion(fProp);
				pxGridLines[ i - 1 ].m_fValue = (fTime / pxGameSpline->GetTotalLinkTime());
			}
		}
    }
}

void Tools_EntityNode_LiftSpline::AddOverlayControls( Asura_Overlay* pxNewOverlay, Asura_Vector_2& xOffset )
{
	PARENT::AddOverlayControls(pxNewOverlay,xOffset);
	xOffset.y += Asura_Dialog::LargeSpacing() - Asura_Dialog::DefaultSpacing();

	Tools_EntityNode_Spline::AddSplineOverlayControls( pxNewOverlay, xOffset );
	xOffset.y += Asura_Dialog::LargeSpacing() - Asura_Dialog::DefaultSpacing();

	AddSplineEventOverlayControls(pxNewOverlay, xOffset);
	xOffset.y += Asura_Dialog::LargeSpacing() - Asura_Dialog::DefaultSpacing();

	Asura_Dialog* pxNewDialog;

	// Orientation from points tickbox
	pxNewDialog = new Asura_Tickbox_Dialog("Take orientation from points", xOffset, &m_bTakeOrientationFromPoints, &m_bChanged);
	pxNewDialog->SetHelpText("Take orientation from the orientation of the track points instead of from the movement direction.");
	pxNewOverlay->AddDialog(pxNewDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();

	if (m_bTakeOrientationFromPoints)
	{
		// Default orientation options
		pxNewDialog = new Asura_Function_Dialog("Set to default orientations", xOffset, SetToDefaultOrientations, &m_bChanged);
		pxNewDialog->SetHelpText("Set the orientation of the track points to the direction of movement.");
		pxNewOverlay->AddDialog(pxNewDialog);
		xOffset.y += Asura_Dialog::DefaultSpacing();
	}

	pxNewDialog = new Asura_Tickbox_Dialog("Distance Vs Time", xOffset, &m_bDistanceVsTimeGraph, &s_bChangedSpeedGraph);
	pxNewDialog->SetHelpText("Change whether the below graph is distance vs time. Otherwise it is speed vs time.");
	pxNewOverlay->AddDialog(pxNewDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();

	// Override duration tickbox.
	if (!m_bDistanceVsTimeGraph)
	{
		pxNewDialog = new Asura_Tickbox_Dialog("Override Duration", xOffset, &m_bOverrideDuration, &s_bChangedSpeedGraph);
		pxNewDialog->SetHelpText("Override how long the lift takes to traverse this spline with a fixed time. Note that speed values on the graph will then become relative.");
		pxNewOverlay->AddDialog(pxNewDialog);
		xOffset.y += Asura_Dialog::DefaultSpacing();
	} 

	pxNewDialog = new Asura_Numerical_Dialog("Duration", xOffset, &m_fDurationOverride, 0.1f, 500.0f, 0.1f, "%.1f", &s_bChangedSpeedGraph);
	pxNewDialog->SetHelpText("The lift will take this amount of time to traverse this spline.");
	static_cast<Asura_Numerical_Dialog*>(pxNewDialog)->SetReadOnly(!(m_bOverrideDuration || m_bDistanceVsTimeGraph));
	pxNewOverlay->AddDialog(pxNewDialog);
	xOffset.x += 20;

	pxNewDialog = new Asura_Numerical_Dialog("Length", xOffset, &m_fLength, 0.1f, 500.0f, 0.1f, "%.1f", &s_bChangedSpeedGraph);
	pxNewDialog->SetHelpText("This is the total length of this spline.");
	static_cast<Asura_Numerical_Dialog*>(pxNewDialog)->SetReadOnly(true);
	pxNewOverlay->AddDialog(pxNewDialog);

	xOffset.y += Asura_Dialog::DefaultSpacing();
	xOffset.x -= 20;

	if (!m_bDistanceVsTimeGraph)
	{
		// Use speed from end of last link.
		pxNewDialog = new Asura_Function_Dialog("Auto-Set start speed", xOffset, AutoSetStartSpeed, NULL, CanAutoSetStartSpeed);
		pxNewDialog->SetHelpText("Automatically sets the start speed of this link to the end speed of the previous link");
		pxNewOverlay->AddDialog(pxNewDialog);
		xOffset.x += 20.0f;

		// Use speed from start of next link.
		pxNewDialog = new Asura_Function_Dialog("Auto-Set end speed", xOffset, AutoSetEndSpeed, NULL, CanAutoSetEndSpeed);
		pxNewDialog->SetHelpText("Automatically sets the end speed of this link to the start speed of the next link");
		pxNewOverlay->AddDialog(pxNewDialog);
		xOffset.x -= 20.0f;
		xOffset.y += Asura_Dialog::DefaultSpacing();
	}



    Asura_ServerNode_LiftSpline* pxGameSpline  = GetGameLiftSpline();
	Asura_Graph_Dialog<float>*   pxGraphDialog = NULL;
	if (m_bDistanceVsTimeGraph)
	{
		// Speed over time graph.
		pxGraphDialog = new Asura_Graph_Dialog<float>("Position", xOffset, pxGameSpline->GetSpeedOverTimeGraph(), 0.0f, 1.0f, &s_bChangedSpeedGraph);
		pxGraphDialog->SetHelpText( "Spline Position/Time Graph" );
		pxGraphDialog->m_pxGraphGadget->AdjustToFit(false, true);
	}
	else
	{
		// Speed over time graph.
		pxGraphDialog = new Asura_Graph_Dialog<float>("Speed", xOffset, pxGameSpline->GetSpeedOverTimeGraph(), 0.0f, 10.0f, &s_bChangedSpeedGraph);
		pxGraphDialog->SetHelpText( "Spline Speed/Time Graph" );
		pxGraphDialog->m_pxGraphGadget->AdjustToFit(false, true);
	}
	if ( pxGraphDialog )
	{
		u_int uNumLinks = pxGameSpline->GetNumberOfPoints() - 2;
		pxGraphDialog->m_pxGraphGadget->SetUseCustomXGridLines(uNumLinks);
		Asura_Graph_Gadget< float >::CustomGridline* pxGridLines = pxGraphDialog->m_pxGraphGadget->GetCustomXGridlines();

		for(int i = 1; i < (int)(uNumLinks) - 1 ; ++i)
		{
			float fDistance = pxGameSpline->GetCumulativeLength(i);
			float fProp = pxGameSpline->GetProportionAlongSpline(fDistance);
			float fTime = pxGameSpline->GetTimeFromProportion(fProp);
			pxGridLines[ i - 1 ].m_fValue = (fTime / pxGameSpline->GetTotalLinkTime());
		}

		m_pxGraphDialog = pxGraphDialog;
		pxNewOverlay->AddDialog(pxGraphDialog);
		xOffset.y = pxGraphDialog->m_xMaxCoord.y;
	}
}

void Tools_EntityNode_LiftSpline::Render()
{
    const Asura_ServerNode_Spline* pxSpline = GetGameLiftSpline();
    UpdateToolsSpline(pxSpline->GetSourceGuid(), pxSpline->GetTargetGuid());
    const unsigned uColour = 0xFFFFFF00;
    RenderPath(uColour);
    // Render the line that links the nodes.
    Asura_Render::RenderLine(m_xSourceNodePosition,m_xTargetNodePosition,uColour);
    Tools_Entity_Node::Render();
}

Tools_EntityNode_LiftSpline* Tools_EntityNode_LiftSpline::CreateAndReturn(Asura_Guid uStartGuid, Asura_Guid uEndGuid)
{
    Asura_ServerEntity_Node* pxSourceNode = Asura_ServerEntity_Node::GetList()->FindEntity( uStartGuid );
    //Asura_ServerEntity_Node* pxTargetNode = Asura_ServerEntity_Node::GetList().FindEntity( uEndGuid );

	// Create the game object.
    // Get a new GUID
    const Asura_Guid uGuid = Asura_Entity_System::GetCreatedByToolsGuid();

    // Set up tools data and auto-create a unique name (prompt for new name if there is a clash).
    Tools_Entity_Data* pxToolsData = CreateToolsDataWithDefaultName( "Lift Spline", "Lift Spline", uGuid, GetNamePrefix() );
    if ( !pxToolsData ) { return(NULL); }

    // Create the game specfic server object and set its data.
    Asura_ServerNode_LiftSpline* pxGameNode = new Asura_ServerNode_LiftSpline( uGuid );
    if ( !pxGameNode ) { return(NULL); }

    pxGameNode->ToolsData = pxToolsData;
    Asura_Vector_3 xPosition;
    GetSplineRenderPosition(xPosition, uStartGuid, uEndGuid);
    pxGameNode->SetPosition( xPosition );
    pxGameNode->SetSourceGuid(uStartGuid);
    pxGameNode->SetTargetGuid(uEndGuid);
    // (NY - 11.04.2007) will assume most lifts won't want to be locked to zero orientation...
	pxGameNode->EnableTakeOrientationFromPoints(true);
    pxGameNode->CreateBasePoints();

	pxSourceNode->AddNewSpline( pxGameNode->GetGuid() );

	// Create the tools object.
	Tools_EntityNode_LiftSpline* pxToolsObject = new Tools_EntityNode_LiftSpline( pxGameNode );
    if ( !pxToolsObject ) { return(NULL); }

    pxToolsObject->Position = pxGameNode->GetPosition();

    Tools_Object_System::SelectObject( pxToolsObject );

    Tools_Timed_Message_System::AddMessage( Tools_Timed_Message_System::COLOUR_DEFAULT, "Created new Lift Spline" );
    Tools_SaveAsura::SetEntityModified();

	return (pxToolsObject);
}

void Tools_EntityNode_LiftSpline::CreateAllToolsPathObjects( const int iSelectIndexAfter /*= -1*/, const bool bShowEndPoints /*= true*/ )
{
	// Remove all of the old tools objects.
	RemoveAllToolsPathObjects();	

    // Create the tools objects for the link points.
    Asura_ServerNode_LiftSpline* pxGameSpline = GetGameLiftSpline();
	for (u_int u = 1; u < pxGameSpline->GetNumberOfPoints() - 1; ++u)
	{
		const bool bIsEndPoint = (u == 1 || u == pxGameSpline->GetNumberOfPoints() - 2);
		Tools_Object_LiftSplinePoint* pxPoint = new Tools_Object_LiftSplinePoint(pxGameSpline, this, u, bIsEndPoint);
		m_xListAttachedPoints.add_entry(pxPoint);

		pxPoint->Position = pxGameSpline->GetPointPosition(u);
		pxGameSpline->GetLinkOrientation(u).ToMatrix(pxPoint->Orientation);

		if ( iSelectIndexAfter + 1 == static_cast< int >( u ) )
		{
			Tools_Object_System::SelectObject(pxPoint, false);
		}
		else if ( !bShowEndPoints && bIsEndPoint )
		{
			pxPoint->SetHiddenFlag( ObjectHideFlag_User, true );
		}
	}
}

void Tools_EntityNode_LiftSpline::SetToDefaultOrientations()
{
	s_pxThisToolsLiftSpline->SetPointsToDefaultOrientations();
}

void Tools_EntityNode_LiftSpline::AutoSetStartSpeed()
{
    Asura_ServerNode_LiftSpline* pxGameSpline = s_pxThisToolsLiftSpline->GetGameLiftSpline();

    Asura_ServerEntity_Node* pxSourceNode = Asura_ServerEntity_Node::GetList()->FindEntity( pxGameSpline->GetSourceGuid() );
	Asura_Assert(pxSourceNode, "Failed to find node");
    if ( !pxSourceNode || pxGameSpline->GetDistanceVsTimeGraph() ) { return; }
	if (pxSourceNode->IsBaseOrDerivativeOf( AsuraEntityClass_LiftNode ))
	{
        for ( Asura_Hashed_List_It< Asura_ServerEntity_Node > xNodeIter( Asura_ServerEntity_Node::GetList() ); !xNodeIter.Done(); xNodeIter.Next() )
        {
            Asura_ServerEntity_Node* pxNode = xNodeIter.GetCurrent();
            if ( pxNode->IsBaseOrDerivativeOf( AsuraEntityClass_LiftSpline ) )
            {
                Asura_ServerNode_LiftSpline* pxLiftSpline = static_cast< Asura_ServerNode_LiftSpline* >( pxNode );
                if ( pxLiftSpline->GetTargetGuid() == pxSourceNode->GetGuid() )
                {
                    float fStartSpeed = pxLiftSpline->GetSpeedOverTimeGraph()->GetValueAtTime(1.0f);
                    Asura_Graph_Point<float> *pxGraphPoints = pxGameSpline->GetSpeedOverTimeGraph()->GetControlPoints();
                    pxGraphPoints->m_pxNext->m_xValue = fStartSpeed * pxGameSpline->GetVelocityMultiplier();
                    pxGameSpline->GetSpeedOverTimeGraph()->Update();
					s_pxThisToolsLiftSpline->m_fDurationOverride = pxGameSpline->GetTotalLinkTime();
					s_pxThisToolsLiftSpline->m_fLength = pxGameSpline->GetTotalLength();
                    return;
                }
            }
        }
	}
	Asura_Assert(false, "Shouldn't get here");
}

bool Tools_EntityNode_LiftSpline::CanAutoSetStartSpeed()
{
    Asura_ServerNode_LiftSpline* pxGameSpline = s_pxThisToolsLiftSpline->GetGameLiftSpline();

    Asura_ServerEntity_Node* pxSourceNode = Asura_ServerEntity_Node::GetList()->FindEntity( pxGameSpline->GetSourceGuid() );
	Asura_Assert(pxSourceNode, "Failed to find node");
    if (!pxSourceNode || pxGameSpline->GetDistanceVsTimeGraph()) { return false; }

    if ( pxSourceNode->IsBaseOrDerivativeOf( AsuraEntityClass_LiftNode ) )
	{
        for ( Asura_Hashed_List_It< Asura_ServerEntity_Node > xNodeIter( Asura_ServerEntity_Node::GetList() ); !xNodeIter.Done(); xNodeIter.Next() )
        {
            Asura_ServerEntity_Node* pxNode = xNodeIter.GetCurrent();
            if ( pxNode->IsBaseOrDerivativeOf( AsuraEntityClass_LiftSpline ) )
            {
                Asura_ServerNode_LiftSpline* pxLiftSpline = static_cast< Asura_ServerNode_LiftSpline* >( pxNode );
                if ( pxLiftSpline->GetTargetGuid() == pxSourceNode->GetGuid()  && !pxLiftSpline->GetDistanceVsTimeGraph())
                {
                    return true;
                }
            }
        }
	}
	return false;
}

void Tools_EntityNode_LiftSpline::AutoSetEndSpeed()
{
    Asura_ServerNode_LiftSpline* pxGameSpline = s_pxThisToolsLiftSpline->GetGameLiftSpline();

    Asura_ServerEntity_Node* pxTargetNode = Asura_ServerEntity_Node::GetList()->FindEntity( pxGameSpline->GetTargetGuid() );
	Asura_Assert(pxTargetNode, "Failed to find node");
    if (!pxTargetNode || pxGameSpline->GetDistanceVsTimeGraph()) { return; }

    if (pxTargetNode->IsBaseOrDerivativeOf( AsuraEntityClass_LiftNode ) )
	{
		if (pxTargetNode->GetNumberLinks())
		{
            Asura_ServerEntity_Node* pxNode = Asura_ServerEntity_Node::GetList()->FindEntity( pxTargetNode->GetLink( 0 ) );
            if ( pxNode && pxNode->IsBaseOrDerivativeOf( AsuraEntityClass_LiftSpline ) )
            {
                Asura_ServerNode_LiftSpline* pxLiftSpline = static_cast< Asura_ServerNode_LiftSpline* >( pxNode );

                float fSpeed = pxLiftSpline->GetSpeedOverTimeGraph()->GetValueAtTime(0.0f);
                Asura_Graph_Point<float> *pxGraphPoints = pxGameSpline->GetSpeedOverTimeGraph()->GetControlPoints();
                while (pxGraphPoints->m_pxNext->m_pxNext)
                {
                    pxGraphPoints = pxGraphPoints->m_pxNext;
                }
                pxGraphPoints->m_xValue = fSpeed * pxGameSpline->GetVelocityMultiplier();
                pxGameSpline->GetSpeedOverTimeGraph()->Update();
				s_pxThisToolsLiftSpline->m_fDurationOverride = pxGameSpline->GetTotalLinkTime();
				s_pxThisToolsLiftSpline->m_fLength = pxGameSpline->GetTotalLength();

                return;   
            }
		}
	}
}

bool Tools_EntityNode_LiftSpline::CanAutoSetEndSpeed()
{
    Asura_ServerNode_LiftSpline* pxGameSpline = s_pxThisToolsLiftSpline->GetGameLiftSpline();

    Asura_ServerEntity_Node* pxTargetNode = Asura_ServerEntity_Node::GetList()->FindEntity( pxGameSpline->GetTargetGuid() );
    Asura_Assert(pxTargetNode, "Failed to find node");
    if (!pxTargetNode || pxGameSpline->GetDistanceVsTimeGraph()) { return false; }

    if ( pxTargetNode->IsBaseOrDerivativeOf( AsuraEntityClass_LiftNode ) )
	{
		if (pxTargetNode->GetNumberLinks() > 0)
		{
			return true;
		}
	}
	return false;
}

////////////////////////////////////////////////////////////////////////////////
// Function     : Tools_EntityNode_LiftSpline::UpdateSplinePoint
// Author       : Andy Tate
// Date         : 25-Apr-2007
////////////////////////////////////////////////////////////////////////////////

void Tools_EntityNode_LiftSpline::UpdateSplinePoint(const int iIndex,
													const Asura_Vector_3& xPosition,
													const Asura_Matrix_3x3& xOrientation)
{
	Asura_ServerNode_LiftSpline* pxLiftSpline = GetGameLiftSpline();

	if(pxLiftSpline == NULL)
	{
		Asura_Assert(false, "Cannot find lift-spline to create new end-point for.");
	}
	else
	{
		// Call the parent function...
		PARENT::UpdateSplinePoint(iIndex, xPosition, xOrientation);

		// Ensure the lift-spline's start and end nodes are up-to-date...
		if(iIndex <= 1)
		{
			const Asura_Guid			uGuid			= pxLiftSpline->GetSourceGuid();
			Tools_EntityNode_LiftNode*	pxToolsLiftNode	= static_cast<Tools_EntityNode_LiftNode*>(Tools_EntityNode_LiftNode::FindEntity(uGuid));

			if(pxToolsLiftNode == NULL)
			{
				Asura_Assert(false, "Cannot find specified start-node for this spline.");
			}
			else
			{
				// Ensure we also move the lift-spline start-point...
				pxToolsLiftNode->Position		= xPosition;
				pxToolsLiftNode->Orientation	= xOrientation;
				pxToolsLiftNode->UpdatePositionInAsuraData(true);
			}
		}
		else
		{
			const int	iNumNodes	= pxLiftSpline->GetNumberOfPoints();

			if(iIndex >= (iNumNodes - 2))
			{
				const Asura_Guid			uGuid			= pxLiftSpline->GetTargetGuid();
				Tools_EntityNode_LiftNode*	pxToolsLiftNode	= static_cast<Tools_EntityNode_LiftNode*>(Tools_EntityNode_LiftNode::FindEntity(uGuid));

				if(pxToolsLiftNode == NULL)
				{
					Asura_Assert(false, "Cannot find specified end-node for this spline.");
				}
				else
				{
					// Ensure we also move the lift-spline end-point...
					pxToolsLiftNode->Position		= xPosition;
					pxToolsLiftNode->Orientation	= xOrientation;
					pxToolsLiftNode->UpdatePositionInAsuraData(true);
				}
			}
		}
	}
}

/// End of function 'Tools_EntityNode_LiftSpline::UpdateSplinePoint'. ///

Tools_ChooseObject* Tools_EntityNode_LiftSpline::CreateSourceNodeChooseObject( Asura_Guid* pxGuid ) const
{
	return new Tools_Lift_SelectLiftNode( GetGameLiftSpline()->GetSourceGuid(), pxGuid );
}

Tools_ChooseObject* Tools_EntityNode_LiftSpline::CreateTargetNodeChooseObject( Asura_Guid* pxGuid ) const
{
	return new Tools_Lift_SelectLiftNode( GetGameLiftSpline()->GetTargetGuid(), pxGuid );
}

/// End of file. ///
