#include <osg/MatrixTransform>
#include <osg/PositionAttitudeTransform>
#include <osg/CameraView>
+#include <osg/LOD>
+
#include <osgViewer/Viewer>
#include <simgear/constants.h>
+#include <simgear/sg_inlines.h>
#include <simgear/debug/logstream.hxx>
#include <simgear/scene/tgdb/userdata.hxx>
#include <simgear/scene/material/matlib.hxx>
#include <simgear/scene/util/OsgMath.hxx>
#include <simgear/scene/util/SGSceneUserData.hxx>
#include <simgear/scene/model/CheckSceneryVisitor.hxx>
+#include <simgear/scene/sky/sky.hxx>
+
#include <simgear/bvh/BVHNode.hxx>
#include <simgear/bvh/BVHLineSegmentVisitor.hxx>
+#include <simgear/structure/commands.hxx>
#include <Viewer/renderer.hxx>
#include <Main/fg_props.hxx>
+#include <GUI/MouseCursor.hxx>
#include "tilemgr.hxx"
#include "scenery.hxx"
class FGGroundPickCallback : public SGPickCallback {
public:
- virtual bool buttonPressed(int button, const Info& info)
+ FGGroundPickCallback() : SGPickCallback(PriorityScenery)
+ { }
+
+ virtual bool buttonPressed( int button,
+ const osgGA::GUIEventAdapter&,
+ const Info& info )
{
// only on left mouse button
if (button != 0)
bool _haveHit;
};
+class FGScenery::ScenerySwitchListener : public SGPropertyChangeListener
+{
+public:
+ ScenerySwitchListener(FGScenery* scenery) :
+ _scenery(scenery)
+ {
+ SGPropertyNode_ptr maskNode = fgGetNode("/sim/rendering/draw-mask", true);
+ maskNode->getChild("terrain", 0, true)->addChangeListener(this, true);
+ maskNode->getChild("models", 0, true)->addChangeListener(this, true);
+ maskNode->getChild("aircraft", 0, true)->addChangeListener(this, true);
+ maskNode->getChild("clouds", 0, true)->addChangeListener(this, true);
+
+ // legacy compatability option
+ fgGetNode("/sim/rendering/draw-otw")->addChangeListener(this);
+
+ // badly named property, this is what is set by --enable/disable-clouds
+ fgGetNode("/environment/clouds/status")->addChangeListener(this);
+ }
+
+ ~ScenerySwitchListener()
+ {
+ SGPropertyNode_ptr maskNode = fgGetNode("/sim/rendering/draw-mask");
+ for (int i=0; i < maskNode->nChildren(); ++i) {
+ maskNode->getChild(i)->removeChangeListener(this);
+ }
+
+ fgGetNode("/sim/rendering/draw-otw")->removeChangeListener(this);
+ fgGetNode("/environment/clouds/status")->removeChangeListener(this);
+ }
+
+ virtual void valueChanged (SGPropertyNode * node)
+ {
+ bool b = node->getBoolValue();
+ std::string name(node->getNameString());
+
+ if (name == "terrain") {
+ _scenery->scene_graph->setChildValue(_scenery->terrain_branch, b);
+ } else if (name == "models") {
+ _scenery->scene_graph->setChildValue(_scenery->models_branch, b);
+ } else if (name == "aircraft") {
+ _scenery->scene_graph->setChildValue(_scenery->aircraft_branch, b);
+ } else if (name == "clouds") {
+ // clouds live elsewhere in the scene, but we handle them here
+ globals->get_renderer()->getSky()->set_clouds_enabled(b);
+ } else if (name == "draw-otw") {
+ // legacy setting but let's keep it working
+ fgGetNode("/sim/rendering/draw-mask")->setBoolValue("terrain", b);
+ fgGetNode("/sim/rendering/draw-mask")->setBoolValue("models", b);
+ } else if (name == "status") {
+ fgGetNode("/sim/rendering/draw-mask")->setBoolValue("clouds", b);
+ }
+ }
+private:
+ FGScenery* _scenery;
+};
+
+////////////////////////////////////////////////////////////////////////////
+
// Scenery Management system
-FGScenery::FGScenery()
+FGScenery::FGScenery() :
+ _listener(NULL)
{
- SG_LOG( SG_TERRAIN, SG_INFO, "Initializing scenery subsystem" );
// keep reference to pager singleton, so it cannot be destroyed while FGScenery lives
_pager = FGScenery::getPagerSingleton();
+
+ // Initialise the state of the scene graph.
+ _inited = false;
}
-FGScenery::~FGScenery() {
+FGScenery::~FGScenery()
+{
+ delete _listener;
}
// Initialize the Scenery Management system
void FGScenery::init() {
+ // Already set up.
+ if (_inited)
+ return;
+
// Scene graph root
- scene_graph = new osg::Group;
- scene_graph->setName( "Scene" );
+ scene_graph = new osg::Switch;
+ scene_graph->setName( "FGScenery" );
// Terrain branch
terrain_branch = new osg::Group;
aircraft_branch->setName( "Aircraft" );
scene_graph->addChild( aircraft_branch.get() );
- // Initials values needed by the draw-time object loader
- sgUserDataInit( globals->get_props() );
+// choosing to make the interior branch a child of the main
+// aircraft group, for the moment. This simplifes places which
+// assume all aircraft elements are within this group - principally
+// FGODGuage::set_aircraft_texture.
+ interior_branch = new osg::Group;
+ interior_branch->setName( "Interior" );
+
+ osg::LOD* interiorLOD = new osg::LOD;
+ interiorLOD->addChild(interior_branch.get(), 0.0, 50.0);
+ aircraft_branch->addChild( interiorLOD );
+
+ // Set up the particle system as a directly accessible branch of the scene graph.
+ particles_branch = simgear::Particles::getCommonRoot();
+ particles_branch->setName("Particles");
+ scene_graph->addChild(particles_branch.get());
+ simgear::GlobalParticleCallback::setSwitch(fgGetNode("/sim/rendering/particles", true));
+
+ // Set up the precipitation system.
+ precipitation_branch = new osg::Group;
+ precipitation_branch->setName("Precipitation");
+ scene_graph->addChild(precipitation_branch.get());
+
+ _listener = new ScenerySwitchListener(this);
+
+ // Toggle the setup flag.
+ _inited = true;
+}
+
+void FGScenery::shutdown()
+{
+ scene_graph = NULL;
+ terrain_branch = NULL;
+ models_branch = NULL;
+ aircraft_branch = NULL;
+ particles_branch = NULL;
+
+ // Toggle the setup flag.
+ _inited = false;
}
-void FGScenery::update(double dt) {
+void FGScenery::update(double dt)
+{
+ SG_UNUSED(dt);
+ // nothing here, don't call again
+ suspend();
}
// while the splashscreen is there, so CheckSceneryVisitor force-loads
// missing objects in the main thread
get_scene_graph()->accept(csnv);
- if(!csnv.isLoaded())
+ if(!csnv.isLoaded()) {
+ SG_LOG(SG_TERRAIN, SG_DEBUG, "FGScenery::scenery_available: waiting on CheckSceneryVisitor");
return false;
+ }
return true;
+ } else {
+ SG_LOG(SG_TERRAIN, SG_DEBUG, "FGScenery::scenery_available: waiting on tile manager");
}
return false;
}
+static osg::ref_ptr<SceneryPager> pager;
+
SceneryPager* FGScenery::getPagerSingleton()
{
- static osg::ref_ptr<SceneryPager> pager = new SceneryPager;
+ if (!pager)
+ pager = new SceneryPager;
return pager.get();
}
+void FGScenery::resetPagerSingleton()
+{
+ pager = NULL;
+}
+