161 lines
4.7 KiB
C++
161 lines
4.7 KiB
C++
/////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////
|
|
//
|
|
// EntityFindPath
|
|
//
|
|
/////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////
|
|
|
|
#include "CKAll.h"
|
|
#include "float.h"
|
|
#include "N3dGraph.h"
|
|
|
|
CKObjectDeclaration *FillBehaviorEntityFindPathDecl();
|
|
CKERROR CreateEntityFindPathProto(CKBehaviorPrototype **);
|
|
int EntityFindPath(const CKBehaviorContext& behcontext);
|
|
CKERROR EntityFindPathCallback(const CKBehaviorContext& behcontext);
|
|
|
|
CKObjectDeclaration *FillBehaviorEntityFindPathDecl()
|
|
{
|
|
CKObjectDeclaration *od = CreateCKObjectDeclaration("Entity Find Nodal Path");
|
|
od->SetDescription("Finds the shortest path to a specified destination for a 3D Entity.");
|
|
/* rem:
|
|
<SPAN CLASS=in>In: </SPAN>triggers the process.<BR>
|
|
<SPAN CLASS=out>Out: </SPAN>is activated when the process is completed.<BR>
|
|
<BR>
|
|
<SPAN CLASS=pin>Nodal Path: </SPAN>group of nodal paths to search in.<BR>
|
|
<SPAN CLASS=pin>Goal Object: </SPAN>destination to reach.<BR>
|
|
<BR>
|
|
<SPAN CLASS=pout>Group: </SPAN>list of nodes passed though on way to destination. List will be empty if no path is found.<BR>
|
|
<BR>
|
|
The building block will search the node closest to its owner first, finding the shortest path to the destination node.<BR>
|
|
<a href="nodal.htm">More information on Nodal Paths.</a><BR>
|
|
See also: other Nodal related building blocks in the Nodal Path folder of 3D Transformations.<BR>
|
|
*/
|
|
od->SetType( CKDLL_BEHAVIORPROTOTYPE);
|
|
od->SetGuid(CKGUID(0x170a5187,0x42f10a3a));
|
|
od->SetAuthorGuid(VIRTOOLS_GUID);
|
|
od->SetAuthorName("Virtools");
|
|
od->SetVersion(0x00010000);
|
|
od->SetCreationFunction(CreateEntityFindPathProto);
|
|
od->SetCompatibleClassId(CKCID_3DENTITY);
|
|
od->SetCategory("3D Transformations/Nodal Path");
|
|
return od;
|
|
}
|
|
|
|
|
|
CKERROR CreateEntityFindPathProto(CKBehaviorPrototype **pproto)
|
|
{
|
|
CKBehaviorPrototype *proto = NULL;
|
|
proto = CreateCKBehaviorPrototype("Entity Find Nodal Path");
|
|
if(!proto) return CKERR_OUTOFMEMORY;
|
|
|
|
proto->DeclareInput("In");
|
|
proto->DeclareOutput("Path Found");
|
|
proto->DeclareOutput("No Path Found");
|
|
|
|
proto->DeclareInParameter("Nodal Path",CKPGUID_GROUP);
|
|
proto->DeclareInParameter("Goal Object",CKPGUID_3DENTITY);
|
|
|
|
proto->DeclareOutParameter("Object List",CKPGUID_GROUP);
|
|
|
|
proto->SetFlags(CK_BEHAVIORPROTOTYPE_NORMAL);
|
|
proto->SetFunction( EntityFindPath );
|
|
proto->SetBehaviorCallbackFct( EntityFindPathCallback );
|
|
proto->SetBehaviorFlags(CKBEHAVIOR_TARGETABLE);
|
|
|
|
*pproto = proto;
|
|
return CK_OK;
|
|
|
|
}
|
|
|
|
|
|
int EntityFindPath(const CKBehaviorContext& behcontext)
|
|
{
|
|
CKBehavior* beh = behcontext.Behavior;
|
|
CKContext* ctx = behcontext.Context;
|
|
CKAttributeManager* attman = ctx->GetAttributeManager();
|
|
|
|
beh->ActivateInput(0,FALSE);
|
|
|
|
CKGroup* group = (CKGroup*)beh->GetInputParameterObject(0);
|
|
if(!group) VXTHROW "No group given";
|
|
CKParameterOut* param = group->GetAttributeParameter(attman->GetAttributeTypeByName(Network3dName));
|
|
if(!param) VXTHROW "Given Group isn't a Network";
|
|
N3DGraph* graph;
|
|
param->GetValue(&graph);
|
|
if(!graph) VXTHROW "There is no Graph attached";
|
|
|
|
int c = group->GetObjectCount();
|
|
|
|
|
|
CK3dEntity* object = (CK3dEntity*)beh->GetTarget();
|
|
if(!object) {
|
|
beh->ActivateOutput(1); // No path found
|
|
return CKBR_OK;
|
|
}
|
|
|
|
VxVector pos;
|
|
object->GetPosition(&pos);
|
|
|
|
CK3dEntity* ent;
|
|
CK3dEntity* s=NULL;
|
|
float min = FLT_MAX;
|
|
int i=0;
|
|
while( i<c ){
|
|
ent = (CK3dEntity*)group->GetObject( i );
|
|
if(CKIsChildClassOf(ent,CKCID_3DENTITY)) {
|
|
VxVector p;
|
|
ent->GetPosition(&p);
|
|
float m = SquareMagnitude(p - pos);
|
|
if(m<min) {
|
|
min = m;
|
|
s = ent;
|
|
}
|
|
}
|
|
i++;
|
|
}
|
|
|
|
if(graph->SeekPosition(CKOBJID(s))==-1) VXTHROW "Start point isn't in the Network";
|
|
CK3dEntity* e = (CK3dEntity*)beh->GetInputParameterObject(1);
|
|
if(graph->SeekPosition(CKOBJID(e))==-1) VXTHROW "End point isn't in the Network";
|
|
|
|
CKGroup* path = (CKGroup*)beh->GetOutputParameterObject(0);
|
|
path->Clear();
|
|
|
|
// the core code
|
|
graph->FindPath(s,e,path);
|
|
|
|
// Output Activation
|
|
if(path->GetObjectCount() >0) beh->ActivateOutput(0); // Path found
|
|
else beh->ActivateOutput(1); // No path found
|
|
|
|
return CKBR_OK;
|
|
}
|
|
|
|
CKERROR EntityFindPathCallback(const CKBehaviorContext& behcontext)
|
|
{
|
|
CKBehavior *beh = behcontext.Behavior;
|
|
CKContext* ctx = beh->GetCKContext();
|
|
|
|
switch(behcontext.CallbackMessage){
|
|
case CKM_BEHAVIORCREATE:
|
|
case CKM_BEHAVIORLOAD:
|
|
{
|
|
CKGroup* group = (CKGroup*)ctx->CreateObject(CKCID_GROUP,"FindPathGroup",beh->IsDynamic()?CK_OBJECTCREATION_DYNAMIC:CK_OBJECTCREATION_NONAMECHECK);
|
|
group->ModifyObjectFlags(CK_OBJECT_NOTTOBELISTEDANDSAVED,0);
|
|
beh->SetOutputParameterObject(0,group);
|
|
}
|
|
break;
|
|
|
|
case CKM_BEHAVIORDELETE:
|
|
{
|
|
CKGroup* group = (CKGroup*)beh->GetOutputParameterObject(0);
|
|
CKDestroyObject(group);
|
|
}
|
|
break;
|
|
}
|
|
return CKBR_OK;
|
|
|
|
}
|