Commands to control scenarios / AI-objects.
New commands allow runtime scenario loading and unloading, and AI object creation and removal at runtime.
This commit is contained in:
parent
4a84ea0bc4
commit
96a40fe70c
2 changed files with 145 additions and 85 deletions
|
@ -25,6 +25,8 @@
|
|||
#include <simgear/math/sg_geodesy.hxx>
|
||||
#include <simgear/props/props_io.hxx>
|
||||
#include <simgear/structure/exception.hxx>
|
||||
#include <simgear/structure/commands.hxx>
|
||||
|
||||
#include <boost/mem_fn.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
|
@ -45,6 +47,33 @@
|
|||
#include "AIGroundVehicle.hxx"
|
||||
#include "AIEscort.hxx"
|
||||
|
||||
class FGAIManager::Scenario
|
||||
{
|
||||
public:
|
||||
Scenario(FGAIManager* man, SGPropertyNode* scenarios) :
|
||||
_manager(man)
|
||||
{
|
||||
BOOST_FOREACH(SGPropertyNode* scEntry, scenarios->getChildren("entry")) {
|
||||
FGAIBasePtr ai = man->addObject(scEntry);
|
||||
if (ai) {
|
||||
_objects.push_back(ai);
|
||||
}
|
||||
} // of scenario entry iteration
|
||||
}
|
||||
|
||||
~Scenario()
|
||||
{
|
||||
BOOST_FOREACH(FGAIBasePtr ai, _objects) {
|
||||
ai->setDie(true);
|
||||
}
|
||||
}
|
||||
private:
|
||||
FGAIManager* _manager;
|
||||
std::vector<FGAIBasePtr> _objects;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FGAIManager::FGAIManager() :
|
||||
cb_ai_bare(SGPropertyChangeCallback<FGAIManager>(this,&FGAIManager::updateLOD,
|
||||
fgGetNode("/sim/rendering/static-lod/ai-bare", true))),
|
||||
|
@ -72,6 +101,9 @@ FGAIManager::init() {
|
|||
user_altitude_agl_node = fgGetNode("/position/altitude-agl-ft", true);
|
||||
user_yaw_node = fgGetNode("/orientation/side-slip-deg", true);
|
||||
user_speed_node = fgGetNode("/velocities/uBody-fps", true);
|
||||
|
||||
globals->get_commands()->addCommand("load-scenario", this, &FGAIManager::loadScenarioCommand);
|
||||
globals->get_commands()->addCommand("unload-scenario", this, &FGAIManager::unloadScenarioCommand);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -86,20 +118,18 @@ FGAIManager::postinit() {
|
|||
enabled->setBoolValue(true);
|
||||
|
||||
// process all scenarios
|
||||
std::set<std::string> loadedScenarios;
|
||||
BOOST_FOREACH(SGPropertyNode* n, root->getChildren("scenario")) {
|
||||
const string& name = n->getStringValue();
|
||||
if (name.empty())
|
||||
continue;
|
||||
|
||||
if (loadedScenarios.find(name) != loadedScenarios.end()) {
|
||||
if (_scenarios.find(name) != _scenarios.end()) {
|
||||
SG_LOG(SG_AI, SG_WARN, "won't load scenario '" << name << "' twice");
|
||||
continue;
|
||||
}
|
||||
|
||||
SG_LOG(SG_AI, SG_INFO, "loading scenario '" << name << '\'');
|
||||
loadScenario(name);
|
||||
loadedScenarios.insert(name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -242,81 +272,101 @@ FGAIManager::processThermal( double dt, FGAIThermal* thermal ) {
|
|||
|
||||
}
|
||||
|
||||
bool FGAIManager::loadScenarioCommand(const SGPropertyNode* args)
|
||||
{
|
||||
std::string name = args->getStringValue("name");
|
||||
return loadScenario(name);
|
||||
}
|
||||
|
||||
bool FGAIManager::unloadScenarioCommand(const SGPropertyNode* args)
|
||||
{
|
||||
std::string name = args->getStringValue("name");
|
||||
unloadScenario(name);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FGAIManager::addObjectCommand(const SGPropertyNode* definition)
|
||||
{
|
||||
addObject(definition);
|
||||
return true;
|
||||
}
|
||||
|
||||
FGAIBasePtr FGAIManager::addObject(const SGPropertyNode* definition)
|
||||
{
|
||||
const std::string& type = definition->getStringValue("type", "aircraft");
|
||||
|
||||
FGAIBase* ai = NULL;
|
||||
if (type == "tanker") { // refueling scenarios
|
||||
ai = new FGAITanker;
|
||||
} else if (type == "wingman") {
|
||||
ai = new FGAIWingman;
|
||||
} else if (type == "aircraft") {
|
||||
ai = new FGAIAircraft;
|
||||
} else if (type == "ship") {
|
||||
ai = new FGAIShip;
|
||||
} else if (type == "carrier") {
|
||||
ai = new FGAICarrier;
|
||||
} else if (type == "groundvehicle") {
|
||||
ai = new FGAIGroundVehicle;
|
||||
} else if (type == "escort") {
|
||||
ai = new FGAIEscort;
|
||||
} else if (type == "thunderstorm") {
|
||||
ai = new FGAIStorm;
|
||||
} else if (type == "thermal") {
|
||||
ai = new FGAIThermal;
|
||||
} else if (type == "ballistic") {
|
||||
ai = new FGAIBallistic;
|
||||
} else if (type == "static") {
|
||||
ai = new FGAIStatic;
|
||||
}
|
||||
|
||||
ai->readFromScenario(const_cast<SGPropertyNode*>(definition));
|
||||
attach(ai);
|
||||
return ai;
|
||||
}
|
||||
|
||||
bool FGAIManager::removeObject(const SGPropertyNode* args)
|
||||
{
|
||||
int id = args->getIntValue("id");
|
||||
BOOST_FOREACH(FGAIBase* ai, get_ai_list()) {
|
||||
if (ai->getID() == id) {
|
||||
ai->setDie(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
FGAIManager::loadScenario( const string &filename )
|
||||
{
|
||||
SGPropertyNode_ptr file = loadScenarioFile(filename);
|
||||
if (!file) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SGPropertyNode_ptr scNode = file->getChild("scenario");
|
||||
if (!scNode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_scenarios[filename] = new Scenario(this, scNode);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FGAIManager::loadScenario( const string &filename ) {
|
||||
|
||||
SGPropertyNode_ptr scenarioTop = loadScenarioFile(filename);
|
||||
|
||||
if (!scenarioTop)
|
||||
FGAIManager::unloadScenario( const string &filename)
|
||||
{
|
||||
ScenarioDict::iterator it = _scenarios.find(filename);
|
||||
if (it == _scenarios.end()) {
|
||||
SG_LOG(SG_AI, SG_WARN, "unload scenario: not found:" << filename);
|
||||
return;
|
||||
|
||||
SGPropertyNode* scenarios = scenarioTop->getChild("scenario");
|
||||
|
||||
if (!scenarios)
|
||||
return;
|
||||
|
||||
BOOST_FOREACH(SGPropertyNode* scEntry, scenarios->getChildren("entry")) {
|
||||
const std::string& type = scEntry->getStringValue("type", "aircraft");
|
||||
|
||||
if (type == "tanker") { // refueling scenarios
|
||||
FGAITanker* tanker = new FGAITanker;
|
||||
tanker->readFromScenario(scEntry);
|
||||
attach(tanker);
|
||||
|
||||
} else if (type == "wingman") {
|
||||
FGAIWingman* wingman = new FGAIWingman;
|
||||
wingman->readFromScenario(scEntry);
|
||||
attach(wingman);
|
||||
|
||||
} else if (type == "aircraft") {
|
||||
FGAIAircraft* aircraft = new FGAIAircraft;
|
||||
aircraft->readFromScenario(scEntry);
|
||||
attach(aircraft);
|
||||
|
||||
} else if (type == "ship") {
|
||||
FGAIShip* ship = new FGAIShip;
|
||||
ship->readFromScenario(scEntry);
|
||||
attach(ship);
|
||||
|
||||
} else if (type == "carrier") {
|
||||
FGAICarrier* carrier = new FGAICarrier;
|
||||
carrier->readFromScenario(scEntry);
|
||||
attach(carrier);
|
||||
|
||||
} else if (type == "groundvehicle") {
|
||||
FGAIGroundVehicle* groundvehicle = new FGAIGroundVehicle;
|
||||
groundvehicle->readFromScenario(scEntry);
|
||||
attach(groundvehicle);
|
||||
|
||||
} else if (type == "escort") {
|
||||
FGAIEscort* escort = new FGAIEscort;
|
||||
escort->readFromScenario(scEntry);
|
||||
attach(escort);
|
||||
|
||||
} else if (type == "thunderstorm") {
|
||||
FGAIStorm* storm = new FGAIStorm;
|
||||
storm->readFromScenario(scEntry);
|
||||
attach(storm);
|
||||
|
||||
} else if (type == "thermal") {
|
||||
FGAIThermal* thermal = new FGAIThermal;
|
||||
thermal->readFromScenario(scEntry);
|
||||
attach(thermal);
|
||||
|
||||
} else if (type == "ballistic") {
|
||||
FGAIBallistic* ballistic = new FGAIBallistic;
|
||||
ballistic->readFromScenario(scEntry);
|
||||
attach(ballistic);
|
||||
|
||||
} else if (type == "static") {
|
||||
FGAIStatic* aistatic = new FGAIStatic;
|
||||
aistatic->readFromScenario(scEntry);
|
||||
attach(aistatic);
|
||||
}
|
||||
|
||||
} // of scenario entry iteration
|
||||
}
|
||||
|
||||
delete it->second;
|
||||
_scenarios.erase(it);
|
||||
}
|
||||
|
||||
SGPropertyNode_ptr
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#define _FG_AIMANAGER_HXX
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
#include <simgear/structure/subsystem_mgr.hxx>
|
||||
#include <simgear/structure/SGSharedPtr.hxx>
|
||||
|
@ -37,24 +38,21 @@
|
|||
#include <Traffic/SchedFlight.hxx>
|
||||
#include <Traffic/Schedule.hxx>
|
||||
|
||||
using std::list;
|
||||
|
||||
class FGAIThermal;
|
||||
|
||||
typedef SGSharedPtr<FGAIBase> FGAIBasePtr;
|
||||
|
||||
class FGAIManager : public SGSubsystem
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
// A list of pointers to AI objects
|
||||
typedef list <SGSharedPtr<FGAIBase> > ai_list_type;
|
||||
typedef std::list <FGAIBasePtr> ai_list_type;
|
||||
typedef ai_list_type::iterator ai_list_iterator;
|
||||
typedef ai_list_type::const_iterator ai_list_const_iterator;
|
||||
|
||||
ai_list_type ai_list;
|
||||
|
||||
inline const ai_list_type& get_ai_list() const {
|
||||
SG_LOG(SG_AI, SG_DEBUG, "AI Manager: AI model return list size " << ai_list.size());
|
||||
const ai_list_type& get_ai_list() const {
|
||||
return ai_list;
|
||||
}
|
||||
|
||||
|
@ -72,9 +70,6 @@ public:
|
|||
|
||||
const FGAIBase *calcCollision(double alt, double lat, double lon, double fuse_range);
|
||||
|
||||
// inline double get_user_latitude() const { return user_latitude; }
|
||||
// inline double get_user_longitude() const { return user_longitude; }
|
||||
// inline double get_user_altitude() const { return user_altitude; }
|
||||
inline double get_user_heading() const { return user_heading; }
|
||||
inline double get_user_pitch() const { return user_pitch; }
|
||||
inline double get_user_yaw() const { return user_yaw; }
|
||||
|
@ -86,18 +81,27 @@ public:
|
|||
|
||||
int getNumAiObjects(void) const;
|
||||
|
||||
void loadScenario( const string &filename );
|
||||
bool loadScenario( const string &filename );
|
||||
|
||||
static SGPropertyNode_ptr loadScenarioFile(const std::string& filename);
|
||||
|
||||
static bool getStartPosition(const string& id, const string& pid,
|
||||
SGGeod& geodPos, double& hdng, SGVec3d& uvw);
|
||||
|
||||
FGAIBasePtr addObject(const SGPropertyNode* definition);
|
||||
|
||||
private:
|
||||
void removeDeadItem(FGAIBase* base);
|
||||
|
||||
double calcRange(const SGVec3d& aCartPos, FGAIBase* aObject) const;
|
||||
|
||||
bool loadScenarioCommand(const SGPropertyNode* args);
|
||||
bool unloadScenarioCommand(const SGPropertyNode* args);
|
||||
bool addObjectCommand(const SGPropertyNode* definition);
|
||||
|
||||
bool removeObject(const SGPropertyNode* args);
|
||||
void unloadScenario( const string &filename );
|
||||
|
||||
SGPropertyNode_ptr root;
|
||||
SGPropertyNode_ptr enabled;
|
||||
SGPropertyNode_ptr thermal_lift_node;
|
||||
|
@ -108,6 +112,8 @@ private:
|
|||
SGPropertyNode_ptr wind_from_north_node;
|
||||
|
||||
|
||||
ai_list_type ai_list;
|
||||
|
||||
double user_altitude_agl;
|
||||
double user_heading;
|
||||
double user_pitch;
|
||||
|
@ -127,6 +133,10 @@ private:
|
|||
|
||||
SGPropertyChangeCallback<FGAIManager> cb_ai_bare;
|
||||
SGPropertyChangeCallback<FGAIManager> cb_ai_detailed;
|
||||
|
||||
class Scenario;
|
||||
typedef std::map<std::string, Scenario*> ScenarioDict;
|
||||
ScenarioDict _scenarios;
|
||||
};
|
||||
|
||||
#endif // _FG_AIMANAGER_HXX
|
||||
|
|
Loading…
Reference in a new issue