#include "canvas.hxx"
#include "elements/group.hxx"
+
#include <Canvas/property_helper.hxx>
+#include <Main/globals.hxx>
+#include <Viewer/renderer.hxx>
#include <osg/Camera>
#include <osg/Geode>
#include <osgText/Text>
+#include <osgViewer/Viewer>
#include <iostream>
_status(0),
_sampling_dirty(false),
_color_dirty(true),
- _node(0)
+ _node(0),
+ _render_always(false)
{
setStatusFlags(MISSING_SIZE_X | MISSING_SIZE_Y);
- CameraCullCallback *camera_callback = new CameraCullCallback;
- _camera_callback = camera_callback;
- _cull_callback = new PlacementCullCallback(this, camera_callback);
+ _camera_callback = new CameraCullCallback;
+ _cull_callback = new PlacementCullCallback(this, _camera_callback);
}
//------------------------------------------------------------------------------
_cull_callback
);
}
+
+ if( _render_always )
+ _camera_callback->enableRendering();
}
//------------------------------------------------------------------------------
|| node->getNameString() == "coverage-samples"
|| node->getNameString() == "color-samples" )
_sampling_dirty = true;
+ else if( node->getNameString() == "render-always" )
+ _render_always = node->getBoolValue();
}
_root_group->valueChanged(node);
}
+//------------------------------------------------------------------------------
+GLuint Canvas::getTexId() const
+{
+ osg::Texture2D* tex = _texture.getTexture();
+ if( !tex )
+ return 0;
+
+ osgViewer::Viewer::Contexts contexts;
+ globals->get_renderer()->getViewer()->getContexts(contexts);
+
+ if( contexts.empty() )
+ return 0;
+
+ osg::State* state = contexts[0]->getState();
+ if( !state )
+ return 0;
+
+ osg::Texture::TextureObject* tobj =
+ tex->getTextureObject( state->getContextID() );
+ if( !tobj )
+ return 0;
+
+ return tobj->_id;
+}
+
//------------------------------------------------------------------------------
void Canvas::setStatusFlags(unsigned int flags, bool set)
{
class Group;
}
+class CameraCullCallback;
class Canvas:
public SGPropertyChangeListener
{
SGPropertyNode * child );
virtual void valueChanged (SGPropertyNode * node);
+ GLuint getTexId() const;
+
private:
Canvas(const Canvas&); // = delete;
SGPropertyNode_ptr _node;
std::vector<SGPropertyNode_ptr> _color_background;
- osg::ref_ptr<osg::NodeCallback> _camera_callback;
+ osg::ref_ptr<CameraCullCallback> _camera_callback;
osg::ref_ptr<osg::NodeCallback> _cull_callback;
+
+ bool _render_always; //<! Used to disable automatic lazy rendering (culling)
+
std::vector<SGPropertyNode*> _dirty_placements;
std::vector<Placements> _placements;
}
}
+//------------------------------------------------------------------------------
+unsigned int CanvasMgr::getCanvasTexId(size_t index) const
+{
+ if( index >= _canvases.size()
+ || !_canvases[index] )
+ return 0;
+
+ return _canvases[index]->getTexId();
+}
+
//------------------------------------------------------------------------------
void CanvasMgr::textureAdded(SGPropertyNode* node)
{
_canvases.resize(index + 1);
}
- else
- {
+ else if( _canvases[index] )
SG_LOG(SG_GL, SG_WARN, "texture[" << index << "] already exists!");
- }
_canvases[index].reset( new Canvas() );
_canvases[index]->reset(node);
virtual void childRemoved( SGPropertyNode * parent,
SGPropertyNode * child );
+ /**
+ * Get OpenGL texture name for given canvas
+ *
+ * @param Index of canvas
+ * @return OpenGL texture name
+ */
+ unsigned int getCanvasTexId(size_t index) const;
+
private:
/** Root node for everything concerning the canvas system */
set(SOURCES
AirportList.cxx
+ CanvasWidget.cxx
MapWidget.cxx
WaypointList.cxx
dialog.cxx
set(HEADERS
AirportList.hxx
+ CanvasWidget.hxx
MapWidget.hxx
WaypointList.hxx
dialog.hxx
--- /dev/null
+/*
+ * CanvasWidget.cxx
+ *
+ * Created on: 03.07.2012
+ * Author: tom
+ */
+
+#include "CanvasWidget.hxx"
+
+#include <Canvas/canvas_mgr.hxx>
+#include <Main/fg_os.hxx> // fgGetKeyModifiers()
+#include <Scripting/NasalSys.hxx>
+
+//------------------------------------------------------------------------------
+CanvasWidget::CanvasWidget( int x, int y,
+ int width, int height,
+ SGPropertyNode* props,
+ const std::string& module ):
+ puObject(x, y, width, height),
+ _canvas_mgr( dynamic_cast<CanvasMgr*>(globals->get_subsystem("Canvas")) ),
+ _tex_id(0),
+ _no_tex_cnt(0)
+{
+ if( !_canvas_mgr )
+ {
+ SG_LOG(SG_GENERAL, SG_ALERT, "CanvasWidget: failed to get canvas manager!");
+ return;
+ }
+
+ // Get the first unused canvas slot
+ SGPropertyNode* canvas_root = fgGetNode("/canvas", true);
+ for(int index = 0;; ++index)
+ {
+ if( !canvas_root->getChild("texture", index) )
+ {
+ int view[2] = {
+ // Get canvas viewport size. If not specified use the widget dimensions
+ props->getIntValue("view[0]", width),
+ props->getIntValue("view[1]", height)
+ };
+ _canvas = canvas_root->getChild("texture", index, true);
+ _canvas->setIntValue("size[0]", view[0] * 2); // use higher resolution
+ _canvas->setIntValue("size[1]", view[1] * 2); // for antialias
+ _canvas->setIntValue("view[0]", view[0]);
+ _canvas->setIntValue("view[1]", view[1]);
+ _canvas->setBoolValue("render-always", true);
+ _canvas->setStringValue( "name",
+ props->getStringValue("name", "gui-anonymous") );
+ SGPropertyNode* input = _canvas->getChild("input", 0, true);
+ _mouse_x = input->getChild("mouse-x", 0, true);
+ _mouse_y = input->getChild("mouse-y", 0, true);
+ _mouse_down = input->getChild("mouse-down", 0, true);
+ _mouse_drag = input->getChild("mouse-drag", 0, true);
+
+ SGPropertyNode *nasal = props->getNode("nasal");
+ if( !nasal )
+ break;
+
+ FGNasalSys *nas =
+ dynamic_cast<FGNasalSys*>(globals->get_subsystem("nasal"));
+ if( !nas )
+ SG_LOG( SG_GENERAL,
+ SG_ALERT,
+ "CanvasWidget: Failed to get nasal subsystem!" );
+
+ const std::string file = std::string("__canvas:")
+ + _canvas->getStringValue("name");
+
+ SGPropertyNode *load = nasal->getNode("load");
+ if( load )
+ {
+ const char *s = load->getStringValue();
+ nas->handleCommand(module.c_str(), file.c_str(), s, _canvas);
+ }
+ break;
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+CanvasWidget::~CanvasWidget()
+{
+ if( _canvas )
+ _canvas->getParent()
+ ->removeChild(_canvas->getName(), _canvas->getIndex(), false);
+}
+
+//------------------------------------------------------------------------------
+void CanvasWidget::doHit(int button, int updown, int x, int y)
+{
+ puObject::doHit(button, updown, x, y);
+
+ // CTRL allows resizing and SHIFT allows moving the window
+ if( fgGetKeyModifiers() & (KEYMOD_CTRL | KEYMOD_SHIFT) )
+ return;
+
+ _mouse_x->setIntValue(x - abox.min[0]);
+ _mouse_y->setIntValue(y - abox.min[1]);
+
+ if( updown == PU_DRAG )
+ _mouse_drag->setIntValue(button);
+ else if( updown == PU_DOWN )
+ _mouse_down->setIntValue(button);
+
+ if( button != active_mouse_button )
+ return;
+
+ if (updown == PU_UP)
+ puDeactivateWidget();
+ else if (updown == PU_DOWN)
+ puSetActiveWidget(this, x, y);
+}
+
+//------------------------------------------------------------------------------
+int CanvasWidget::checkKey(int key, int updown)
+{
+ return puObject::checkKey(key, updown);
+}
+
+//------------------------------------------------------------------------------
+void CanvasWidget::setSize(int w, int h)
+{
+ puObject::setSize(w, h);
+
+ _canvas->setIntValue("view[0]", w);
+ _canvas->setIntValue("view[1]", h);
+}
+
+//------------------------------------------------------------------------------
+void CanvasWidget::draw(int dx, int dy)
+{
+ if( !_tex_id )
+ {
+ _tex_id = _canvas_mgr->getCanvasTexId(_canvas->getIndex());
+
+ // Normally we should be able to get the texture after one frame. I don't
+ // know if there are circumstances where it can take longer, so we don't
+ // log a warning message until we have tried a few times.
+ if( !_tex_id )
+ {
+ if( ++_no_tex_cnt == 5 )
+ SG_LOG(SG_GENERAL, SG_WARN, "CanvasWidget: failed to get texture!");
+ return;
+ }
+ else
+ {
+ if( _no_tex_cnt >= 5 )
+ SG_LOG
+ (
+ SG_GENERAL,
+ SG_INFO,
+ "CanvasWidget: got texture after " << _no_tex_cnt << " tries."
+ );
+ _no_tex_cnt = 0;
+ }
+ }
+
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, _tex_id);
+ glBegin( GL_QUADS );
+ glColor3f(1,1,1);
+ glTexCoord2f(0,0); glVertex2f(dx + abox.min[0], dy + abox.min[1]);
+ glTexCoord2f(1,0); glVertex2f(dx + abox.max[0], dy + abox.min[1]);
+ glTexCoord2f(1,1); glVertex2f(dx + abox.max[0], dy + abox.max[1]);
+ glTexCoord2f(0,1); glVertex2f(dx + abox.min[0], dy + abox.max[1]);
+ glEnd();
+ glDisable(GL_TEXTURE_2D);
+}
--- /dev/null
+/*
+ * CanvasWidget.hxx
+ *
+ * Created on: 03.07.2012
+ * Author: tom
+ */
+
+#ifndef CANVASWIDGET_HXX_
+#define CANVASWIDGET_HXX_
+
+#include <Main/fg_props.hxx>
+#include <plib/pu.h>
+
+class CanvasMgr;
+
+class CanvasWidget:
+ public puObject
+{
+ public:
+ CanvasWidget( int x, int y,
+ int width, int height,
+ SGPropertyNode* props,
+ const std::string& module );
+ virtual ~CanvasWidget();
+
+ virtual void doHit (int button, int updown, int x, int y);
+ virtual int checkKey(int key , int updown);
+
+ virtual void setSize ( int w, int h );
+ virtual void draw(int dx, int dy);
+
+ private:
+
+ CanvasMgr *_canvas_mgr; // TODO maybe we should store this in some central
+ // location or make it static...
+
+ GLuint _tex_id; //<! OpenGL texture id if canvas
+ size_t _no_tex_cnt;//<! Count since how many frames we were not
+ // able to get the texture (for debugging)
+ SGPropertyNode_ptr _canvas; //<! Canvas root property node
+ SGPropertyNode *_mouse_x,
+ *_mouse_y,
+ *_mouse_down,
+ *_mouse_drag;
+};
+
+#endif /* CANVASWIDGET_HXX_ */
#include "property_list.hxx"
#include "layout.hxx"
#include "WaypointList.hxx"
+#include "CanvasWidget.hxx"
#include "MapWidget.hxx"
#include "FGFontCache.hxx"
#include "FGColor.hxx"
MapWidget* mapWidget = new MapWidget(x, y, x + width, y + height);
setupObject(mapWidget, props);
return mapWidget;
+ } else if (type == "canvas") {
+ CanvasWidget* canvasWidget = new CanvasWidget( x, y,
+ x + width, y + height,
+ props,
+ _module );
+ setupObject(canvasWidget, props);
+ return canvasWidget;
} else if (type == "combo") {
fgComboBox *obj = new fgComboBox(x, y, x + width, y + height, props,
props->getBoolValue("editable", false));
/**
* Get the OSG camera for drawing this gauge.
*/
- osg::Camera* getCamera() { return camera.get(); }
+ osg::Camera* getCamera() const { return camera.get(); }
- osg::Texture2D* getTexture() { return texture.get(); }
+ osg::Texture2D* getTexture() const { return texture.get(); }
//void setTexture(osg::Texture2D* t) { texture = t; }
// Real initialization function. Bad name.
////////////////////////////////////////////////////////////////////
// Initialize the canvas 2d drawing subsystem.
////////////////////////////////////////////////////////////////////
- globals->add_subsystem("Canvas2D", new CanvasMgr, SGSubsystemMgr::DISPLAY);
+ globals->add_subsystem("Canvas", new CanvasMgr, SGSubsystemMgr::DISPLAY);
////////////////////////////////////////////////////////////////////
// Initialise the ATIS Manager
return naBindFunction(_context, code, _globals);
}
-bool FGNasalSys::handleCommand(const SGPropertyNode* arg)
+bool FGNasalSys::handleCommand( const char* moduleName,
+ const char* fileName,
+ const char* src,
+ const SGPropertyNode* arg )
{
- const char* nasal = arg->getStringValue("script");
- const char* moduleName = arg->getStringValue("module");
- naRef code = parse(arg->getPath(true).c_str(), nasal, strlen(nasal));
+ naRef code = parse(fileName, src, strlen(src));
if(naIsNil(code)) return false;
// Commands can be run "in" a module. Make sure that module
return true;
}
+bool FGNasalSys::handleCommand(const SGPropertyNode* arg)
+{
+ const char* src = arg->getStringValue("script");
+ const char* moduleName = arg->getStringValue("module");
+
+ return handleCommand( moduleName,
+ arg ? arg->getPath(true).c_str() : moduleName,
+ src,
+ arg );
+}
+
// settimer(func, dt, simtime) extension function. The first argument
// is a Nasal function to call, the second is a delta time (from now),
// in seconds. The third, if present, is a boolean value indicating
naRef cmdArgGhost();
// Callbacks for command and timer bindings
+ virtual bool handleCommand( const char* moduleName,
+ const char* fileName,
+ const char* src,
+ const SGPropertyNode* arg = 0 );
virtual bool handleCommand(const SGPropertyNode* arg);
bool createModule(const char* moduleName, const char* fileName,