|
|
Line 184: |
Line 184: |
|
| |
|
| == Patches == | | == Patches == |
| === SimGear ===
| |
| <syntaxhighlight lang="diff">
| |
| --- /simgear/simgear/canvas/Canvas.hxx 2016-05-17 02:40:01.297701130 +0200
| |
| +++ canvas/Canvas.hxx 2016-10-19 16:46:47.000000000 +0200
| |
| @@ -44,6 +44,14 @@
| |
| class CanvasMgr;
| |
| class MouseEvent;
| |
|
| |
| + class CanvasImageReadyListener {
| |
| + public:
| |
| + virtual void imageReady(osg::ref_ptr<osg::Image>) = 0;
| |
| + virtual ~CanvasImageReadyListener()
| |
| + {
| |
| + }
| |
| + };
| |
| +
| |
| /**
| |
| * Canvas to draw onto (to an off-screen render target).
| |
| */
| |
| @@ -162,6 +170,9 @@
| |
|
| |
| void update(double delta_time_sec);
| |
|
| |
| + int subscribe(CanvasImageReadyListener * subscriber);
| |
| + int unsubscribe(CanvasImageReadyListener * subscriber);
| |
| +
| |
| bool addEventListener(const std::string& type, const EventListener& cb);
| |
| bool dispatchEvent(const EventPtr& event);
| |
| </syntaxhighlight>
| |
|
| |
| <syntaxhighlight lang="diff">
| |
| --- /simgear/simgear/canvas/Canvas.cxx 2016-05-17 02:40:01.297701130 +0200
| |
| +++ Canvas.cxx 2016-10-20 08:04:14.000000000 +0200
| |
| @@ -37,6 +37,66 @@
| |
| {
| |
| namespace canvas
| |
| {
| |
| + class CanvasImageCallback : public osg::Camera::DrawCallback {
| |
| + public:
| |
| + osg::Image *_rawImage;
| |
| +
| |
| + CanvasImageCallback(osg::Image *rawImage)
| |
| + : _min_delta_tick(1.0 / 8.0) {
| |
| + _previousFrameTick = osg::Timer::instance()->tick();
| |
| + _rawImage = rawImage;
| |
| + }
| |
| +
| |
| + virtual void operator()(osg::RenderInfo& renderInfo/*const osg::Camera& camera*/) const {
| |
| + osg::Timer_t n = osg::Timer::instance()->tick();
| |
| + double dt = osg::Timer::instance()->delta_s(_previousFrameTick, n);
| |
| + if (dt < _min_delta_tick)
| |
| + return;
| |
| + _previousFrameTick = n;
| |
| +
| |
| + bool hasSubscribers = false;
| |
| + {
| |
| + OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_lock);
| |
| + hasSubscribers = !_subscribers.empty();
| |
| + }
| |
| + if (hasSubscribers) {
| |
| + //Make sure image can be overwritten by next frame while it is still returned to the client
| |
| + osg::Image* image = new osg::Image(*_rawImage, osg::CopyOp::DEEP_COPY_ALL);
| |
| + {
| |
| + OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_lock);
| |
| + while (!_subscribers.empty()) {
| |
| + try {
| |
| + SG_LOG(SG_GENERAL,SG_INFO,"CanvasImageCallback image ready for subscriber");
| |
| + CanvasImageReadyListener *subs = _subscribers.back();
| |
| + if (subs){
| |
| + subs->imageReady(image);
| |
| + }else{
| |
| + SG_LOG(SG_GENERAL,SG_WARN,"CanvasImageCallback subscriber null");
| |
| + }
| |
| + } catch (...) { }
| |
| + _subscribers.pop_back();
| |
| + }
| |
| + }
| |
| + }
| |
| + }
| |
| +
| |
| + void subscribe(CanvasImageReadyListener * subscriber) {
| |
| + OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_lock);
| |
| + _subscribers.push_back(subscriber);
| |
| + }
| |
| +
| |
| + void unsubscribe(CanvasImageReadyListener * subscriber) {
| |
| + OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_lock);
| |
| + _subscribers.remove(subscriber);
| |
| + }
| |
| +
| |
| + private:
| |
| + mutable list<CanvasImageReadyListener*> _subscribers;
| |
| + mutable OpenThreads::Mutex _lock;
| |
| + mutable double _previousFrameTick;
| |
| + double _min_delta_tick;
| |
| + };
| |
| +
| |
|
| |
| //----------------------------------------------------------------------------
| |
| Canvas::CullCallback::CullCallback(const CanvasWeakPtr& canvas):
| |
| @@ -251,6 +311,22 @@
| |
|
| |
| osg::Camera* camera = _texture.getCamera();
| |
|
| |
| + const char *canvasname = _node->getStringValue("name");
| |
| + int rendertoimage = _node->getBoolValue("rendertoimage");
| |
| + if (camera && rendertoimage && canvasname) {
| |
| + SG_LOG(SG_GENERAL,SG_INFO,"rendertoimage of canvas "<< rendertoimage);
| |
| +
| |
| + CanvasImageCallback *_screenshotCallback = dynamic_cast<CanvasImageCallback*> (camera->getFinalDrawCallback());
| |
| + if (!_screenshotCallback) {
| |
| + osg::Image* shot = new osg::Image();
| |
| + shot->allocateImage(getSizeX(), getSizeY(), 24, GL_RGB, GL_UNSIGNED_BYTE);
| |
| + camera->attach(osg::Camera::COLOR_BUFFER, shot);
| |
| + camera->setFinalDrawCallback(new CanvasImageCallback(shot));
| |
| + SG_LOG(SG_GENERAL,SG_INFO,"attached");
| |
| + }
| |
| + }
| |
| +
| |
| +
| |
| // TODO Allow custom render order? For now just keep in order with
| |
| // property tree.
| |
| camera->setRenderOrder(osg::Camera::PRE_RENDER, _node->getIndex());
| |
| @@ -350,6 +426,36 @@
| |
| }
| |
| }
| |
|
| |
| + int Canvas::subscribe(CanvasImageReadyListener * subscriber) {
| |
| + if (!_node->getBoolValue("rendertoimage")) {
| |
| + SG_LOG(SG_GENERAL,SG_INFO,"Setting rendertoimage");
| |
| + _node->addChild("rendertoimage", 0)->setBoolValue(1);
| |
| + setStatusFlags(STATUS_DIRTY, true);
| |
| + }
| |
| +
| |
| + osg::Camera* camera = _texture.getCamera();
| |
| + SG_LOG(SG_GENERAL,SG_INFO,"Canvas: subscribe to camera "<< camera);
| |
| + CanvasImageCallback *_screenshotCallback = dynamic_cast<CanvasImageCallback*> (camera->getFinalDrawCallback());
| |
| + if (_screenshotCallback) {
| |
| + SG_LOG(SG_GENERAL,SG_INFO,"Canvas: really subscribe to camera ");
| |
| + _screenshotCallback->subscribe(subscriber);
| |
| + // TODO: check: Is this the correct way to ensure the canvas will be available?
| |
| + enableRendering(true);
| |
| + }
| |
| + return 0;
| |
| + }
| |
| +
| |
| + int Canvas::unsubscribe(CanvasImageReadyListener * subscriber) {
| |
| + osg::Camera* camera = _texture.getCamera();
| |
| + SG_LOG(SG_GENERAL,SG_INFO,"CanvasImage: unsubscribe from camera "<< camera);
| |
| + CanvasImageCallback *cb = dynamic_cast<CanvasImageCallback*> (camera->getFinalDrawCallback());
| |
| + if (cb) {
| |
| + SG_LOG(SG_GENERAL,SG_INFO,"CanvasImage: unsubscribe ");
| |
| + cb->unsubscribe(subscriber);
| |
| + }
| |
| + return 0;
| |
| + }
| |
| +
| |
| //----------------------------------------------------------------------------
| |
| bool Canvas::addEventListener( const std::string& type,
| |
| const EventListener& cb )
| |
|
| |
| </syntaxhighlight>
| |
|
| |
| === FlightGear === | | === FlightGear === |
| <syntaxhighlight lang="diff"> | | <syntaxhighlight lang="diff"> |