]> git.mxchange.org Git - flightgear.git/blob - src/Canvas/window.cxx
Canvas: Fully remove Window drawable if destroyed
[flightgear.git] / src / Canvas / window.cxx
1 // Window for placing a Canvas onto it (for dialogs, menus, etc.)
2 //
3 // Copyright (C) 2012  Thomas Geymayer <tomgey@gmail.com>
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License as
7 // published by the Free Software Foundation; either version 2 of the
8 // License, or (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful, but
11 // WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18
19 #include "window.hxx"
20 #include <Canvas/canvas.hxx>
21
22 #include <osg/BlendFunc>
23 #include <osg/Geometry>
24 #include <osg/Texture2D>
25 #include <osgGA/GUIEventHandler>
26
27 #include <boost/foreach.hpp>
28
29 /**
30  * Callback to enable/disable rendering of canvas displayed inside windows
31  */
32 class CullCallback:
33   public osg::Drawable::CullCallback
34 {
35   public:
36     CullCallback(Canvas::CameraCullCallback* camera_cull);
37
38   private:
39     Canvas::CameraCullCallback *_camera_cull;
40
41     virtual bool cull( osg::NodeVisitor* nv,
42                        osg::Drawable* drawable,
43                        osg::RenderInfo* renderInfo ) const;
44 };
45
46 //------------------------------------------------------------------------------
47 CullCallback::CullCallback(Canvas::CameraCullCallback* camera_cull):
48   _camera_cull( camera_cull )
49 {
50
51 }
52
53 //------------------------------------------------------------------------------
54 bool CullCallback::cull( osg::NodeVisitor* nv,
55                          osg::Drawable* drawable,
56                          osg::RenderInfo* renderInfo ) const
57 {
58   _camera_cull->enableRendering();
59   return false;
60 }
61
62 namespace canvas
63 {
64   //----------------------------------------------------------------------------
65   Window::Window(SGPropertyNode* node):
66     PropertyBasedElement(node),
67     _dirty(true),
68     _geometry( new osg::Geometry ),
69     _vertices( new osg::Vec3Array(4) ),
70     _tex_coords( new osg::Vec2Array(4) ),
71     _x(node, "x"),
72     _y(node, "y"),
73     _width(node, "size[0]"),
74     _height(node, "size[1]")
75   {
76     _x = 50;
77     _y = 100;
78     _width = 400;
79     _height = 300;
80
81     _geometry->setVertexArray(_vertices);
82     _geometry->setTexCoordArray(0,_tex_coords);
83
84     osg::Vec4Array* colors = new osg::Vec4Array(1);
85     (*colors)[0].set(1.0f,1.0f,1.0,1.0f);
86     _geometry->setColorArray(colors);
87     _geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
88
89     _geometry->addPrimitiveSet(
90       new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4)
91     );
92     _geometry->setDataVariance(osg::Object::DYNAMIC);
93
94     osg::StateSet* stateSet = _geometry->getOrCreateStateSet();
95     stateSet->setRenderBinDetails(1000, "RenderBin");
96
97     // speed optimization?
98     stateSet->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
99     stateSet->setAttribute(new osg::BlendFunc(
100       osg::BlendFunc::SRC_ALPHA,
101       osg::BlendFunc::ONE_MINUS_SRC_ALPHA)
102     );
103     stateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
104     stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
105     stateSet->setMode(GL_FOG, osg::StateAttribute::OFF);
106     stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
107     stateSet->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON);
108   }
109
110   //----------------------------------------------------------------------------
111   Window::~Window()
112   {
113     BOOST_FOREACH(osg::Node* parent, _geometry->getParents())
114     {
115       osg::Geode* geode = dynamic_cast<osg::Geode*>(parent);
116       if( geode )
117         geode->removeDrawable(_geometry);
118     }
119   }
120
121   //----------------------------------------------------------------------------
122   void Window::update(double delta_time_sec)
123   {
124     if( !_dirty )
125       return;
126     _dirty = false;
127
128     _region.set(_x, _y, _width, _height);
129
130     int z = 0; // TODO do we need to use z for depth ordering?
131
132     (*_vertices)[0].set(_region.l(), _region.t(), z);
133     (*_vertices)[1].set(_region.r(), _region.t(), z);
134     (*_vertices)[2].set(_region.r(), _region.b(), z);
135     (*_vertices)[3].set(_region.l(), _region.b(), z);
136
137     float l = 0, t = 1, b = 0, r = 1;
138     (*_tex_coords)[0].set(l,t);
139     (*_tex_coords)[1].set(r,t);
140     (*_tex_coords)[2].set(r,b);
141     (*_tex_coords)[3].set(l,b);
142
143     _geometry->dirtyDisplayList();
144   }
145
146   //----------------------------------------------------------------------------
147   void Window::valueChanged (SGPropertyNode * node)
148   {
149     if( node->getParent() != _node )
150       return;
151
152     const std::string& name = node->getNameString();
153     if(    name == "x" || name == "y" || name == "size" )
154       _dirty = true;
155   }
156
157   //----------------------------------------------------------------------------
158   void Window::setCanvas(CanvasPtr canvas)
159   {
160     _canvas = canvas;
161     _geometry->getOrCreateStateSet()
162              ->setTextureAttribute(0, canvas ? canvas->getTexture() : 0);
163     _geometry->dirtyDisplayList();
164     _geometry->setCullCallback(
165       canvas ? new CullCallback(canvas->getCameraCullCallback()) : 0
166     );
167   }
168
169   //----------------------------------------------------------------------------
170   CanvasWeakPtr Window::getCanvas() const
171   {
172     return _canvas;
173   }
174
175   //----------------------------------------------------------------------------
176   bool Window::handleMouseEvent(const MouseEvent& event)
177   {
178     if( !_canvas.expired() )
179       return _canvas.lock()->handleMouseEvent(event);
180     else
181       return false;
182   }
183
184 } // namespace canvas