///////////////////////////////////////////////////// ///////////////////////////////////////////////////// // // 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: In: triggers the process.
Out: is activated when the process is completed.

Nodal Path: group of nodal paths to search in.
Goal Object: destination to reach.

Group: list of nodes passed though on way to destination. List will be empty if no path is found.

The building block will search the node closest to its owner first, finding the shortest path to the destination node.
More information on Nodal Paths.
See also: other Nodal related building blocks in the Nodal Path folder of 3D Transformations.
*/ 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( iGetObject( i ); if(CKIsChildClassOf(ent,CKCID_3DENTITY)) { VxVector p; ent->GetPosition(&p); float m = SquareMagnitude(p - pos); if(mSeekPosition(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; }