]> git.mxchange.org Git - flightgear.git/blob - src/GUI/CanvasWidget.cxx
Merge branch 'timoore/optimization' into next
[flightgear.git] / src / GUI / CanvasWidget.cxx
1 /*
2  * CanvasWidget.cxx
3  *
4  *  Created on: 03.07.2012
5  *      Author: tom
6  */
7
8 #ifdef HAVE_CONFIG_H
9 #  include <config.h>
10 #endif
11
12 #include "CanvasWidget.hxx"
13
14 #include <Canvas/canvas_mgr.hxx>
15 #include <Main/fg_os.hxx>      // fgGetKeyModifiers()
16 #include <Scripting/NasalSys.hxx>
17
18 //------------------------------------------------------------------------------
19 CanvasWidget::CanvasWidget( int x, int y,
20                             int width, int height,
21                             SGPropertyNode* props,
22                             const std::string& module ):
23   puObject(x, y, width, height),
24   _canvas_mgr( dynamic_cast<CanvasMgr*>(globals->get_subsystem("Canvas")) ),
25   _tex_id(0),
26   _no_tex_cnt(0)
27 {
28   if( !_canvas_mgr )
29   {
30     SG_LOG(SG_GENERAL, SG_ALERT, "CanvasWidget: failed to get canvas manager!");
31     return;
32   }
33
34   // Get the first unused canvas slot
35   SGPropertyNode* canvas_root = fgGetNode("/canvas", true);
36   for(int index = 0;; ++index)
37   {
38     if( !canvas_root->getChild("texture", index) )
39     {
40       int view[2] = {
41         // Get canvas viewport size. If not specified use the widget dimensions
42         props->getIntValue("view[0]", width),
43         props->getIntValue("view[1]", height)
44       };
45       _canvas = canvas_root->getChild("texture", index, true);
46       _canvas->setIntValue("size[0]", view[0] * 2); // use higher resolution
47       _canvas->setIntValue("size[1]", view[1] * 2); // for antialias
48       _canvas->setIntValue("view[0]", view[0]);
49       _canvas->setIntValue("view[1]", view[1]);
50       _canvas->setBoolValue("render-always", true);
51       _canvas->setStringValue( "name",
52                                props->getStringValue("name", "gui-anonymous") );
53       SGPropertyNode* input = _canvas->getChild("input", 0, true);
54       _mouse_x = input->getChild("mouse-x", 0, true);
55       _mouse_y = input->getChild("mouse-y", 0, true);
56       _mouse_down = input->getChild("mouse-down", 0, true);
57       _mouse_drag = input->getChild("mouse-drag", 0, true);
58
59       SGPropertyNode *nasal = props->getNode("nasal");
60       if( !nasal )
61         break;
62
63       FGNasalSys *nas =
64         dynamic_cast<FGNasalSys*>(globals->get_subsystem("nasal"));
65       if( !nas )
66         SG_LOG( SG_GENERAL,
67                 SG_ALERT,
68                 "CanvasWidget: Failed to get nasal subsystem!" );
69
70       const std::string file = std::string("__canvas:")
71                              + _canvas->getStringValue("name");
72
73       SGPropertyNode *load = nasal->getNode("load");
74       if( load )
75       {
76         const char *s = load->getStringValue();
77         nas->handleCommand(module.c_str(), file.c_str(), s, _canvas);
78       }
79       break;
80     }
81   }
82 }
83
84 //------------------------------------------------------------------------------
85 CanvasWidget::~CanvasWidget()
86 {
87   if( _canvas )
88     _canvas->getParent()
89            ->removeChild(_canvas->getName(), _canvas->getIndex(), false);
90 }
91
92 //------------------------------------------------------------------------------
93 void CanvasWidget::doHit(int button, int updown, int x, int y)
94 {
95   puObject::doHit(button, updown, x, y);
96
97   // CTRL allows resizing and SHIFT allows moving the window
98   if( fgGetKeyModifiers() & (KEYMOD_CTRL | KEYMOD_SHIFT) )
99     return;
100
101   _mouse_x->setIntValue(x - abox.min[0]);
102   _mouse_y->setIntValue(abox.max[1] - y);
103
104   if( updown == PU_DRAG )
105     _mouse_drag->setIntValue(button);
106   else if( updown == PU_DOWN )
107     _mouse_down->setIntValue(button);
108
109   if( button != active_mouse_button )
110     return;
111
112   if (updown == PU_UP)
113     puDeactivateWidget();
114   else if (updown == PU_DOWN)
115     puSetActiveWidget(this, x, y);
116 }
117
118 //------------------------------------------------------------------------------
119 int CanvasWidget::checkKey(int key, int updown)
120 {
121   return puObject::checkKey(key, updown);
122 }
123
124 //------------------------------------------------------------------------------
125 void CanvasWidget::setSize(int w, int h)
126 {
127   puObject::setSize(w, h);
128
129   _canvas->setIntValue("view[0]", w);
130   _canvas->setIntValue("view[1]", h);
131 }
132
133 //------------------------------------------------------------------------------
134 void CanvasWidget::draw(int dx, int dy)
135 {
136   if( !_tex_id )
137   {
138     _tex_id = _canvas_mgr->getCanvasTexId(_canvas->getIndex());
139
140     // Normally we should be able to get the texture after one frame. I don't
141     // know if there are circumstances where it can take longer, so we don't
142     // log a warning message until we have tried a few times.
143     if( !_tex_id )
144     {
145       if( ++_no_tex_cnt == 5 )
146         SG_LOG(SG_GENERAL, SG_WARN, "CanvasWidget: failed to get texture!");
147       return;
148     }
149     else
150     {
151       if( _no_tex_cnt >= 5 )
152         SG_LOG
153         (
154           SG_GENERAL,
155           SG_INFO,
156           "CanvasWidget: got texture after " << _no_tex_cnt << " tries."
157         );
158       _no_tex_cnt = 0;
159     }
160   }
161
162   glEnable(GL_TEXTURE_2D);
163   glBindTexture(GL_TEXTURE_2D, _tex_id);
164   glBegin( GL_QUADS );
165     glColor3f(1,1,1);
166     glTexCoord2f(0,0); glVertex2f(dx + abox.min[0], dy + abox.min[1]);
167     glTexCoord2f(1,0); glVertex2f(dx + abox.max[0], dy + abox.min[1]);
168     glTexCoord2f(1,1); glVertex2f(dx + abox.max[0], dy + abox.max[1]);
169     glTexCoord2f(0,1); glVertex2f(dx + abox.min[0], dy + abox.max[1]);
170   glEnd();
171   glDisable(GL_TEXTURE_2D);
172 }