/* * CanvasWidget.cxx * * Created on: 03.07.2012 * Author: tom */ #ifdef HAVE_CONFIG_H # include #endif #include "CanvasWidget.hxx" #include #include
// fgGetKeyModifiers() #include #include #include SGPropertyNode_ptr CanvasWidget::_time; //------------------------------------------------------------------------------ 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(globals->get_subsystem("Canvas")) ), _tex_id(0), _no_tex_cnt(0), _last_x(0), _last_y(0) { if( !_canvas_mgr ) { SG_LOG(SG_GENERAL, SG_ALERT, "CanvasWidget: failed to get canvas manager!"); return; } _canvas = _canvas_mgr->createCanvas ( props->getStringValue("name", "gui-anonymous") ); int view[2] = { // Get canvas viewport size. If not specified use the widget dimensions props->getIntValue("view[0]", width), props->getIntValue("view[1]", height) }; SGPropertyNode* cprops = _canvas->getProps(); cprops->setIntValue("size[0]", view[0] * 2); // use higher resolution cprops->setIntValue("size[1]", view[1] * 2); // for antialias cprops->setIntValue("view[0]", view[0]); cprops->setIntValue("view[1]", view[1]); cprops->setBoolValue("render-always", true); cprops->setStringValue( "name", props->getStringValue("name", "gui-anonymous") ); SGPropertyNode* input = cprops->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 ) return; FGNasalSys *nas = dynamic_cast(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:") + cprops->getStringValue("name"); SGPropertyNode *load = nasal->getNode("load"); if( load ) { const char *s = load->getStringValue(); nas->handleCommand(module.c_str(), file.c_str(), s, cprops); } } //------------------------------------------------------------------------------ CanvasWidget::~CanvasWidget() { if( _canvas ) // TODO check if really not in use anymore _canvas->getProps() ->getParent() ->removeChild( _canvas->getProps()->getName(), _canvas->getProps()->getIndex(), false ); } // Old versions of PUI are missing this defines... #ifndef PU_SCROLL_UP_BUTTON # define PU_SCROLL_UP_BUTTON 3 #endif #ifndef PU_SCROLL_DOWN_BUTTON # define PU_SCROLL_DOWN_BUTTON 4 #endif //------------------------------------------------------------------------------ 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; namespace sc = simgear::canvas; sc::MouseEventPtr event(new sc::MouseEvent); if( !_time ) _time = globals->get_props()->getNode("/sim/time/elapsed-sec"); event->time = _time->getDoubleValue(); event->pos.set(x - abox.min[0], abox.max[1] - y); event->delta.set( event->pos.x() - _last_x, event->pos.y() - _last_y ); _last_x = event->pos.x(); _last_y = event->pos.y(); switch( button ) { case PU_LEFT_BUTTON: event->button = osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON; break; case PU_MIDDLE_BUTTON: event->button = osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON; break; case PU_RIGHT_BUTTON: event->button = osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON; break; case PU_SCROLL_UP_BUTTON: case PU_SCROLL_DOWN_BUTTON: // Only let PU_DOWN trigger a scroll wheel event if( updown != PU_DOWN ) return; event->type = sc::Event::WHEEL; event->delta.y() = button == PU_SCROLL_UP_BUTTON ? 1 : -1; _canvas->handleMouseEvent(event); return; default: SG_LOG(SG_INPUT, SG_WARN, "CanvasWidget: Unknown button: " << button); return; } switch( updown ) { case PU_DOWN: event->type = sc::Event::MOUSE_DOWN; puSetActiveWidget(this, x, y); break; case PU_UP: event->type = sc::Event::MOUSE_UP; puDeactivateWidget(); break; case PU_DRAG: event->type = sc::Event::DRAG; break; default: SG_LOG(SG_INPUT, SG_WARN, "CanvasWidget: Unknown updown: " << updown); return; } _canvas->handleMouseEvent(event); _mouse_x->setIntValue(x - abox.min[0]); _mouse_y->setIntValue(abox.max[1] - y); if( updown == PU_DRAG ) _mouse_drag->setIntValue(button); else if( updown == PU_DOWN ) _mouse_down->setIntValue(button); } //------------------------------------------------------------------------------ int CanvasWidget::checkKey(int key, int updown) { return puObject::checkKey(key, updown); } //------------------------------------------------------------------------------ void CanvasWidget::setSize(int w, int h) { puObject::setSize(w, h); _canvas->getProps()->setIntValue("view[0]", w); _canvas->getProps()->setIntValue("view[1]", h); } //------------------------------------------------------------------------------ void CanvasWidget::draw(int dx, int dy) { if( !_tex_id ) { _tex_id = _canvas_mgr->getCanvasTexId( _canvas->getProps()->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); }