Support reloading Compositor instances at runtime via a fgcommand
This commit is contained in:
parent
1781bebb12
commit
ae41eba3da
3 changed files with 65 additions and 7 deletions
|
@ -34,6 +34,7 @@
|
|||
#include <Sound/sample_queue.hxx>
|
||||
#include <Airports/xmlloader.hxx>
|
||||
#include <Network/HTTPClient.hxx>
|
||||
#include <Viewer/CameraGroup.hxx>
|
||||
#include <Viewer/viewmgr.hxx>
|
||||
#include <Viewer/view.hxx>
|
||||
#include <Environment/presets.hxx>
|
||||
|
@ -215,6 +216,15 @@ do_hires_screen_capture (const SGPropertyNode * arg, SGPropertyNode * root)
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload all Compositor instances in the default CameraGroup.
|
||||
*/
|
||||
static bool
|
||||
do_reload_compositor(const SGPropertyNode*, SGPropertyNode*)
|
||||
{
|
||||
flightgear::reloadCompositors(flightgear::CameraGroup::getDefault());
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload the tile cache.
|
||||
|
@ -544,6 +554,7 @@ static struct {
|
|||
{ "print-visible-scene", do_print_visible_scene_info },
|
||||
{ "reload-shaders", do_reload_shaders },
|
||||
{ "reload-materials", do_materials_reload },
|
||||
{ "reload-compositor", do_reload_compositor },
|
||||
{ "open-launcher", do_open_launcher },
|
||||
{ 0, 0 } // zero-terminated
|
||||
};
|
||||
|
|
|
@ -689,10 +689,16 @@ void CameraGroup::buildCamera(SGPropertyNode* cameraNode)
|
|||
// If no width or height has been specified, fill the entire window
|
||||
viewportNode->getDoubleValue("width", window->gc->getTraits()->width),
|
||||
viewportNode->getDoubleValue("height",window->gc->getTraits()->height));
|
||||
std::string default_compositor =
|
||||
fgGetString("/sim/rendering/default-compositor", "Compositor/default");
|
||||
std::string compositor_path =
|
||||
cameraNode->getStringValue("compositor", default_compositor.c_str());
|
||||
|
||||
std::string compositor_path = cameraNode->getStringValue("compositor", "");
|
||||
if (compositor_path.empty()) {
|
||||
compositor_path = fgGetString("/sim/rendering/default-compositor",
|
||||
"Compositor/default");
|
||||
} else {
|
||||
// Store the custom path in case we need to reload later
|
||||
info->compositor_path = compositor_path;
|
||||
}
|
||||
|
||||
osg::ref_ptr<SGReaderWriterOptions> options =
|
||||
SGReaderWriterOptions::fromPath(globals->get_fg_root());
|
||||
options->setPropertyNode(globals->get_props());
|
||||
|
@ -705,7 +711,7 @@ void CameraGroup::buildCamera(SGPropertyNode* cameraNode)
|
|||
compositor_path,
|
||||
options);
|
||||
if (compositor) {
|
||||
info->compositor = compositor;
|
||||
info->compositor.reset(compositor);
|
||||
} else {
|
||||
throw sg_exception(std::string("Failed to create Compositor in path '") +
|
||||
compositor_path + "'");
|
||||
|
@ -787,7 +793,7 @@ void CameraGroup::buildGUICamera(SGPropertyNode* cameraNode,
|
|||
info->name = "GUI camera";
|
||||
info->viewOffset = osg::Matrix::identity();
|
||||
info->projOffset = osg::Matrix::identity();
|
||||
info->compositor = compositor;
|
||||
info->compositor.reset(compositor);
|
||||
_cameras.push_back(info);
|
||||
|
||||
// Disable statistics for the GUI camera.
|
||||
|
@ -944,6 +950,36 @@ void warpGUIPointer(CameraGroup* cgroup, int x, int y)
|
|||
cgroup->getView()->getEventQueue()->mouseWarped(viewerX, viewerY);
|
||||
}
|
||||
|
||||
void reloadCompositors(CameraGroup *cgroup)
|
||||
{
|
||||
for (auto &info : cgroup->_cameras) {
|
||||
// Ignore the GUI camera
|
||||
if (info->flags & CameraInfo::GUI)
|
||||
continue;
|
||||
// Get the viewport and the graphics context from the old Compositor
|
||||
osg::ref_ptr<osg::Viewport> viewport = info->compositor->getViewport();
|
||||
osg::ref_ptr<osg::GraphicsContext> gc =
|
||||
info->compositor->getGraphicsContext();
|
||||
osg::ref_ptr<SGReaderWriterOptions> options =
|
||||
SGReaderWriterOptions::fromPath(globals->get_fg_root());
|
||||
options->setPropertyNode(globals->get_props());
|
||||
|
||||
cgroup->_viewer->getViewerBase()->stopThreading();
|
||||
// Force deletion
|
||||
info->compositor.reset(nullptr);
|
||||
// Then replace it with a new instance
|
||||
std::string compositor_path = info->compositor_path.empty() ?
|
||||
fgGetString("/sim/rendering/default-compositor", "Compositor/default") :
|
||||
info->compositor_path;
|
||||
info->compositor.reset(Compositor::create(cgroup->_viewer,
|
||||
gc,
|
||||
viewport,
|
||||
compositor_path,
|
||||
options));
|
||||
cgroup->_viewer->getViewerBase()->startThreading();
|
||||
}
|
||||
}
|
||||
|
||||
void CameraGroup::buildDefaultGroup(osgViewer::View* viewer)
|
||||
{
|
||||
// Look for windows, camera groups, and the old syntax of
|
||||
|
|
|
@ -114,7 +114,12 @@ struct CameraInfo : public osg::Referenced
|
|||
osg::Matrix viewMatrix, projMatrix;
|
||||
/** The Compositor used to manage the pipeline of this camera.
|
||||
*/
|
||||
osg::ref_ptr<simgear::compositor::Compositor> compositor;
|
||||
std::unique_ptr<simgear::compositor::Compositor> compositor;
|
||||
/** Compositor path. Used to recreate the pipeline when reloading.
|
||||
* If the path is empty, it means that this camera isn't using a custom
|
||||
* Compositor path and should use the default one.
|
||||
*/
|
||||
std::string compositor_path;
|
||||
};
|
||||
|
||||
class CameraGroup : public osg::Referenced
|
||||
|
@ -190,6 +195,7 @@ protected:
|
|||
const osg::Vec2d& windowPos,
|
||||
osgUtil::LineSegmentIntersector::Intersections&
|
||||
intersections);
|
||||
friend void reloadCompositors(CameraGroup *cgroup);
|
||||
|
||||
typedef std::vector<osg::ref_ptr<CameraInfo>> CameraList;
|
||||
CameraList _cameras;
|
||||
|
@ -237,6 +243,11 @@ bool computeIntersections(const CameraGroup* cgroup,
|
|||
*/
|
||||
void warpGUIPointer(CameraGroup* cgroup, int x, int y);
|
||||
|
||||
/** Force a reload of all Compositor instances in the CameraGroup,
|
||||
* except the one used by the GUI camera.
|
||||
*/
|
||||
void reloadCompositors(CameraGroup *cgroup);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue