]> git.mxchange.org Git - flightgear.git/blobdiff - src/GUI/CanvasWidget.cxx
Reset: GUI can be shutdown.
[flightgear.git] / src / GUI / CanvasWidget.cxx
index fea0f150f0667209db5956a949c5fc7eb07ccdbd..fc21d0c93cb1acfed2abd64a6061a129e2aa9a7f 100644 (file)
@@ -1,9 +1,20 @@
-/*
- * CanvasWidget.cxx
- *
- *  Created on: 03.07.2012
- *      Author: tom
- */
+// Airports forward declarations
+//
+// Copyright (C) 2012  Thomas Geymayer <tomgey@gmail.com>
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 #ifdef HAVE_CONFIG_H
 #  include <config.h>
 #include <Main/fg_os.hxx>      // fgGetKeyModifiers()
 #include <Scripting/NasalSys.hxx>
 
+#include <simgear/canvas/Canvas.hxx>
+#include <simgear/canvas/MouseEvent.hxx>
+
+SGPropertyNode_ptr CanvasWidget::_time,
+                   CanvasWidget::_view_height;
+
 //------------------------------------------------------------------------------
 CanvasWidget::CanvasWidget( int x, int y,
                             int width, int height,
@@ -22,8 +39,10 @@ CanvasWidget::CanvasWidget( int x, int y,
                             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)
+  _last_x(0),
+  _last_y(0),
+  // automatically resize viewport of canvas if no size is given
+  _auto_viewport( !props->hasChild("view") )
 {
   if( !_canvas_mgr )
   {
@@ -31,53 +50,44 @@ CanvasWidget::CanvasWidget( int x, int y,
     return;
   }
 
-  // Get the first unused canvas slot
-  SGPropertyNode* canvas_root = fgGetNode("/canvas", true);
-  for(int index = 0;; ++index)
+  _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 *nasal = props->getNode("nasal");
+  if( !nasal )
+    return;
+
+  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:")
+                         + cprops->getStringValue("name");
+
+  SGPropertyNode *load = nasal->getNode("load");
+  if( load )
   {
-    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;
-    }
+    const char *s = load->getStringValue();
+    nas->handleCommand(module.c_str(), file.c_str(), s, cprops);
   }
 }
 
@@ -85,10 +95,17 @@ CanvasWidget::CanvasWidget( int x, int y,
 CanvasWidget::~CanvasWidget()
 {
   if( _canvas )
-    _canvas->getParent()
-           ->removeChild(_canvas->getName(), _canvas->getIndex(), false);
+    _canvas->destroy();
 }
 
+// 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)
 {
@@ -98,21 +115,71 @@ void CanvasWidget::doHit(int button, int updown, int x, int y)
   if( fgGetKeyModifiers() & (KEYMOD_CTRL | KEYMOD_SHIFT) )
     return;
 
-  _mouse_x->setIntValue(x - abox.min[0]);
-  _mouse_y->setIntValue(abox.max[1] - y);
+  namespace sc = simgear::canvas;
+  sc::MouseEventPtr event(new sc::MouseEvent);
 
-  if( updown == PU_DRAG )
-    _mouse_drag->setIntValue(button);
-  else if( updown == PU_DOWN )
-    _mouse_down->setIntValue(button);
+  if( !_time )
+    _time = globals->get_props()->getNode("/sim/time/elapsed-sec");
+  event->time = _time->getDoubleValue();
 
-  if( button != active_mouse_button )
-    return;
+  if( !_view_height )
+    _view_height = globals->get_props()->getNode("/sim/gui/canvas/size[1]");
+  event->screen_pos.set(x, _view_height->getIntValue() - y);
+
+  event->client_pos.set(x - abox.min[0], abox.max[1] - y);
+  event->delta.set( event->getScreenX() - _last_x,
+                    event->getScreenY() - _last_y );
+
+  _last_x = event->getScreenX();
+  _last_y = event->getScreenY();
+
+  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;
 
-  if (updown == PU_UP)
-    puDeactivateWidget();
-  else if (updown == PU_DOWN)
-    puSetActiveWidget(this, x, y);
+      _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);
 }
 
 //------------------------------------------------------------------------------
@@ -126,41 +193,18 @@ void CanvasWidget::setSize(int w, int h)
 {
   puObject::setSize(w, h);
 
-  _canvas->setIntValue("view[0]", w);
-  _canvas->setIntValue("view[1]", h);
+  if( _auto_viewport )
+  {
+    _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->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);
+  glBindTexture(GL_TEXTURE_2D, _canvas_mgr->getCanvasTexId(_canvas));
   glBegin( GL_QUADS );
     glColor3f(1,1,1);
     glTexCoord2f(0,0); glVertex2f(dx + abox.min[0], dy + abox.min[1]);