#include <simgear/props/props.hxx>
#include <Main/globals.hxx>
+#include <Main/fg_props.hxx>
#include <Scenery/scenery.hxx>
#include <Scripting/NasalSys.hxx>
#include <Scripting/NasalModelData.hxx>
#include <Sound/fg_fx.hxx>
+#include "AIFlightPlan.hxx"
#include "AIBase.hxx"
#include "AIManager.hxx"
FGAIModelData(SGPropertyNode *root = NULL)
: _nasal( new FGNasalModelDataProxy(root) ),
_ready(false),
- _initialized(false)
+ _initialized(false),
+ _hasInteriorPath(false),
+ _interiorLoaded(false)
{
}
if (_ready)
return;
+ if(prop->hasChild("interior-path")){
+ _interiorPath = prop->getStringValue("interior-path");
+ _hasInteriorPath = true;
+ }
+
_fxpath = prop->getStringValue("sound/path");
_nasal->modelLoaded(path, prop, n);
bool needInitilization(void) { return _ready && !_initialized;}
bool isInitialized(void) { return _initialized;}
inline std::string& get_sound_path() { return _fxpath;}
-
+
+ void setInteriorLoaded(const bool state) { _interiorLoaded = state;}
+ bool getInteriorLoaded(void) { return _interiorLoaded;}
+ bool hasInteriorPath(void) { return _hasInteriorPath;}
+ inline std::string& getInteriorPath() { return _interiorPath; }
private:
std::auto_ptr<FGNasalModelDataProxy> _nasal;
std::string _fxpath;
bool _ready;
bool _initialized;
+
+ std::string _interiorPath;
+ bool _hasInteriorPath;
+ bool _interiorLoaded;
};
FGAIBase::FGAIBase(object_type ot, bool enableHot) :
return;
FGScenery* pSceneryManager = globals->get_scenery();
- if (pSceneryManager)
+ if (pSceneryManager && pSceneryManager->get_models_branch())
{
osg::ref_ptr<osg::Object> temp = _model.get();
- pSceneryManager->get_scene_graph()->removeChild(aip.getSceneGraph());
+ pSceneryManager->get_models_branch()->removeChild(aip.getSceneGraph());
// withdraw from SGModelPlacement and drop own reference (unref)
aip.clear();
_modeldata = 0;
}
else
{
- SG_LOG(SG_AI, SG_ALERT, "AIBase: Could not unload model. Missing scenery manager!");
+ aip.clear();
+ _model = 0;
+ _modeldata = 0;
}
}
}
}
}
+
+ updateInterior();
+}
+
+void FGAIBase::updateInterior()
+{
+ if(!_modeldata || !_modeldata->hasInteriorPath())
+ return;
+
+ if(!_modeldata->getInteriorLoaded()){ // interior is not yet load
+ double d2 = dist(SGVec3d::fromGeod(pos), globals->get_aircraft_position_cart());
+ if(d2 <= _maxRangeInterior){ // if the AI is in-range we load the interior
+ _interior = SGModelLib::loadPagedModel(_modeldata->getInteriorPath(), props, _modeldata);
+ if(_interior.valid()){
+ _interior->setRange(0, 0.0, _maxRangeInterior);
+ aip.add(_interior.get());
+ _modeldata->setInteriorLoaded(true);
+ SG_LOG(SG_AI, SG_INFO, "AIBase: Loaded interior model " << _interior->getName());
+ }
+ }
+ }
}
/** update LOD properties of the model */
void FGAIBase::updateLOD()
{
double maxRangeDetail = fgGetDouble("/sim/rendering/static-lod/ai-detailed", 10000.0);
- double maxRangeBare = fgGetDouble("/sim/rendering/static-lod/ai-bare", 20000.0);
+// double maxRangeBare = fgGetDouble("/sim/rendering/static-lod/ai-bare", 20000.0);
+
+ _maxRangeInterior = fgGetDouble("/sim/rendering/static-lod/ai-interior", 50.0);
if (_model.valid())
{
if( maxRangeDetail == 0.0 )
}
else
{
- _model->setRange(0, 0.0, maxRangeDetail);
- _model->setRange(1, maxRangeDetail,maxRangeBare);
+ if( fgGetBool("/sim/rendering/static-lod/ai-range-mode-pixel", false ) )
+ {
+ _model->setRangeMode( osg::LOD::PIXEL_SIZE_ON_SCREEN );
+ _model->setRange(0, maxRangeDetail, 100000 );
+ } else {
+ _model->setRangeMode( osg::LOD:: DISTANCE_FROM_EYE_POINT);
+ _model->setRange(0, 0.0, maxRangeDetail);
+ }
}
}
}
string f;
if(search_in_AI_path)
{
- // setup a modified Options structure, with only the $fg-root/AI defined;
- // we'll check that first, then give the normal search logic a chance.
- // this ensures that models in AI/ are preferred to normal models, where
- // both exist.
- osg::ref_ptr<osgDB::ReaderWriter::Options>
- opt(osg::clone(osgDB::Registry::instance()->getOptions(), osg::CopyOp::SHALLOW_COPY));
-
- osgDB::FilePathList& paths(opt->getDatabasePathList());
- paths.clear();
BOOST_FOREACH(SGPath p, globals->get_data_paths("AI")) {
- paths.push_back(p.str());
- }
- f = osgDB::findDataFile(model_path, opt.get());
- }
+ p.append(model_path);
+ if (p.exists()) {
+ f = p.str();
+ break;
+ }
+ } // of AI data paths iteration
+ } // of search in AI path
if (f.empty()) {
- f = simgear::SGModelLib::findDataFile(model_path);
+ f = simgear::SGModelLib::findDataFile(model_path);
}
if(f.empty())
else
_installed = true;
+ props->addChild("type")->setStringValue("AI");
_modeldata = new FGAIModelData(props);
- osg::Node * mdl = SGModelLib::loadDeferredModel(f, props, _modeldata);
+ _model= SGModelLib::loadPagedModel(f, props, _modeldata);
- _model = new osg::LOD;
_model->setName("AI-model range animation node");
- _model->addChild( mdl, 0, FLT_MAX );
- _model->setCenterMode(osg::LOD::USE_BOUNDING_SPHERE_CENTER);
- _model->setRangeMode(osg::LOD::DISTANCE_FROM_EYE_POINT);
+ // _model->setCenterMode(osg::LOD::USE_BOUNDING_SPHERE_CENTER);
+ // _model->setRangeMode(osg::LOD::DISTANCE_FROM_EYE_POINT);
+
// We really need low-resolution versions of AI/MP aircraft.
// Or at least dummy "stubs" with some default silhouette.
// _model->addChild( SGModelLib::loadPagedModel(fgGetString("/sim/multiplay/default-model", default_model),
// props, new FGNasalModelData(props)), FLT_MAX, FLT_MAX);
updateLOD();
-
- initModel(mdl);
+ initModel();
+
if (_model.valid() && _initialized == false) {
aip.init( _model.get() );
aip.setVisible(true);
invisible = false;
- globals->get_scenery()->get_scene_graph()->addChild(aip.getSceneGraph());
+ globals->get_scenery()->get_models_branch()->addChild(aip.getSceneGraph());
_initialized = true;
SG_LOG(SG_AI, SG_DEBUG, "AIBase: Loaded model " << model_path);
return true;
}
-void FGAIBase::initModel(osg::Node *node)
+void FGAIBase::initModel()
{
if (_model.valid()) {
return id;
}
-
-
+bool FGAIBase::isValid() {
+ //Either no flightplan or it is valid
+ return !fp || fp->isValidPlan();
+}