1
0
Fork 0

Support reloading Compositor instances at runtime via a fgcommand

This commit is contained in:
Fernando García Liñán 2020-12-17 04:21:53 +01:00
parent 1781bebb12
commit ae41eba3da
3 changed files with 65 additions and 7 deletions

View file

@ -34,6 +34,7 @@
#include <Sound/sample_queue.hxx> #include <Sound/sample_queue.hxx>
#include <Airports/xmlloader.hxx> #include <Airports/xmlloader.hxx>
#include <Network/HTTPClient.hxx> #include <Network/HTTPClient.hxx>
#include <Viewer/CameraGroup.hxx>
#include <Viewer/viewmgr.hxx> #include <Viewer/viewmgr.hxx>
#include <Viewer/view.hxx> #include <Viewer/view.hxx>
#include <Environment/presets.hxx> #include <Environment/presets.hxx>
@ -215,6 +216,15 @@ do_hires_screen_capture (const SGPropertyNode * arg, SGPropertyNode * root)
return true; 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. * Reload the tile cache.
@ -544,6 +554,7 @@ static struct {
{ "print-visible-scene", do_print_visible_scene_info }, { "print-visible-scene", do_print_visible_scene_info },
{ "reload-shaders", do_reload_shaders }, { "reload-shaders", do_reload_shaders },
{ "reload-materials", do_materials_reload }, { "reload-materials", do_materials_reload },
{ "reload-compositor", do_reload_compositor },
{ "open-launcher", do_open_launcher }, { "open-launcher", do_open_launcher },
{ 0, 0 } // zero-terminated { 0, 0 } // zero-terminated
}; };

View file

@ -689,10 +689,16 @@ void CameraGroup::buildCamera(SGPropertyNode* cameraNode)
// If no width or height has been specified, fill the entire window // If no width or height has been specified, fill the entire window
viewportNode->getDoubleValue("width", window->gc->getTraits()->width), viewportNode->getDoubleValue("width", window->gc->getTraits()->width),
viewportNode->getDoubleValue("height",window->gc->getTraits()->height)); 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", "");
std::string compositor_path = if (compositor_path.empty()) {
cameraNode->getStringValue("compositor", default_compositor.c_str()); 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 = osg::ref_ptr<SGReaderWriterOptions> options =
SGReaderWriterOptions::fromPath(globals->get_fg_root()); SGReaderWriterOptions::fromPath(globals->get_fg_root());
options->setPropertyNode(globals->get_props()); options->setPropertyNode(globals->get_props());
@ -705,7 +711,7 @@ void CameraGroup::buildCamera(SGPropertyNode* cameraNode)
compositor_path, compositor_path,
options); options);
if (compositor) { if (compositor) {
info->compositor = compositor; info->compositor.reset(compositor);
} else { } else {
throw sg_exception(std::string("Failed to create Compositor in path '") + throw sg_exception(std::string("Failed to create Compositor in path '") +
compositor_path + "'"); compositor_path + "'");
@ -787,7 +793,7 @@ void CameraGroup::buildGUICamera(SGPropertyNode* cameraNode,
info->name = "GUI camera"; info->name = "GUI camera";
info->viewOffset = osg::Matrix::identity(); info->viewOffset = osg::Matrix::identity();
info->projOffset = osg::Matrix::identity(); info->projOffset = osg::Matrix::identity();
info->compositor = compositor; info->compositor.reset(compositor);
_cameras.push_back(info); _cameras.push_back(info);
// Disable statistics for the GUI camera. // Disable statistics for the GUI camera.
@ -944,6 +950,36 @@ void warpGUIPointer(CameraGroup* cgroup, int x, int y)
cgroup->getView()->getEventQueue()->mouseWarped(viewerX, viewerY); 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) void CameraGroup::buildDefaultGroup(osgViewer::View* viewer)
{ {
// Look for windows, camera groups, and the old syntax of // Look for windows, camera groups, and the old syntax of

View file

@ -114,7 +114,12 @@ struct CameraInfo : public osg::Referenced
osg::Matrix viewMatrix, projMatrix; osg::Matrix viewMatrix, projMatrix;
/** The Compositor used to manage the pipeline of this camera. /** 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 class CameraGroup : public osg::Referenced
@ -190,6 +195,7 @@ protected:
const osg::Vec2d& windowPos, const osg::Vec2d& windowPos,
osgUtil::LineSegmentIntersector::Intersections& osgUtil::LineSegmentIntersector::Intersections&
intersections); intersections);
friend void reloadCompositors(CameraGroup *cgroup);
typedef std::vector<osg::ref_ptr<CameraInfo>> CameraList; typedef std::vector<osg::ref_ptr<CameraInfo>> CameraList;
CameraList _cameras; CameraList _cameras;
@ -237,6 +243,11 @@ bool computeIntersections(const CameraGroup* cgroup,
*/ */
void warpGUIPointer(CameraGroup* cgroup, int x, int y); 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 #endif