forked from bartvdbraak/blender
Added new actuator type for following steering behaviors: seek, flee, path following; renamed KX_Pathfinder to KX_NavMeshObject
This commit is contained in:
parent
d7a701c2c5
commit
05b92f0fc9
@ -552,7 +552,7 @@
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\source\gameengine\Ketsji\KX_Pathfinder.cpp"
|
||||
RelativePath="..\..\..\source\gameengine\Ketsji\KX_NavMeshObject.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
@ -682,6 +682,10 @@
|
||||
RelativePath="..\..\..\source\gameengine\Ketsji\KX_StateActuator.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\source\gameengine\Ketsji\KX_SteeringActuator.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\source\gameengine\Ketsji\KX_TrackToActuator.cpp"
|
||||
>
|
||||
@ -857,11 +861,11 @@
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\source\gameengine\Ketsji\KX_OdePhysicsController.h"
|
||||
RelativePath="..\..\..\source\gameengine\Ketsji\KX_NavMeshObject.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\source\gameengine\Ketsji\KX_Pathfinder.h"
|
||||
RelativePath="..\..\..\source\gameengine\Ketsji\KX_OdePhysicsController.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
@ -999,6 +1003,10 @@
|
||||
RelativePath="..\..\..\source\gameengine\Ketsji\KX_StateActuator.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\source\gameengine\Ketsji\KX_SteeringActuator.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\source\gameengine\Ketsji\KX_TrackToActuator.h"
|
||||
>
|
||||
|
@ -468,6 +468,8 @@ void init_actuator(bActuator *act)
|
||||
case ACT_ARMATURE:
|
||||
act->data = MEM_callocN(sizeof( bArmatureActuator ), "armature act");
|
||||
break;
|
||||
case ACT_STEERING:
|
||||
act->data = MEM_callocN(sizeof( bSteeringActuator), "steering act");
|
||||
default:
|
||||
; /* this is very severe... I cannot make any memory for this */
|
||||
/* logic brick... */
|
||||
@ -611,6 +613,7 @@ void sca_remove_ob_poin(Object *obt, Object *ob)
|
||||
bMessageActuator *ma;
|
||||
bParentActuator *para;
|
||||
bArmatureActuator *aa;
|
||||
bSteeringActuator *sta;
|
||||
|
||||
sens= obt->sensors.first;
|
||||
while(sens) {
|
||||
@ -658,6 +661,11 @@ void sca_remove_ob_poin(Object *obt, Object *ob)
|
||||
if (aa->target == ob) aa->target = NULL;
|
||||
if (aa->subtarget == ob) aa->subtarget = NULL;
|
||||
break;
|
||||
case ACT_STEERING:
|
||||
sta = act->data;
|
||||
if (sta->target==ob) sta->target = NULL;
|
||||
if (sta->navmesh==ob) sta->navmesh = NULL;
|
||||
break;
|
||||
}
|
||||
act= act->next;
|
||||
}
|
||||
|
@ -3612,6 +3612,11 @@ static void lib_link_object(FileData *fd, Main *main)
|
||||
arma->target= newlibadr(fd, ob->id.lib, arma->target);
|
||||
arma->subtarget= newlibadr(fd, ob->id.lib, arma->subtarget);
|
||||
}
|
||||
else if(act->type==ACT_STEERING) {
|
||||
bSteeringActuator *steeringa = act->data;
|
||||
steeringa->target = newlibadr(fd, ob->id.lib, steeringa->target);
|
||||
steeringa->navmesh = newlibadr(fd, ob->id.lib, steeringa->navmesh);
|
||||
}
|
||||
act= act->next;
|
||||
}
|
||||
|
||||
@ -11745,6 +11750,11 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob)
|
||||
bArmatureActuator *arma= act->data;
|
||||
expand_doit(fd, mainvar, arma->target);
|
||||
}
|
||||
else if(act->type==ACT_STEERING) {
|
||||
bSteeringActuator *sta= act->data;
|
||||
expand_doit(fd, mainvar, sta->target);
|
||||
expand_doit(fd, mainvar, sta->navmesh);
|
||||
}
|
||||
act= act->next;
|
||||
}
|
||||
|
||||
|
@ -858,6 +858,9 @@ static void write_actuators(WriteData *wd, ListBase *lb)
|
||||
case ACT_ARMATURE:
|
||||
writestruct(wd, DATA, "bArmatureActuator", 1, act->data);
|
||||
break;
|
||||
case ACT_STEERING:
|
||||
writestruct(wd, DATA, "bSteeringActuator", 1, act->data);
|
||||
break;
|
||||
default:
|
||||
; /* error: don't know how to write this file */
|
||||
}
|
||||
|
@ -710,6 +710,8 @@ static char *actuator_name(int type)
|
||||
return "State";
|
||||
case ACT_ARMATURE:
|
||||
return "Armature";
|
||||
case ACT_STEERING:
|
||||
return "Steering";
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
@ -2895,7 +2897,6 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh
|
||||
uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
|
||||
yco-= ysize;
|
||||
break;
|
||||
|
||||
default:
|
||||
ysize= 4;
|
||||
|
||||
@ -4232,6 +4233,20 @@ static void draw_actuator_visibility(uiLayout *layout, PointerRNA *ptr)
|
||||
uiItemR(row, ptr, "children", 0, NULL, 0);
|
||||
}
|
||||
|
||||
static void draw_actuator_steering(uiLayout *layout, PointerRNA *ptr)
|
||||
{
|
||||
uiLayout *row;
|
||||
|
||||
uiItemR(layout, ptr, "mode", 0, NULL, 0);
|
||||
uiItemR(layout, ptr, "target", 0, NULL, 0);
|
||||
uiItemR(layout, ptr, "navmesh", 0, NULL, 0);
|
||||
|
||||
row = uiLayoutRow(layout, 0);
|
||||
uiItemR(row, ptr, "distance", 0, NULL, 0);
|
||||
uiItemR(row, ptr, "movement", 0, NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
void draw_brick_actuator(uiLayout *layout, PointerRNA *ptr, bContext *C)
|
||||
{
|
||||
uiLayout *box;
|
||||
@ -4296,6 +4311,8 @@ void draw_brick_actuator(uiLayout *layout, PointerRNA *ptr, bContext *C)
|
||||
case ACT_VISIBILITY:
|
||||
draw_actuator_visibility(box, ptr);
|
||||
break;
|
||||
case ACT_STEERING:
|
||||
draw_actuator_steering(box, ptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -214,6 +214,15 @@ typedef struct bArmatureActuator {
|
||||
struct Object *subtarget;
|
||||
} bArmatureActuator;
|
||||
|
||||
typedef struct bSteeringActuator {
|
||||
char pad[4];
|
||||
int type; /* 0=seek, 1=flee, 2=path following */
|
||||
float dist;
|
||||
float movement;
|
||||
struct Object *target;
|
||||
struct Object *navmesh;
|
||||
} bSteeringActuator;
|
||||
|
||||
typedef struct bActuator {
|
||||
struct bActuator *next, *prev, *mynew;
|
||||
short type;
|
||||
@ -286,6 +295,7 @@ typedef struct FreeCamera {
|
||||
#define ACT_SHAPEACTION 21
|
||||
#define ACT_STATE 22
|
||||
#define ACT_ARMATURE 23
|
||||
#define ACT_STEERING 24
|
||||
|
||||
/* actuator flag */
|
||||
#define ACT_SHOW 1
|
||||
@ -502,6 +512,11 @@ typedef struct FreeCamera {
|
||||
#define ACT_CAMERA_X (float)'x'
|
||||
#define ACT_CAMERA_Y (float)'y'
|
||||
|
||||
/* steeringactuator->type */
|
||||
#define ACT_STEERING_SEEK 0
|
||||
#define ACT_STEERING_FLEE 1
|
||||
#define ACT_STEERING_PATHFOLLOWING 2
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -54,6 +54,7 @@ EnumPropertyItem actuator_type_items[] ={
|
||||
{ACT_SOUND, "SOUND", 0, "Sound", ""},
|
||||
{ACT_STATE, "STATE", 0, "State", ""},
|
||||
{ACT_VISIBILITY, "VISIBILITY", 0, "Visibility", ""},
|
||||
{ACT_STEERING, "STEERING", 0, "Steering", ""},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
EnumPropertyItem edit_object_type_items[] ={
|
||||
@ -109,6 +110,8 @@ static StructRNA* rna_Actuator_refine(struct PointerRNA *ptr)
|
||||
return &RNA_StateActuator;
|
||||
case ACT_ARMATURE:
|
||||
return &RNA_ArmatureActuator;
|
||||
case ACT_STEERING:
|
||||
return &RNA_SteeringActuator;
|
||||
default:
|
||||
return &RNA_Actuator;
|
||||
}
|
||||
@ -401,6 +404,7 @@ EnumPropertyItem *rna_Actuator_type_itemf(bContext *C, PointerRNA *ptr, int *fre
|
||||
RNA_enum_items_add_value(&item, &totitem, actuator_type_items, ACT_PROPERTY);
|
||||
RNA_enum_items_add_value(&item, &totitem, actuator_type_items, ACT_RANDOM);
|
||||
RNA_enum_items_add_value(&item, &totitem, actuator_type_items, ACT_SCENE);
|
||||
RNA_enum_items_add_value(&item, &totitem, actuator_type_items, ACT_STEERING);
|
||||
|
||||
if (ob != NULL) {
|
||||
if (ob->type==OB_MESH){
|
||||
@ -1841,6 +1845,54 @@ static void rna_def_armature_actuator(BlenderRNA *brna)
|
||||
RNA_def_property_update(prop, NC_LOGIC, NULL);
|
||||
}
|
||||
|
||||
static void rna_def_steering_actuator(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
static EnumPropertyItem prop_type_items[] ={
|
||||
{ACT_STEERING_SEEK, "SEEK", 0, "Seek", ""},
|
||||
{ACT_STEERING_FLEE, "FLEE", 0, "Flee", ""},
|
||||
{ACT_STEERING_PATHFOLLOWING, "PATHFOLLOWING", 0, "Path following", ""},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
srna= RNA_def_struct(brna, "SteeringActuator", "Actuator");
|
||||
RNA_def_struct_ui_text(srna, "Steering Actuator", "");
|
||||
RNA_def_struct_sdna_from(srna, "bSteeringActuator", "data");
|
||||
|
||||
prop= RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "type");
|
||||
RNA_def_property_enum_items(prop, prop_type_items);
|
||||
RNA_def_property_ui_text(prop, "Behavior", "");
|
||||
RNA_def_property_update(prop, NC_LOGIC, NULL);
|
||||
|
||||
prop= RNA_def_property(srna, "movement", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "movement");
|
||||
RNA_def_property_range(prop, 0.0, 1000.0);
|
||||
RNA_def_property_ui_text(prop, "Move", "Movement value");
|
||||
RNA_def_property_update(prop, NC_LOGIC, NULL);
|
||||
|
||||
prop= RNA_def_property(srna, "distance", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "dist");
|
||||
RNA_def_property_range(prop, 0.0, 1000.0);
|
||||
RNA_def_property_ui_text(prop, "Dist", "Relax distance");
|
||||
RNA_def_property_update(prop, NC_LOGIC, NULL);
|
||||
|
||||
prop= RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "Object");
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "target");
|
||||
RNA_def_property_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Target Object", "Set target object");
|
||||
RNA_def_property_update(prop, NC_LOGIC, NULL);
|
||||
|
||||
prop= RNA_def_property(srna, "navmesh", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "Object");
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "navmesh");
|
||||
RNA_def_property_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "NavMesh Object", "Navigation mesh");
|
||||
RNA_def_property_update(prop, NC_LOGIC, NULL);
|
||||
}
|
||||
|
||||
void RNA_def_actuator(BlenderRNA *brna)
|
||||
{
|
||||
rna_def_actuator(brna);
|
||||
@ -1863,6 +1915,7 @@ void RNA_def_actuator(BlenderRNA *brna)
|
||||
rna_def_shape_action_actuator(brna);
|
||||
rna_def_state_actuator(brna);
|
||||
rna_def_armature_actuator(brna);
|
||||
rna_def_steering_actuator(brna);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -172,7 +172,7 @@ extern "C" {
|
||||
#include "BL_ArmatureObject.h"
|
||||
#include "BL_DeformableGameObject.h"
|
||||
|
||||
#include "KX_Pathfinder.h"
|
||||
#include "KX_NavMeshObject.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -1717,7 +1717,7 @@ static KX_GameObject *gameobject_from_blenderobject(
|
||||
|
||||
if (ob->gameflag & OB_NAVMESH)
|
||||
{
|
||||
gameobj = new KX_Pathfinder(kxscene,KX_Scene::m_callbacks);
|
||||
gameobj = new KX_NavMeshObject(kxscene,KX_Scene::m_callbacks);
|
||||
gameobj->AddMesh(meshobj);
|
||||
break;
|
||||
}
|
||||
@ -2685,7 +2685,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
|
||||
struct Object* blenderobject = gameobj->GetBlenderObject();
|
||||
if (blenderobject->type==OB_MESH && (blenderobject->gameflag & OB_NAVMESH))
|
||||
{
|
||||
KX_Pathfinder* pathfinder = static_cast<KX_Pathfinder*>(gameobj);
|
||||
KX_NavMeshObject* pathfinder = static_cast<KX_NavMeshObject*>(gameobj);
|
||||
pathfinder->BuildNavMesh();
|
||||
pathfinder->SetVisible(0, true);
|
||||
}
|
||||
|
@ -62,6 +62,7 @@
|
||||
#include "KX_SCA_ReplaceMeshActuator.h"
|
||||
#include "KX_ParentActuator.h"
|
||||
#include "KX_SCA_DynamicActuator.h"
|
||||
#include "KX_SteeringActuator.h"
|
||||
|
||||
#include "KX_Scene.h"
|
||||
#include "KX_KetsjiEngine.h"
|
||||
@ -89,6 +90,7 @@
|
||||
#include "BL_ActionActuator.h"
|
||||
#include "BL_ShapeActionActuator.h"
|
||||
#include "BL_ArmatureActuator.h"
|
||||
#include "RNA_access.h"
|
||||
/* end of blender include block */
|
||||
|
||||
#include "BL_BlenderDataConversion.h"
|
||||
@ -1028,6 +1030,39 @@ void BL_ConvertActuators(char* maggiename,
|
||||
baseact = tmparmact;
|
||||
break;
|
||||
}
|
||||
case ACT_STEERING:
|
||||
{
|
||||
bSteeringActuator *stAct = (bSteeringActuator *) bact->data;
|
||||
KX_GameObject *navmeshob = NULL;
|
||||
if (stAct->navmesh)
|
||||
{
|
||||
PointerRNA settings_ptr;
|
||||
RNA_pointer_create((ID *)stAct->navmesh, &RNA_GameObjectSettings, stAct->navmesh, &settings_ptr);
|
||||
if (RNA_enum_get(&settings_ptr, "physics_type") == OB_BODY_TYPE_NAVMESH)
|
||||
navmeshob = converter->FindGameObject(stAct->navmesh);
|
||||
}
|
||||
KX_GameObject *targetob = converter->FindGameObject(stAct->target);
|
||||
|
||||
int mode = KX_SteeringActuator::KX_STEERING_NODEF;
|
||||
switch(stAct->type)
|
||||
{
|
||||
case ACT_STEERING_SEEK:
|
||||
mode = KX_SteeringActuator::KX_STEERING_SEEK;
|
||||
break;
|
||||
case ACT_STEERING_FLEE:
|
||||
mode = KX_SteeringActuator::KX_STEERING_FLEE;
|
||||
break;
|
||||
case ACT_STEERING_PATHFOLLOWING:
|
||||
mode = KX_SteeringActuator::KX_STEERING_PATHFOLLOWING;
|
||||
break;
|
||||
}
|
||||
|
||||
KX_SteeringActuator *tmpstact
|
||||
= new KX_SteeringActuator(gameobj, mode, targetob, navmeshob,
|
||||
stAct->movement, stAct->dist);
|
||||
baseact = tmpstact;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
; /* generate some error */
|
||||
}
|
||||
|
@ -85,6 +85,7 @@ public:
|
||||
KX_ACT_SHAPEACTION,
|
||||
KX_ACT_STATE,
|
||||
KX_ACT_ARMATURE,
|
||||
KX_ACT_STEERING,
|
||||
};
|
||||
|
||||
SCA_IActuator(SCA_IObject* gameobj, KX_ACTUATOR_TYPE type);
|
||||
|
@ -75,7 +75,7 @@
|
||||
#include "DNA_world_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "KX_Pathfinder.h"
|
||||
#include "KX_NavMeshObject.h"
|
||||
|
||||
// If define: little test for Nzc: guarded drawing. If the canvas is
|
||||
// not valid, skip rendering this frame.
|
||||
|
@ -26,7 +26,7 @@
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#include "KX_Pathfinder.h"
|
||||
#include "KX_NavMeshObject.h"
|
||||
#include "RAS_MeshObject.h"
|
||||
|
||||
#include "DNA_mesh_types.h"
|
||||
@ -68,23 +68,36 @@ inline void flipAxes(float* vec)
|
||||
std::swap(vec[1],vec[2]);
|
||||
}
|
||||
|
||||
KX_Pathfinder::KX_Pathfinder(void* sgReplicationInfo, SG_Callbacks callbacks)
|
||||
KX_NavMeshObject::KX_NavMeshObject(void* sgReplicationInfo, SG_Callbacks callbacks)
|
||||
: KX_GameObject(sgReplicationInfo, callbacks)
|
||||
, m_navMesh(NULL)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
KX_Pathfinder::~KX_Pathfinder()
|
||||
KX_NavMeshObject::~KX_NavMeshObject()
|
||||
{
|
||||
if (m_navMesh)
|
||||
delete m_navMesh;
|
||||
}
|
||||
|
||||
bool KX_Pathfinder::BuildVertIndArrays(RAS_MeshObject* meshobj, float *&vertices, int& nverts,
|
||||
CValue* KX_NavMeshObject::GetReplica()
|
||||
{
|
||||
KX_NavMeshObject* replica = new KX_NavMeshObject(*this);
|
||||
replica->ProcessReplica();
|
||||
return replica;
|
||||
}
|
||||
|
||||
void KX_NavMeshObject::ProcessReplica()
|
||||
{
|
||||
KX_GameObject::ProcessReplica();
|
||||
BuildNavMesh();
|
||||
}
|
||||
|
||||
bool KX_NavMeshObject::BuildVertIndArrays(RAS_MeshObject* meshobj, float *&vertices, int& nverts,
|
||||
unsigned short* &faces, int& npolys)
|
||||
{
|
||||
if (!meshobj || meshobj->HasColliderPolygon()==false)
|
||||
if (!meshobj)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -144,7 +157,7 @@ bool KX_Pathfinder::BuildVertIndArrays(RAS_MeshObject* meshobj, float *&vertices
|
||||
return true;
|
||||
}
|
||||
|
||||
bool KX_Pathfinder::BuildNavMesh()
|
||||
bool KX_NavMeshObject::BuildNavMesh()
|
||||
{
|
||||
if (GetMeshCount()==0)
|
||||
return false;
|
||||
@ -162,12 +175,11 @@ bool KX_Pathfinder::BuildNavMesh()
|
||||
MT_Point3 pos;
|
||||
for (int i=0; i<nverts; i++)
|
||||
{
|
||||
flipAxes(&vertices[i*3]);
|
||||
pos.setValue(&vertices[i*3]);
|
||||
//add world transform
|
||||
pos = worldTransform(pos);
|
||||
pos.getValue(&vertices[i*3]);
|
||||
|
||||
flipAxes(&vertices[i*3]);
|
||||
}
|
||||
//reorder tris
|
||||
for (int i=0; i<npolys; i++)
|
||||
@ -177,9 +189,6 @@ bool KX_Pathfinder::BuildNavMesh()
|
||||
const int vertsPerPoly = 3;
|
||||
buildMeshAdjacency(faces, npolys, nverts, vertsPerPoly);
|
||||
|
||||
|
||||
|
||||
|
||||
int ndtris = npolys;
|
||||
int uniqueDetailVerts = 0;
|
||||
float cs = 0.2f;
|
||||
@ -298,7 +307,7 @@ bool KX_Pathfinder::BuildNavMesh()
|
||||
return true;
|
||||
}
|
||||
|
||||
void KX_Pathfinder::DebugDraw()
|
||||
void KX_NavMeshObject::DrawNavMesh()
|
||||
{
|
||||
if (!m_navMesh)
|
||||
return;
|
||||
@ -332,7 +341,7 @@ void KX_Pathfinder::DebugDraw()
|
||||
}
|
||||
}
|
||||
|
||||
int KX_Pathfinder::FindPath(MT_Vector3& from, MT_Vector3& to, float* path, int maxPathLen)
|
||||
int KX_NavMeshObject::FindPath(const MT_Point3& from, const MT_Point3& to, float* path, int maxPathLen)
|
||||
{
|
||||
if (!m_navMesh)
|
||||
return 0;
|
||||
@ -359,7 +368,7 @@ int KX_Pathfinder::FindPath(MT_Vector3& from, MT_Vector3& to, float* path, int m
|
||||
return pathLen;
|
||||
}
|
||||
|
||||
float KX_Pathfinder::Raycast(MT_Vector3& from, MT_Vector3& to)
|
||||
float KX_NavMeshObject::Raycast(const MT_Point3& from, const MT_Point3& to)
|
||||
{
|
||||
if (!m_navMesh)
|
||||
return 0.f;
|
||||
@ -373,13 +382,25 @@ float KX_Pathfinder::Raycast(MT_Vector3& from, MT_Vector3& to)
|
||||
return t;
|
||||
}
|
||||
|
||||
void KX_NavMeshObject::DrawPath(const float *path, int pathLen, const MT_Vector3& color)
|
||||
{
|
||||
MT_Vector3 a,b;
|
||||
for (int i=0; i<pathLen-1; i++)
|
||||
{
|
||||
a.setValue(&path[3*i]);
|
||||
b.setValue(&path[3*(i+1)]);
|
||||
KX_RasterizerDrawDebugLine(a, b, color);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifndef DISABLE_PYTHON
|
||||
//----------------------------------------------------------------------------
|
||||
//Python
|
||||
|
||||
PyTypeObject KX_Pathfinder::Type = {
|
||||
PyTypeObject KX_NavMeshObject::Type = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"KX_Pathfinder",
|
||||
"KX_NavMeshObject",
|
||||
sizeof(PyObjectPlus_Proxy),
|
||||
0,
|
||||
py_base_dealloc,
|
||||
@ -402,26 +423,26 @@ PyTypeObject KX_Pathfinder::Type = {
|
||||
py_base_new
|
||||
};
|
||||
|
||||
PyAttributeDef KX_Pathfinder::Attributes[] = {
|
||||
PyAttributeDef KX_NavMeshObject::Attributes[] = {
|
||||
{ NULL } //Sentinel
|
||||
};
|
||||
|
||||
//KX_PYMETHODTABLE_NOARGS(KX_GameObject, getD),
|
||||
PyMethodDef KX_Pathfinder::Methods[] = {
|
||||
KX_PYMETHODTABLE(KX_Pathfinder, findPath),
|
||||
KX_PYMETHODTABLE(KX_Pathfinder, raycast),
|
||||
KX_PYMETHODTABLE(KX_Pathfinder, draw),
|
||||
PyMethodDef KX_NavMeshObject::Methods[] = {
|
||||
KX_PYMETHODTABLE(KX_NavMeshObject, findPath),
|
||||
KX_PYMETHODTABLE(KX_NavMeshObject, raycast),
|
||||
KX_PYMETHODTABLE(KX_NavMeshObject, draw),
|
||||
{NULL,NULL} //Sentinel
|
||||
};
|
||||
|
||||
KX_PYMETHODDEF_DOC(KX_Pathfinder, findPath,
|
||||
KX_PYMETHODDEF_DOC(KX_NavMeshObject, findPath,
|
||||
"findPath(start, goal): find path from start to goal points\n"
|
||||
"Returns a path as list of points)\n")
|
||||
{
|
||||
PyObject *ob_from, *ob_to;
|
||||
if (!PyArg_ParseTuple(args,"OO:getPath",&ob_from,&ob_to))
|
||||
return NULL;
|
||||
MT_Vector3 from, to;
|
||||
MT_Point3 from, to;
|
||||
if (!PyVecTo(ob_from, from) || !PyVecTo(ob_to, to))
|
||||
return NULL;
|
||||
|
||||
@ -430,31 +451,31 @@ KX_PYMETHODDEF_DOC(KX_Pathfinder, findPath,
|
||||
PyObject *pathList = PyList_New( pathLen );
|
||||
for (int i=0; i<pathLen; i++)
|
||||
{
|
||||
MT_Vector3 point(&path[3*i]);
|
||||
MT_Point3 point(&path[3*i]);
|
||||
PyList_SET_ITEM(pathList, i, PyObjectFrom(point));
|
||||
}
|
||||
|
||||
return pathList;
|
||||
}
|
||||
|
||||
KX_PYMETHODDEF_DOC(KX_Pathfinder, raycast,
|
||||
KX_PYMETHODDEF_DOC(KX_NavMeshObject, raycast,
|
||||
"raycast(start, goal): raycast from start to goal points\n"
|
||||
"Returns hit factor)\n")
|
||||
{
|
||||
PyObject *ob_from, *ob_to;
|
||||
if (!PyArg_ParseTuple(args,"OO:getPath",&ob_from,&ob_to))
|
||||
return NULL;
|
||||
MT_Vector3 from, to;
|
||||
MT_Point3 from, to;
|
||||
if (!PyVecTo(ob_from, from) || !PyVecTo(ob_to, to))
|
||||
return NULL;
|
||||
float hit = Raycast(from, to);
|
||||
return PyFloat_FromDouble(hit);
|
||||
}
|
||||
|
||||
KX_PYMETHODDEF_DOC_NOARGS(KX_Pathfinder, draw,
|
||||
KX_PYMETHODDEF_DOC_NOARGS(KX_NavMeshObject, draw,
|
||||
"draw(): navigation mesh debug drawing\n")
|
||||
{
|
||||
DebugDraw();
|
||||
DrawNavMesh();
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
@ -36,7 +36,7 @@
|
||||
class RAS_MeshObject;
|
||||
class MT_Transform;
|
||||
|
||||
class KX_Pathfinder: public KX_GameObject
|
||||
class KX_NavMeshObject: public KX_GameObject
|
||||
{
|
||||
Py_Header;
|
||||
|
||||
@ -47,12 +47,18 @@ protected:
|
||||
unsigned short *&faces, int& npolys);
|
||||
|
||||
public:
|
||||
KX_Pathfinder(void* sgReplicationInfo, SG_Callbacks callbacks);
|
||||
~KX_Pathfinder();
|
||||
KX_NavMeshObject(void* sgReplicationInfo, SG_Callbacks callbacks);
|
||||
~KX_NavMeshObject();
|
||||
|
||||
virtual CValue* GetReplica();
|
||||
virtual void ProcessReplica();
|
||||
|
||||
|
||||
bool BuildNavMesh();
|
||||
int FindPath(MT_Vector3& from, MT_Vector3& to, float* path, int maxPathLen);
|
||||
float Raycast(MT_Vector3& from, MT_Vector3& to);
|
||||
void DebugDraw();
|
||||
int FindPath(const MT_Point3& from, const MT_Point3& to, float* path, int maxPathLen);
|
||||
float Raycast(const MT_Point3& from, const MT_Point3& to);
|
||||
void DrawNavMesh();
|
||||
void DrawPath(const float *path, int pathLen, const MT_Vector3& color);
|
||||
|
||||
|
||||
#ifndef DISABLE_PYTHON
|
||||
@ -60,9 +66,9 @@ public:
|
||||
/* Python interface ---------------------------------------------------- */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
KX_PYMETHOD_DOC(KX_Pathfinder, findPath);
|
||||
KX_PYMETHOD_DOC(KX_Pathfinder, raycast);
|
||||
KX_PYMETHOD_DOC_NOARGS(KX_Pathfinder, draw);
|
||||
KX_PYMETHOD_DOC(KX_NavMeshObject, findPath);
|
||||
KX_PYMETHOD_DOC(KX_NavMeshObject, raycast);
|
||||
KX_PYMETHOD_DOC_NOARGS(KX_NavMeshObject, draw);
|
||||
#endif
|
||||
};
|
||||
|
@ -93,7 +93,7 @@
|
||||
#include "SCA_PythonController.h"
|
||||
#include "SCA_RandomActuator.h"
|
||||
#include "SCA_IController.h"
|
||||
#include "KX_Pathfinder.h"
|
||||
#include "KX_NavMeshObject.h"
|
||||
|
||||
static void PyType_Attr_Set(PyGetSetDef *attr_getset, PyAttributeDef *attr)
|
||||
{
|
||||
@ -211,7 +211,7 @@ void initPyTypes(void)
|
||||
PyType_Ready_Attr(dict, KX_SCA_EndObjectActuator, init_getset);
|
||||
PyType_Ready_Attr(dict, KX_SCA_ReplaceMeshActuator, init_getset);
|
||||
PyType_Ready_Attr(dict, KX_Scene, init_getset);
|
||||
PyType_Ready_Attr(dict, KX_Pathfinder, init_getset);
|
||||
PyType_Ready_Attr(dict, KX_NavMeshObject, init_getset);
|
||||
PyType_Ready_Attr(dict, KX_SceneActuator, init_getset);
|
||||
PyType_Ready_Attr(dict, KX_SoundActuator, init_getset);
|
||||
PyType_Ready_Attr(dict, KX_StateActuator, init_getset);
|
||||
|
256
source/gameengine/Ketsji/KX_SteeringActuator.cpp
Normal file
256
source/gameengine/Ketsji/KX_SteeringActuator.cpp
Normal file
@ -0,0 +1,256 @@
|
||||
/**
|
||||
* Add steering behaviors
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version. The Blender
|
||||
* Foundation also sells licenses for use in proprietary software under
|
||||
* the Blender License. See http://www.blender.org/BL/ for information
|
||||
* about this.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#include "KX_SteeringActuator.h"
|
||||
#include "KX_GameObject.h"
|
||||
#include "KX_NavMeshObject.h"
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Native functions */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
KX_SteeringActuator::KX_SteeringActuator(SCA_IObject *gameobj,
|
||||
int mode,
|
||||
KX_GameObject *target,
|
||||
KX_GameObject *navmesh,
|
||||
MT_Scalar movement,
|
||||
MT_Scalar distance) :
|
||||
SCA_IActuator(gameobj, KX_ACT_STEERING),
|
||||
m_mode(mode),
|
||||
m_target(target),
|
||||
m_movement(movement),
|
||||
m_distance(distance)
|
||||
{
|
||||
m_navmesh = static_cast<KX_NavMeshObject*>(navmesh);
|
||||
if (m_navmesh)
|
||||
m_navmesh->RegisterActuator(this);
|
||||
if (m_target)
|
||||
m_target->RegisterActuator(this);
|
||||
}
|
||||
|
||||
KX_SteeringActuator::~KX_SteeringActuator()
|
||||
{
|
||||
if (m_navmesh)
|
||||
m_navmesh->UnregisterActuator(this);
|
||||
if (m_target)
|
||||
m_target->UnregisterActuator(this);
|
||||
}
|
||||
|
||||
CValue* KX_SteeringActuator::GetReplica()
|
||||
{
|
||||
KX_SteeringActuator* replica = new KX_SteeringActuator(*this);
|
||||
// replication just copy the m_base pointer => common random generator
|
||||
replica->ProcessReplica();
|
||||
return replica;
|
||||
}
|
||||
|
||||
void KX_SteeringActuator::ProcessReplica()
|
||||
{
|
||||
if (m_target)
|
||||
m_target->RegisterActuator(this);
|
||||
if (m_navmesh)
|
||||
m_navmesh->RegisterActuator(this);
|
||||
SCA_IActuator::ProcessReplica();
|
||||
}
|
||||
|
||||
|
||||
bool KX_SteeringActuator::UnlinkObject(SCA_IObject* clientobj)
|
||||
{
|
||||
if (clientobj == m_target)
|
||||
{
|
||||
// this object is being deleted, we cannot continue to track it.
|
||||
m_target = NULL;
|
||||
return true;
|
||||
}
|
||||
else if (clientobj == m_navmesh)
|
||||
{
|
||||
// this object is being deleted, we cannot continue to track it.
|
||||
m_navmesh = NULL;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void KX_SteeringActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map)
|
||||
{
|
||||
void **h_obj = (*obj_map)[m_target];
|
||||
if (h_obj) {
|
||||
if (m_target)
|
||||
m_target->UnregisterActuator(this);
|
||||
m_target = (KX_GameObject*)(*h_obj);
|
||||
m_target->RegisterActuator(this);
|
||||
}
|
||||
|
||||
h_obj = (*obj_map)[m_navmesh];
|
||||
if (h_obj) {
|
||||
if (m_navmesh)
|
||||
m_navmesh->UnregisterActuator(this);
|
||||
m_navmesh = (KX_NavMeshObject*)(*h_obj);
|
||||
m_navmesh->RegisterActuator(this);
|
||||
}
|
||||
}
|
||||
|
||||
bool KX_SteeringActuator::Update()
|
||||
{
|
||||
bool bNegativeEvent = IsNegativeEvent();
|
||||
RemoveAllEvents();
|
||||
|
||||
if (bNegativeEvent)
|
||||
return false; // do nothing on negative events
|
||||
|
||||
KX_GameObject *obj = (KX_GameObject*) GetParent();
|
||||
const MT_Point3& mypos = obj->NodeGetWorldPosition();
|
||||
const MT_Point3& targpos = m_target->NodeGetWorldPosition();
|
||||
MT_Vector3 vectotarg = targpos - mypos;
|
||||
MT_Vector3 steervec = MT_Vector3(0, 0, 0);
|
||||
bool apply_steerforce = false;
|
||||
|
||||
switch (m_mode) {
|
||||
case KX_STEERING_SEEK:
|
||||
if (vectotarg.length2()>m_distance*m_distance)
|
||||
{
|
||||
apply_steerforce = true;
|
||||
steervec = vectotarg;
|
||||
steervec.normalize();
|
||||
}
|
||||
break;
|
||||
case KX_STEERING_FLEE:
|
||||
if (vectotarg.length2()<m_distance*m_distance)
|
||||
{
|
||||
apply_steerforce = true;
|
||||
steervec = -vectotarg;
|
||||
steervec.normalize();
|
||||
}
|
||||
case KX_STEERING_PATHFOLLOWING:
|
||||
if (m_navmesh && vectotarg.length2()>m_distance*m_distance)
|
||||
{
|
||||
static const int MAX_PATH_LENGTH = 128;
|
||||
static const MT_Vector3 PATH_COLOR(1,0,0);
|
||||
|
||||
float path[MAX_PATH_LENGTH*3];
|
||||
int pathlen = m_navmesh->FindPath(mypos, targpos, path, MAX_PATH_LENGTH);
|
||||
if (pathlen > 1)
|
||||
{
|
||||
//debug draw
|
||||
m_navmesh->DrawPath(path, pathlen, PATH_COLOR);
|
||||
|
||||
apply_steerforce = true;
|
||||
MT_Vector3 waypoint(&path[3]);
|
||||
steervec = waypoint - mypos;
|
||||
steervec.z() = 0;
|
||||
steervec.normalize();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (apply_steerforce)
|
||||
{
|
||||
MT_Vector3 vel = m_movement*steervec;
|
||||
obj->ApplyMovement(vel, false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifndef DISABLE_PYTHON
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Python functions */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/* Integration hooks ------------------------------------------------------- */
|
||||
PyTypeObject KX_SteeringActuator::Type = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"KX_SteeringActuator",
|
||||
sizeof(PyObjectPlus_Proxy),
|
||||
0,
|
||||
py_base_dealloc,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
py_base_repr,
|
||||
0,0,0,0,0,0,0,0,0,
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
|
||||
0,0,0,0,0,0,0,
|
||||
Methods,
|
||||
0,
|
||||
0,
|
||||
&SCA_IActuator::Type,
|
||||
0,0,0,0,0,0,
|
||||
py_base_new
|
||||
};
|
||||
|
||||
PyMethodDef KX_SteeringActuator::Methods[] = {
|
||||
{NULL,NULL} //Sentinel
|
||||
};
|
||||
|
||||
PyAttributeDef KX_SteeringActuator::Attributes[] = {
|
||||
KX_PYATTRIBUTE_RW_FUNCTION("target", KX_SteeringActuator, pyattr_get_target, pyattr_set_target),
|
||||
{ NULL } //Sentinel
|
||||
};
|
||||
|
||||
PyObject* KX_SteeringActuator::pyattr_get_target(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
|
||||
{
|
||||
KX_SteeringActuator* actuator = static_cast<KX_SteeringActuator*>(self);
|
||||
if (!actuator->m_target)
|
||||
Py_RETURN_NONE;
|
||||
else
|
||||
return actuator->m_target->GetProxy();
|
||||
}
|
||||
|
||||
int KX_SteeringActuator::pyattr_set_target(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
|
||||
{
|
||||
KX_SteeringActuator* actuator = static_cast<KX_SteeringActuator*>(self);
|
||||
KX_GameObject *gameobj;
|
||||
|
||||
if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.object = value: KX_SteeringActuator"))
|
||||
return PY_SET_ATTR_FAIL; // ConvertPythonToGameObject sets the error
|
||||
|
||||
if (actuator->m_target != NULL)
|
||||
actuator->m_target->UnregisterActuator(actuator);
|
||||
|
||||
actuator->m_target = (KX_GameObject*) gameobj;
|
||||
|
||||
if (actuator->m_target)
|
||||
actuator->m_target->RegisterActuator(actuator);
|
||||
|
||||
return PY_SET_ATTR_SUCCESS;
|
||||
}
|
||||
|
||||
#endif // DISABLE_PYTHON
|
||||
|
||||
/* eof */
|
||||
|
95
source/gameengine/Ketsji/KX_SteeringActuator.h
Normal file
95
source/gameengine/Ketsji/KX_SteeringActuator.h
Normal file
@ -0,0 +1,95 @@
|
||||
/**
|
||||
* Add steering behaviors
|
||||
*
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version. The Blender
|
||||
* Foundation also sells licenses for use in proprietary software under
|
||||
* the Blender License. See http://www.blender.org/BL/ for information
|
||||
* about this.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#ifndef __KX_STEERINGACTUATOR
|
||||
#define __KX_STEERINGACTUATOR
|
||||
|
||||
#include "SCA_IActuator.h"
|
||||
#include "SCA_LogicManager.h"
|
||||
|
||||
class KX_GameObject;
|
||||
class KX_NavMeshObject;
|
||||
|
||||
class KX_SteeringActuator : public SCA_IActuator
|
||||
{
|
||||
Py_Header;
|
||||
|
||||
/** Target object */
|
||||
KX_GameObject *m_target;
|
||||
KX_NavMeshObject *m_navmesh;
|
||||
|
||||
int m_mode;
|
||||
MT_Scalar m_distance;
|
||||
MT_Scalar m_movement;
|
||||
public:
|
||||
enum KX_STEERINGACT_MODE
|
||||
{
|
||||
KX_STEERING_NODEF = 0,
|
||||
KX_STEERING_SEEK,
|
||||
KX_STEERING_FLEE,
|
||||
KX_STEERING_PATHFOLLOWING,
|
||||
KX_STEERING_MAX
|
||||
};
|
||||
|
||||
KX_SteeringActuator(class SCA_IObject* gameobj,
|
||||
int mode,
|
||||
KX_GameObject *target,
|
||||
KX_GameObject *navmesh,
|
||||
MT_Scalar movement,
|
||||
MT_Scalar distance);
|
||||
virtual ~KX_SteeringActuator();
|
||||
virtual bool Update();
|
||||
|
||||
virtual CValue* GetReplica();
|
||||
virtual void ProcessReplica();
|
||||
virtual void Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map);
|
||||
virtual bool UnlinkObject(SCA_IObject* clientobj);
|
||||
|
||||
#ifndef DISABLE_PYTHON
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Python interface ---------------------------------------------------- */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/* These are used to get and set m_target */
|
||||
static PyObject* pyattr_get_target(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
|
||||
static int pyattr_set_target(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
|
||||
|
||||
#endif // DISABLE_PYTHON
|
||||
|
||||
}; /* end of class KX_SteeringActuator : public SCA_PropertyActuator */
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user