123
This commit is contained in:
769
Editor/Objects/AiPoint.cpp
Normal file
769
Editor/Objects/AiPoint.cpp
Normal file
@@ -0,0 +1,769 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2001.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: AIPoint.cpp
|
||||
// Version: v1.00
|
||||
// Created: 10/10/2001 by Timur.
|
||||
// Compilers: Visual C++ 6.0
|
||||
// Description: CAIPoint implementation.
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "AIPoint.h"
|
||||
#include "ErrorReport.h"
|
||||
|
||||
#include "..\AIPointPanel.h"
|
||||
#include <IAgent.h>
|
||||
|
||||
#include "..\Viewport.h"
|
||||
#include "Settings.h"
|
||||
|
||||
#include <I3DEngine.h>
|
||||
//#include <I3DIndoorEngine.h>
|
||||
#include <IAISystem.h>
|
||||
|
||||
#define AIWAYPOINT_RADIUS 0.3f
|
||||
#define DIR_VECTOR Vec3(0,-1,0)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CBase implementation.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IMPLEMENT_DYNCREATE(CAIPoint,CBaseObject)
|
||||
|
||||
int CAIPoint::m_rollupId = 0;
|
||||
CAIPointPanel* CAIPoint::m_panel = 0;
|
||||
|
||||
float CAIPoint::m_helperScale = 1;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CAIPoint::CAIPoint()
|
||||
{
|
||||
m_aiNode = 0;
|
||||
m_bIndoorEntrance = false;
|
||||
m_bIndoors = false;
|
||||
m_aiType = EAIPOINT_WAYPOINT;
|
||||
|
||||
m_bLinksValid = false;
|
||||
m_bIgnoreUpdateLinks = false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CAIPoint::Done()
|
||||
{
|
||||
m_bLinksValid = false;
|
||||
if (m_aiNode)
|
||||
{
|
||||
IGraph *aiGraph = GetIEditor()->GetSystem()->GetAISystem()->GetNodeGraph();
|
||||
if (aiGraph)
|
||||
{
|
||||
aiGraph->Disconnect(m_aiNode,false);
|
||||
if (m_bIndoorEntrance)
|
||||
{
|
||||
aiGraph->RemoveEntrance( m_aiNode->nBuildingID,m_aiNode );
|
||||
}
|
||||
}
|
||||
m_aiNode = 0;
|
||||
}
|
||||
|
||||
while (!m_links.empty())
|
||||
{
|
||||
CAIPoint *obj = GetLink(0);
|
||||
if (obj)
|
||||
RemoveLink( obj );
|
||||
else
|
||||
m_links.erase(m_links.begin());
|
||||
}
|
||||
|
||||
CBaseObject::Done();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CAIPoint::Init( IEditor *ie,CBaseObject *prev,const CString &file )
|
||||
{
|
||||
m_bLinksValid = false;
|
||||
|
||||
SetColor( RGB(0,128,255) );
|
||||
bool res = CBaseObject::Init( ie,prev,file );
|
||||
|
||||
if (IsCreateGameObjects())
|
||||
if (m_aiType != EAIPOINT_HIDE)
|
||||
{
|
||||
// Create AI graph node in game.
|
||||
IGraph *aiGraph = GetIEditor()->GetSystem()->GetAISystem()->GetNodeGraph();
|
||||
if (aiGraph)
|
||||
m_aiNode = aiGraph->CreateNewNode();
|
||||
}
|
||||
|
||||
if (prev)
|
||||
{
|
||||
CAIPoint *pOriginal = (CAIPoint *)prev;
|
||||
SetAIType(pOriginal->m_aiType);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CString CAIPoint::GetTypeDescription() const
|
||||
{
|
||||
if (m_aiType == EAIPOINT_HIDE)
|
||||
{
|
||||
return CString(GetClassDesc()->ClassName()) + "(Hide)";
|
||||
}
|
||||
else if (m_aiType == EAIPOINT_ENTRY)
|
||||
{
|
||||
return CString(GetClassDesc()->ClassName()) + "(Entry)";
|
||||
}
|
||||
else if (m_aiType == EAIPOINT_EXIT)
|
||||
{
|
||||
return CString(GetClassDesc()->ClassName()) + "(Exit)";
|
||||
}
|
||||
return GetClassDesc()->ClassName();
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
float CAIPoint::GetRadius()
|
||||
{
|
||||
return AIWAYPOINT_RADIUS*m_helperScale * gSettings.gizmo.helpersScale;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CAIPoint::SetPos( const Vec3d &pos )
|
||||
{
|
||||
Vec3d oldpos = GetWorldPos();
|
||||
CBaseObject::SetPos( pos );
|
||||
|
||||
/*
|
||||
if (m_aiNode)
|
||||
{
|
||||
m_aiNode->data.m_pos = pos;
|
||||
|
||||
m_buildingId = -1;
|
||||
|
||||
m_bIndoors = false;
|
||||
IAISystem *pAISystem = GetIEditor()->GetSystem()->GetAISystem();
|
||||
int buildingId;IVisArea *pArea;
|
||||
if (pAISystem && pAISystem->CheckInside(pos,buildingId,pArea))
|
||||
{
|
||||
m_aiNode->nBuildingID = buildingId;
|
||||
m_aiNode->pArea = pArea;
|
||||
|
||||
if (m_buildingId != buildingId)
|
||||
m_bLinksValid = false;
|
||||
m_buildingId = buildingId;
|
||||
m_pArea= pArea;
|
||||
m_bIndoors = true;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bIndoors = false;
|
||||
IAISystem *pAISystem = GetIEditor()->GetSystem()->GetAISystem();
|
||||
if (!pAISystem)
|
||||
return;
|
||||
IGraph *pGraph = pAISystem->GetNodeGraph();
|
||||
if (!pGraph)
|
||||
return;
|
||||
int buildingId;IVisArea *pArea;
|
||||
if (pAISystem->CheckInside(pos,buildingId,pArea))
|
||||
{
|
||||
if (m_buildingId != buildingId)
|
||||
m_bLinksValid = false;
|
||||
|
||||
m_buildingId = buildingId;
|
||||
m_pArea= pArea;
|
||||
m_bIndoors = true;
|
||||
}
|
||||
|
||||
// for hide points
|
||||
int numLinks = m_links.size();
|
||||
for (int i = 0; i < numLinks; i++)
|
||||
{
|
||||
// go trough all the links in the waypoint
|
||||
CAIPoint *pnt = GetLink(i);
|
||||
if (!pnt || !pnt->m_aiNode)
|
||||
continue;
|
||||
|
||||
Matrix44 m;
|
||||
m.SetIdentity();
|
||||
|
||||
//m.RotateMatrix_fix(GetAngles());
|
||||
m=GetRotationZYX44(-GetAngles()*gf_DEGTORAD)*m; //NOTE: angles in radians and negated
|
||||
|
||||
//CHANGED_BY_IVO
|
||||
//Vec3 dir = m.TransformVector(DIR_VECTOR);
|
||||
Vec3 dir = GetTransposed44(m) * (DIR_VECTOR);
|
||||
|
||||
pGraph->RemoveHidePoint(pnt->m_aiNode,oldpos,dir);
|
||||
pGraph->AddHidePoint(pnt->m_aiNode,pos,dir);
|
||||
// and update the point there
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CAIPoint::SetAngles( const Vec3d &angles )
|
||||
{
|
||||
//if (m_aiType == EAIPOINT_HIDE)
|
||||
{
|
||||
CBaseObject::SetAngles(angles);
|
||||
}
|
||||
}
|
||||
|
||||
void CAIPoint::SetScale( const Vec3d &angles )
|
||||
{
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CAIPoint::HitTest( HitContext &hc )
|
||||
{
|
||||
Vec3 origin = GetWorldPos();
|
||||
float radius = GetRadius();
|
||||
|
||||
Vec3 w = origin - hc.raySrc;
|
||||
w = hc.rayDir.Cross( w );
|
||||
float d = w.GetLengthSquared();
|
||||
|
||||
if (d < radius*radius + hc.distanceTollerance)
|
||||
{
|
||||
Vec3 i0;
|
||||
if (Intersect::Ray_SphereFirst( Ray(hc.raySrc,hc.rayDir),Sphere(origin,radius),i0))
|
||||
{
|
||||
hc.dist = GetDistance(hc.raySrc,i0);
|
||||
return true;
|
||||
}
|
||||
hc.dist = GetDistance(hc.raySrc,origin);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CAIPoint::GetBoundBox( BBox &box )
|
||||
{
|
||||
Vec3 pos = GetWorldPos();
|
||||
float r = GetRadius();
|
||||
box.min = pos - Vec3(r,r,r);
|
||||
box.max = pos + Vec3(r,r,r);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CAIPoint::GetLocalBounds( BBox &box )
|
||||
{
|
||||
float r = GetRadius();
|
||||
box.min = -Vec3(r,r,r);
|
||||
box.max = Vec3(r,r,r);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CAIPoint::BeginEditParams( IEditor *ie,int flags )
|
||||
{
|
||||
CBaseObject::BeginEditParams( ie,flags );
|
||||
|
||||
// Unselect all links.
|
||||
for (int i = 0; i < GetLinkCount(); i++)
|
||||
SelectLink(i,false);
|
||||
|
||||
if (!m_panel)
|
||||
{
|
||||
m_panel = new CAIPointPanel;
|
||||
m_rollupId = ie->AddRollUpPage( ROLLUP_OBJECTS,"AIPoint Parameters",m_panel );
|
||||
}
|
||||
if (m_panel)
|
||||
m_panel->SetObject( this );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CAIPoint::EndEditParams( IEditor *ie )
|
||||
{
|
||||
if (m_panel)
|
||||
{
|
||||
ie->RemoveRollUpPage( ROLLUP_OBJECTS,m_rollupId );
|
||||
}
|
||||
m_rollupId = 0;
|
||||
m_panel = 0;
|
||||
|
||||
// Unselect all links.
|
||||
for (int i = 0; i < GetLinkCount(); i++)
|
||||
SelectLink(i,false);
|
||||
|
||||
CBaseObject::EndEditParams( ie );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int CAIPoint::MouseCreateCallback( CViewport *view,EMouseEvent event,CPoint &point,int flags )
|
||||
{
|
||||
if (event == eMouseMove || event == eMouseLDown)
|
||||
{
|
||||
Vec3 pos;
|
||||
if (GetIEditor()->GetAxisConstrains() != AXIS_TERRAIN)
|
||||
{
|
||||
pos = view->MapViewToCP(point);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Snap to terrain.
|
||||
bool hitTerrain;
|
||||
pos = view->ViewToWorld( point,&hitTerrain );
|
||||
if (hitTerrain)
|
||||
{
|
||||
pos.z = GetIEditor()->GetTerrainElevation(pos.x,pos.y) + GetRadius();
|
||||
}
|
||||
pos = view->SnapToGrid(pos);
|
||||
}
|
||||
SetPos( pos );
|
||||
if (event == eMouseLDown)
|
||||
return MOUSECREATE_OK;
|
||||
return MOUSECREATE_CONTINUE;
|
||||
}
|
||||
return CBaseObject::MouseCreateCallback( view,event,point,flags );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CAIPoint::Display( DisplayContext &dc )
|
||||
{
|
||||
COLORREF color = GetColor();
|
||||
COLORREF clrSelectedLink = GetColor();
|
||||
|
||||
if (!m_bIndoors)
|
||||
{
|
||||
// Draw invalid node.
|
||||
color = RGB(255,0,0);
|
||||
}
|
||||
Vec3 wp = GetWorldPos();
|
||||
if (m_aiType == EAIPOINT_HIDE)
|
||||
{
|
||||
color = RGB(0,255,0); //<<FIXME>> Timur solve this in a better way.
|
||||
if (IsSelected())
|
||||
dc.SetSelectedColor();
|
||||
else
|
||||
dc.SetColor( color,1 );
|
||||
|
||||
//Vec3 arrowTrg = GetWorldTM().TransformPoint(0.5f*Vec3d(0,-1,0));
|
||||
//dc.DrawArrow(wp,arrowTrg);
|
||||
Matrix44 tm = GetWorldTM();
|
||||
float sz = m_helperScale * gSettings.gizmo.helpersScale;
|
||||
tm.ScaleMatRow( Vec3(sz,sz,sz) );
|
||||
dc.RenderObject( STATOBJECT_HIDEPOINT,tm );
|
||||
}
|
||||
else if (m_aiType == EAIPOINT_ENTRY || m_aiType == EAIPOINT_EXIT)
|
||||
{
|
||||
if (IsSelected())
|
||||
dc.SetSelectedColor();
|
||||
else
|
||||
dc.SetColor( color,1 );
|
||||
Matrix44 tm = GetWorldTM();
|
||||
float sz = m_helperScale * gSettings.gizmo.helpersScale;
|
||||
tm.ScaleMatRow( Vec3(sz,sz,sz) );
|
||||
dc.RenderObject( STATOBJECT_ENTRANCE,GetWorldTM() );
|
||||
}
|
||||
else
|
||||
{
|
||||
dc.SetColor( color,1 );
|
||||
dc.DrawBall( wp,GetRadius() );
|
||||
if (IsSelected())
|
||||
{
|
||||
dc.SetSelectedColor( 0.3f );
|
||||
dc.renderer->DrawBall( wp,GetRadius()+0.1f );
|
||||
}
|
||||
}
|
||||
|
||||
int numLinks = m_links.size();
|
||||
for (int i = 0; i < numLinks; i++)
|
||||
{
|
||||
CAIPoint *pnt = GetLink(i);
|
||||
if (!pnt)
|
||||
continue;
|
||||
|
||||
if (m_links[i].selected)
|
||||
{
|
||||
dc.SetSelectedColor();
|
||||
dc.DrawLine( wp+Vec3(0,0,0.05f),pnt->GetWorldPos()+Vec3(0,0,0.05f) );
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pnt->m_aiType == EAIPOINT_HIDE)
|
||||
color = RGB(0,255,0);
|
||||
dc.SetColor( color );
|
||||
dc.DrawLine( wp,pnt->GetWorldPos() );
|
||||
}
|
||||
}
|
||||
|
||||
DrawDefault( dc );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CAIPoint::Serialize( CObjectArchive &ar )
|
||||
{
|
||||
m_bIgnoreUpdateLinks = true;
|
||||
CBaseObject::Serialize( ar );
|
||||
m_bIgnoreUpdateLinks = false;
|
||||
|
||||
XmlNodeRef xmlNode = ar.node;
|
||||
if (ar.bLoading)
|
||||
{
|
||||
m_bIgnoreUpdateLinks = true;
|
||||
int aiType = 0;
|
||||
xmlNode->getAttr( "AIType",aiType );
|
||||
|
||||
// Load Links.
|
||||
m_links.clear();
|
||||
XmlNodeRef links = xmlNode->findChild( "Links" );
|
||||
if (links)
|
||||
{
|
||||
m_bLinksValid = false;
|
||||
for (int i = 0; i < links->getChildCount(); i++)
|
||||
{
|
||||
XmlNodeRef pnt = links->getChild(i);
|
||||
Link link;
|
||||
link.object = 0;
|
||||
pnt->getAttr( "Id",link.id );
|
||||
m_links.push_back(link);
|
||||
}
|
||||
}
|
||||
SetAIType((EAIPointType)aiType);
|
||||
m_bIgnoreUpdateLinks = false;
|
||||
if (ar.bUndo)
|
||||
UpdateLinks();
|
||||
}
|
||||
else
|
||||
{
|
||||
xmlNode->setAttr( "AIType",(int)m_aiType );
|
||||
// Save Links.
|
||||
if (!m_links.empty())
|
||||
{
|
||||
XmlNodeRef links = xmlNode->newChild( "Links" );
|
||||
for (int i = 0; i < m_links.size(); i++)
|
||||
{
|
||||
XmlNodeRef pnt = links->newChild( "Link" );
|
||||
CAIPoint* link = GetLink(i);
|
||||
if (!link)
|
||||
continue;
|
||||
pnt->setAttr( "Id",link->GetId() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
XmlNodeRef CAIPoint::Export( const CString &levelPath,XmlNodeRef &xmlNode )
|
||||
{
|
||||
/*
|
||||
XmlNodeRef objNode = CBaseObject::Export( levelPath,xmlNode );
|
||||
objNode->setAttr( "Id",GetId() );
|
||||
|
||||
// Save Links.
|
||||
if (!m_links.empty())
|
||||
{
|
||||
XmlNodeRef links = xmlNode->newChild( "Links" );
|
||||
for (int i = 0; i < m_links.size(); i++)
|
||||
{
|
||||
XmlNodeRef pnt = links->newChild( "Link" );
|
||||
pnt->setAttr( "Id",m_links[i].id );
|
||||
}
|
||||
}
|
||||
|
||||
return CBaseObject::Export( levelPath,xmlNode );
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CAIPoint::OnEvent( ObjectEvent event )
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
//case EVENT_AFTER_LOAD: // After all objects loaded.
|
||||
case EVENT_REFRESH: // when refreshing level.
|
||||
// Recalculate indoors.
|
||||
SetPos( GetPos() );
|
||||
// After loading reconnect all links.
|
||||
UpdateLinks();
|
||||
break;
|
||||
case EVENT_CLEAR_AIGRAPH:
|
||||
m_aiNode = 0;
|
||||
break;
|
||||
case EVENT_MISSION_CHANGE:
|
||||
{
|
||||
// After mission have been changed, AI graph invalidates all pointers, create them again.
|
||||
// Create AI graph node in game.
|
||||
IGraph *aiGraph = GetIEditor()->GetSystem()->GetAISystem()->GetNodeGraph();
|
||||
if (aiGraph)
|
||||
{
|
||||
m_bLinksValid = false;
|
||||
if (m_aiType != EAIPOINT_HIDE)
|
||||
{
|
||||
m_aiNode = aiGraph->CreateNewNode();
|
||||
}
|
||||
UpdateLinks();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CAIPoint* CAIPoint::GetLink( int index )
|
||||
{
|
||||
assert( index >= 0 && index < m_links.size() );
|
||||
if (!m_links[index].object)
|
||||
{
|
||||
CBaseObject *obj = FindObject(m_links[index].id);
|
||||
if (obj && obj->IsKindOf(RUNTIME_CLASS(CAIPoint)))
|
||||
{
|
||||
((CAIPoint*)obj)->AddLink( this,false );
|
||||
m_links[index].object = (CAIPoint*)obj;
|
||||
}
|
||||
}
|
||||
return m_links[index].object;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CAIPoint::AddLink( CAIPoint* obj,bool bNeighbour )
|
||||
{
|
||||
if (obj == this)
|
||||
return;
|
||||
|
||||
GUID id = obj->GetId();
|
||||
for (int i = 0; i < m_links.size(); i++)
|
||||
{
|
||||
if (m_links[i].object == obj || m_links[i].id == id)
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_aiType == EAIPOINT_HIDE)
|
||||
{
|
||||
if (obj->m_aiType == EAIPOINT_HIDE)
|
||||
{
|
||||
Warning( _T("Cannot connect hide spots") );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Link link;
|
||||
link.object = obj;
|
||||
link.id = id;
|
||||
m_links.push_back( link );
|
||||
m_bLinksValid = false;
|
||||
|
||||
|
||||
if (!bNeighbour)
|
||||
{
|
||||
obj->AddLink( this,true );
|
||||
UpdateLinks();
|
||||
}
|
||||
else if (m_aiType == EAIPOINT_HIDE)
|
||||
{
|
||||
UpdateLinks();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CAIPoint::RemoveLink( CAIPoint* obj,bool bNeighbour )
|
||||
{
|
||||
if (obj == this || obj == 0)
|
||||
return;
|
||||
|
||||
if (m_aiType == EAIPOINT_HIDE && obj->m_aiNode)
|
||||
{
|
||||
IAISystem *aiSystem = GetIEditor()->GetSystem()->GetAISystem();
|
||||
IGraph *aiGraph = aiSystem->GetNodeGraph();
|
||||
if (aiGraph)
|
||||
{
|
||||
aiGraph->RemoveHidePoint(obj->m_aiNode,m_currHidePos,m_currHideDir );
|
||||
}
|
||||
}
|
||||
|
||||
int index = -1;
|
||||
GUID id = obj->GetId();
|
||||
for (int i = 0; i < m_links.size(); i++)
|
||||
{
|
||||
if (m_links[i].object == obj || m_links[i].id == id)
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (index < 0)
|
||||
return;
|
||||
|
||||
m_links.erase( m_links.begin() + index );
|
||||
m_bLinksValid = false;
|
||||
|
||||
if (!bNeighbour)
|
||||
{
|
||||
obj->RemoveLink( this,true );
|
||||
UpdateLinks();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CAIPoint::UpdateLinks()
|
||||
{
|
||||
if (m_bLinksValid || m_bIgnoreUpdateLinks)
|
||||
return;
|
||||
|
||||
IAISystem *aiSystem = GetIEditor()->GetSystem()->GetAISystem();
|
||||
if (!aiSystem)
|
||||
return;
|
||||
IGraph *aiGraph = aiSystem->GetNodeGraph();
|
||||
|
||||
if (!aiGraph)
|
||||
return;
|
||||
|
||||
m_bIndoors = false;
|
||||
|
||||
if (m_aiType != EAIPOINT_HIDE)
|
||||
{
|
||||
if (!m_aiNode)
|
||||
return;
|
||||
|
||||
IVisArea *pArea = NULL;
|
||||
int nBuildingId = -1;
|
||||
Vec3 wp = GetWorldPos();
|
||||
if (aiSystem->CheckInside(wp,nBuildingId,pArea))
|
||||
{
|
||||
m_bIndoors = true;
|
||||
}
|
||||
|
||||
aiGraph->Disconnect(m_aiNode,false);
|
||||
|
||||
if (m_bIndoorEntrance)
|
||||
{
|
||||
aiGraph->RemoveEntrance( m_aiNode->nBuildingID,m_aiNode );
|
||||
m_bIndoorEntrance = false;
|
||||
}
|
||||
|
||||
m_aiNode->nBuildingID = nBuildingId;
|
||||
m_aiNode->pArea = m_pArea;
|
||||
m_aiNode->data.m_pos = wp;
|
||||
|
||||
if (m_aiType == EAIPOINT_ENTRY && m_aiNode->nBuildingID >= 0)
|
||||
{
|
||||
aiGraph->AddIndoorEntrance( m_aiNode->nBuildingID,m_aiNode );
|
||||
m_bIndoorEntrance = true;
|
||||
}
|
||||
else if (m_aiType == EAIPOINT_EXIT && m_aiNode->nBuildingID >= 0)
|
||||
{
|
||||
aiGraph->AddIndoorEntrance( m_aiNode->nBuildingID,m_aiNode,true);
|
||||
m_bIndoorEntrance = true;
|
||||
}
|
||||
|
||||
int numLinks = GetLinkCount();
|
||||
for (int i = 0; i < numLinks; i++)
|
||||
{
|
||||
CAIPoint *lnk = GetLink(i);
|
||||
if (!lnk)
|
||||
continue;
|
||||
|
||||
if (!lnk->m_aiNode)
|
||||
{
|
||||
if (lnk->m_aiType == EAIPOINT_HIDE)
|
||||
{
|
||||
Vec3 wp = lnk->GetWorldPos();
|
||||
Matrix44 m = lnk->GetWorldTM();
|
||||
m.NoScale();
|
||||
Vec3 dir = m.TransformVectorOLD(DIR_VECTOR);
|
||||
aiGraph->AddHidePoint(m_aiNode,wp,dir );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
aiGraph->Connect(m_aiNode,lnk->m_aiNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Vec3 wp = GetWorldPos();
|
||||
Matrix44 m = GetWorldTM();
|
||||
m.NoScale();
|
||||
Vec3 dir = m.TransformVectorOLD(DIR_VECTOR);
|
||||
|
||||
int numLinks = GetLinkCount();
|
||||
for (int i = 0; i < numLinks; i++)
|
||||
{
|
||||
CAIPoint *lnk = GetLink(i);
|
||||
if (!lnk || !lnk->m_aiNode)
|
||||
continue;
|
||||
|
||||
aiGraph->RemoveHidePoint( lnk->m_aiNode,m_currHidePos,m_currHideDir );
|
||||
aiGraph->AddHidePoint(lnk->m_aiNode,wp,dir );
|
||||
}
|
||||
m_currHidePos = wp;
|
||||
m_currHideDir = dir;
|
||||
}
|
||||
m_bLinksValid = true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CAIPoint::SetAIType( EAIPointType type )
|
||||
{
|
||||
if (type == m_aiType)
|
||||
return;
|
||||
StoreUndo( "Set AIPoint Type" );
|
||||
EAIPointType oldType = m_aiType;
|
||||
m_aiType = type;
|
||||
if (m_aiType == EAIPOINT_HIDE)
|
||||
{
|
||||
IAISystem *aiSystem = GetIEditor()->GetSystem()->GetAISystem();
|
||||
IGraph *aiGraph = aiSystem->GetNodeGraph();
|
||||
if (m_aiNode && aiGraph)
|
||||
{
|
||||
//aiGraph->DeleteNode(m_aiNode);
|
||||
aiGraph->Disconnect(m_aiNode);
|
||||
m_aiNode = 0;
|
||||
}
|
||||
}
|
||||
else if (!m_aiNode)
|
||||
{
|
||||
IAISystem *aiSystem = GetIEditor()->GetSystem()->GetAISystem();
|
||||
IGraph *aiGraph = aiSystem->GetNodeGraph();
|
||||
if (aiGraph)
|
||||
m_aiNode = aiGraph->CreateNewNode();
|
||||
}
|
||||
|
||||
m_bLinksValid = false;
|
||||
|
||||
UpdateLinks();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Invalidates cached transformation matrix.
|
||||
void CAIPoint::InvalidateTM()
|
||||
{
|
||||
CBaseObject::InvalidateTM();
|
||||
|
||||
m_bLinksValid = false;
|
||||
UpdateLinks();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CAIPoint::StartPick()
|
||||
{
|
||||
if (m_panel)
|
||||
m_panel->StartPick();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CAIPoint::Validate( CErrorReport *report )
|
||||
{
|
||||
CBaseObject::Validate( report );
|
||||
if (!m_bIndoors && m_aiType != EAIPOINT_HIDE)
|
||||
{
|
||||
CErrorRecord err;
|
||||
err.error.Format( "AI Point is not valid %s (Must be indoors)",(const char*)GetName() );
|
||||
err.pObject = this;
|
||||
err.severity = CErrorRecord::ESEVERITY_WARNING;
|
||||
err.flags = CErrorRecord::FLAG_AI;
|
||||
report->ReportError(err);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user