#include <cstring>
+#include <simgear/sg_inlines.h>
#include <simgear/math/sg_geodesy.hxx>
#include <simgear/props/props_io.hxx>
#include <simgear/structure/exception.hxx>
+#include <boost/mem_fn.hpp>
+#include <boost/foreach.hpp>
#include <Main/globals.hxx>
cb_ai_detailed(SGPropertyChangeCallback<FGAIManager>(this,&FGAIManager::updateLOD,
fgGetNode("/sim/rendering/static-lod/ai-detailed", true)))
{
- _dt = 0.0;
- mNumAiModels = 0;
- for (unsigned i = 0; i < FGAIBase::MAX_OBJECTS; ++i)
- mNumAiTypeModels[i] = 0;
}
-FGAIManager::~FGAIManager() {
- ai_list_iterator ai_list_itr = ai_list.begin();
-
- while(ai_list_itr != ai_list.end()) {
- (*ai_list_itr)->unbind();
- ++ai_list_itr;
- }
+FGAIManager::~FGAIManager()
+{
+ std::for_each(ai_list.begin(), ai_list.end(), boost::mem_fn(&FGAIBase::unbind));
}
void
}
void
-FGAIManager::reinit() {
+FGAIManager::reinit()
+{
update(0.0);
-
- ai_list_iterator ai_list_itr = ai_list.begin();
-
- while(ai_list_itr != ai_list.end()) {
- (*ai_list_itr)->reinit();
- ++ai_list_itr;
- }
+ std::for_each(ai_list.begin(), ai_list.end(), boost::mem_fn(&FGAIBase::reinit));
}
void
root->untie("count");
}
+void FGAIManager::removeDeadItem(FGAIBase* base)
+{
+ FGTrafficManager *tmgr = (FGTrafficManager*) globals->get_subsystem("traffic-manager");
+ if (tmgr) {
+ tmgr->release(base->getID());
+ }
+
+ SGPropertyNode *props = base->_getProps();
+
+ props->setBoolValue("valid", false);
+ base->unbind();
+
+ // for backward compatibility reset properties, so that aircraft,
+ // which don't know the <valid> property, keep working
+ // TODO: remove after a while
+ props->setIntValue("id", -1);
+ props->setBoolValue("radar/in-range", false);
+ props->setIntValue("refuel/tanker", false);
+}
+
void
FGAIManager::update(double dt) {
// initialize these for finding nearest thermals
if (!enabled->getBoolValue())
return;
- FGTrafficManager *tmgr = (FGTrafficManager*) globals->get_subsystem("traffic-manager");
- _dt = dt;
-
- ai_list_iterator ai_list_itr = ai_list.begin();
-
- while(ai_list_itr != ai_list.end()) {
+ fetchUserState();
- if ((*ai_list_itr)->getDie()) {
- tmgr->release((*ai_list_itr)->getID());
- --mNumAiModels;
- --(mNumAiTypeModels[(*ai_list_itr)->getType()]);
- FGAIBase *base = (*ai_list_itr).get();
- SGPropertyNode *props = base->_getProps();
-
- props->setBoolValue("valid", false);
- base->unbind();
-
- // for backward compatibility reset properties, so that aircraft,
- // which don't know the <valid> property, keep working
- // TODO: remove after a while
- props->setIntValue("id", -1);
- props->setBoolValue("radar/in-range", false);
- props->setIntValue("refuel/tanker", false);
-
- ai_list_itr = ai_list.erase(ai_list_itr);
+ // partition the list into dead followed by alive
+ ai_list_iterator firstAlive =
+ std::stable_partition(ai_list.begin(), ai_list.end(), boost::mem_fn(&FGAIBase::getDie));
+
+ // clean up each item and finally remove from the container
+ for (ai_list_iterator it=ai_list.begin(); it != firstAlive; ++it) {
+ removeDeadItem(*it);
+ }
+
+ ai_list.erase(ai_list.begin(), firstAlive);
+
+ // every remaining item is alive
+ BOOST_FOREACH(FGAIBase* base, ai_list) {
+ if (base->isa(FGAIBase::otThermal)) {
+ processThermal(dt, (FGAIThermal*)base);
} else {
- fetchUserState();
- if ((*ai_list_itr)->isa(FGAIBase::otThermal)) {
- FGAIBase *base = (*ai_list_itr).get();
- processThermal((FGAIThermal*)base);
- } else {
- (*ai_list_itr)->update(_dt);
- }
- ++ai_list_itr;
+ base->update(dt);
}
- }
+ } // of live AI objects iteration
thermal_lift_node->setDoubleValue( strength ); // for thermals
}
void
FGAIManager::updateLOD(SGPropertyNode* node)
{
- ai_list_iterator ai_list_itr = ai_list.begin();
- while(ai_list_itr != ai_list.end())
- {
- (*ai_list_itr)->updateLOD();
- ++ai_list_itr;
- }
+ SG_UNUSED(node);
+ std::for_each(ai_list.begin(), ai_list.end(), boost::mem_fn(&FGAIBase::updateLOD));
}
void
FGAIManager::attach(FGAIBase *model)
{
- //unsigned idx = mNumAiTypeModels[model->getType()];
const char* typeString = model->getTypeString();
SGPropertyNode* root = globals->get_props()->getNode("ai/models", true);
SGPropertyNode* p;
p = root->getNode(typeString, i, true);
model->setManager(this, p);
ai_list.push_back(model);
- ++mNumAiModels;
- ++(mNumAiTypeModels[model->getType()]);
+
model->init(model->getType()==FGAIBase::otAircraft
|| model->getType()==FGAIBase::otMultiplayer
|| model->getType()==FGAIBase::otStatic);
while(ai_list_itr != ai_list.end()) {
if ((*ai_list_itr)->getID() == ID) {
- --mNumAiModels;
- --(mNumAiTypeModels[(*ai_list_itr)->getType()]);
(*ai_list_itr)->unbind();
ai_list_itr = ai_list.erase(ai_list_itr);
} else
int
FGAIManager::getNumAiObjects(void) const
{
- return mNumAiModels;
+ return ai_list.size();
}
void
// only keep the results from the nearest thermal
void
-FGAIManager::processThermal( FGAIThermal* thermal ) {
- thermal->update(_dt);
+FGAIManager::processThermal( double dt, FGAIThermal* thermal ) {
+ thermal->update(dt);
if ( thermal->_getRange() < range_nearest ) {
range_nearest = thermal->_getRange();
ai_list_iterator ai_list_itr = ai_list.begin();
ai_list_iterator end = ai_list.end();
+ SGGeod pos(SGGeod::fromDegFt(lon, lat, alt));
+ SGVec3d cartPos(SGVec3d::fromGeod(pos));
+
while (ai_list_itr != end) {
double tgt_alt = (*ai_list_itr)->_getAltitude();
int type = (*ai_list_itr)->getType();
continue;
}
- double tgt_lat = (*ai_list_itr)->_getLatitude();
- double tgt_lon = (*ai_list_itr)->_getLongitude();
int id = (*ai_list_itr)->getID();
- double range = calcRange(lat, lon, tgt_lat, tgt_lon);
+ double range = calcRange(cartPos, (*ai_list_itr));
//SG_LOG(SG_AI, SG_DEBUG, "AIManager: AI list size "
// << ai_list.size()
}
double
-FGAIManager::calcRange(double lat, double lon, double lat2, double lon2) const
+FGAIManager::calcRange(const SGVec3d& aCartPos, FGAIBase* aObject) const
{
- double course, az2, distance;
-
- //calculate the bearing and range of the second pos from the first
- geo_inverse_wgs_84(lat, lon, lat2, lon2, &course, &az2, &distance);
- distance *= SG_METER_TO_FEET;
- return distance;
+ double distM = dist(aCartPos, aObject->getCartPos());
+ return distM * SG_METER_TO_FEET;
}
//end AIManager.cxx