]> git.mxchange.org Git - flightgear.git/blob - src/Cockpit/panel.hxx
#738: crash when switching 2D panels
[flightgear.git] / src / Cockpit / panel.hxx
1 //  panel.hxx - generic support classes for a 2D panel.
2 //
3 //  Written by David Megginson, started January 2000.
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 //  $Id$
20
21 #ifndef __PANEL_HXX
22 #define __PANEL_HXX
23
24 #include <osg/ref_ptr>
25 #include <osg/StateSet>
26 #include <osg/Texture2D>
27
28 #include <simgear/compiler.h>
29 #include <simgear/props/props.hxx>
30 #include <simgear/props/propertyObject.hxx>
31
32 #include <simgear/structure/subsystem_mgr.hxx>
33 #include <simgear/structure/SGBinding.hxx>
34 #include <simgear/math/interpolater.hxx>
35 #include <simgear/timing/timestamp.hxx>
36
37 #include <cmath>
38 #include <vector>
39 #include <map>
40
41 #include <Main/fg_props.hxx>
42
43 class FGPanelInstrument;
44 class fntFont;
45 class DCLGPS;
46 class IntRect;
47
48 ////////////////////////////////////////////////////////////////////////
49 // Texture management.
50 ////////////////////////////////////////////////////////////////////////
51
52
53 /**
54  * Texture manager (should migrate out into FGFS).
55  *
56  * This class ensures that no texture is loaded more than once.
57  */
58 class FGTextureManager
59 {
60 public:
61   static osg::Texture2D* createTexture(const std::string &relativePath,
62                                        bool staticTexture = true);
63   static void addTexture(const std::string &relativePath, osg::Texture2D* texture);
64 private:
65   static std::map<std::string,osg::ref_ptr<osg::Texture2D> > _textureMap;
66 };
67
68
69 /**
70  * Cropped texture (should migrate out into FGFS).
71  *
72  * This structure wraps an SSG texture with cropping information.
73  */
74 class FGCroppedTexture
75 {
76 public:
77
78   FGCroppedTexture ();
79   FGCroppedTexture (const std::string &path,
80                   float _minX = 0.0, float _minY = 0.0,
81                   float _maxX = 1.0, float _maxY = 1.0);
82   virtual ~FGCroppedTexture ();
83
84   virtual void setPath (const std::string &path) { _path = path; }
85
86   virtual const std::string &getPath () const { return _path; }
87
88   virtual osg::StateSet* getTexture ();
89
90   virtual void setCrop (float minX, float minY, float maxX, float maxY) {
91     _minX = minX; _minY = minY; _maxX = maxX; _maxY = maxY;
92   }
93
94   virtual float getMinX () const { return _minX; }
95   virtual float getMinY () const { return _minY; }
96   virtual float getMaxX () const { return _maxX; }
97   virtual float getMaxY () const { return _maxY; }
98
99
100 private:
101   std::string _path;
102   osg::ref_ptr<osg::StateSet> _texture;
103   float _minX, _minY, _maxX, _maxY;
104 };
105
106
107 \f
108 ////////////////////////////////////////////////////////////////////////
109 // Top-level panel.
110 ////////////////////////////////////////////////////////////////////////
111
112
113 /**
114  * Instrument panel class.
115  *
116  * The panel is a container that has a background texture and holds
117  * zero or more instruments.  The panel will order the instruments to
118  * redraw themselves when necessary, and will pass mouse clicks on to
119  * the appropriate instruments for processing.
120  */
121 class FGPanel : public SGSubsystem
122 {
123 public:
124
125   FGPanel ();
126   virtual ~FGPanel ();
127
128                                 // Update the panel (every frame).
129   virtual void init ();
130   virtual void bind ();
131   virtual void unbind ();
132   virtual void draw (osg::State& state);
133   virtual void update (double);
134  
135   //void update (osg::State& state);
136   //virtual void update (osg::State& state, GLfloat winx, GLfloat winw, GLfloat winy, GLfloat winh);
137
138   virtual void updateMouseDelay();
139
140                                 // transfer pointer ownership!!!
141   virtual void addInstrument (FGPanelInstrument * instrument);
142
143                                 // Background texture.
144   virtual void setBackground (osg::Texture2D* texture);
145
146                                 // Background multiple textures.
147   virtual void setMultiBackground (osg::Texture2D* texture, int idx);
148
149                                 // Make the panel visible or invisible.
150   virtual bool getVisibility () const;
151   virtual void setVisibility (bool visibility);
152
153                                 // Full width of panel.
154   virtual void setWidth (int width) { _width = width; }
155   virtual int getWidth () const { return _width; }
156
157                                 // Full height of panel.
158   virtual void setHeight (int height) { _height = height; }
159   virtual int getHeight () const { return _height; }
160
161                                 // X-offset
162   virtual void setXOffset (int offset);
163   virtual int getXOffset () const { return _x_offset->getIntValue(); }
164
165                                 // Y-offset.
166   virtual void setYOffset (int offset);
167   virtual int getYOffset () const { return _y_offset->getIntValue(); }
168
169                                 // View height.
170  // virtual void setViewHeight (int height) { _view_height = height; }
171  // virtual int getViewHeight () const { return _view_height; }
172
173   /**
174    * find the actual logical extend of the panel, including all instruments
175    * and actions.
176    */
177   void getLogicalExtent(int &x0, int& y0, int& x1, int &y1);
178   
179                                 // Handle a mouse click.
180   virtual bool doMouseAction (int button, int updown, int x, int y);
181   virtual bool doLocalMouseAction(int button, int updown, int x, int y);
182
183   virtual void setDepthTest (bool enable);
184
185   bool getAutohide(void) const { return _autohide; };
186   void setAutohide(bool enable) { _autohide = enable; };
187   
188   double getAspectScale() const;
189
190 private:
191   void setupVirtualCockpit();
192   void cleanupVirtualCockpit();
193
194   mutable bool _mouseDown;
195   mutable int _mouseButton, _mouseX, _mouseY;
196   mutable int _mouseDelay;
197   mutable FGPanelInstrument * _mouseInstrument;
198   typedef std::vector<FGPanelInstrument *> instrument_list_type;
199   int _width;
200   int _height;
201  // int _view_height;
202
203   SGPropertyNode_ptr _visibility;
204   SGPropertyNode_ptr _x_offset;
205   SGPropertyNode_ptr _y_offset;
206   SGPropertyNode_ptr _jitter;
207   SGPropertyNode_ptr _flipx;
208
209   SGConstPropertyNode_ptr _xsize_node;
210   SGConstPropertyNode_ptr _ysize_node;
211   
212   osg::ref_ptr<osg::StateSet> _bg;
213   osg::ref_ptr<osg::StateSet> _mbg[8];
214                                 // List of instruments in panel.
215   instrument_list_type _instruments;
216   bool _enable_depth_test;
217   bool _autohide;
218   
219   SGPropObjBool _drawPanelHotspots;
220 };
221
222
223 \f
224 ////////////////////////////////////////////////////////////////////////
225 // Actions
226 ////////////////////////////////////////////////////////////////////////
227
228
229 /**
230  * Class for user actions.
231  *
232  * The actions are command bindings, like bindings for the keyboard
233  * or joystick, but they are tied to specific mouse actions in
234  * rectangular areas of the panel.
235  */
236 class FGPanelAction : public SGConditional
237 {
238 public:
239   FGPanelAction ();
240   FGPanelAction (int button, int x, int y, int w, int h, bool repeatable);
241   virtual ~FGPanelAction ();
242
243                                 // Getters.
244   virtual int getButton () const { return _button; }
245   virtual int getX () const { return _x; }
246   virtual int getY () const { return _y; }
247   virtual int getWidth () const { return _w; }
248   virtual int getHeight () const { return _h; }
249
250                                 // Setters.
251
252                                 // transfer pointer ownership
253   virtual void addBinding (SGBinding * binding, int updown);
254   virtual void setButton (int button) { _button = button; }
255   virtual void setX (int x) { _x = x; }
256   virtual void setY (int y) { _y = y; }
257   virtual void setWidth (int w) { _w = w; }
258   virtual void setHeight (int h) { _h = h; }
259
260                                 // Check whether we're in the area.
261   virtual bool inArea (int button, int x, int y)
262   {
263     return (button == _button &&
264             x >= _x &&
265             x < _x + _w &&
266             y >= _y &&
267             y < _y + _h);
268   }
269
270                                 // Perform the action.
271   virtual bool doAction (int updown);
272
273 private:
274   typedef std::vector<SGBinding *> binding_list_t;
275
276   int _button;
277   int _x;
278   int _y;
279   int _w;
280   int _h;
281   bool _repeatable;
282   int _last_state;
283   binding_list_t _bindings[2];
284 };
285
286
287 \f
288 ////////////////////////////////////////////////////////////////////////
289 // Transformations.
290 ////////////////////////////////////////////////////////////////////////
291
292
293 /**
294  * A transformation for a layer.
295  */
296 class FGPanelTransformation : public SGConditional
297 {
298 public:
299
300   enum Type {
301     XSHIFT,
302     YSHIFT,
303     ROTATION
304   };
305
306   FGPanelTransformation ();
307   virtual ~FGPanelTransformation ();
308
309   Type type;
310   SGConstPropertyNode_ptr node;
311   float min;
312   float max;
313   bool has_mod;
314   float mod;
315   float factor;
316   float offset;
317   SGInterpTable * table;
318 };
319
320
321
322 \f
323 ////////////////////////////////////////////////////////////////////////
324 // Layers
325 ////////////////////////////////////////////////////////////////////////
326
327
328 /**
329  * A single layer of a multi-layered instrument.
330  *
331  * Each layer can be subject to a series of transformations based
332  * on current FGFS instrument readings: for example, a texture
333  * representing a needle can rotate to show the airspeed.
334  */
335 class FGInstrumentLayer : public SGConditional
336 {
337 public:
338
339   FGInstrumentLayer (int w = -1, int h = -1);
340   virtual ~FGInstrumentLayer ();
341
342   virtual void draw (osg::State& state) = 0;
343   virtual void transform () const;
344
345   virtual int getWidth () const { return _w; }
346   virtual int getHeight () const { return _h; }
347   virtual void setWidth (int w) { _w = w; }
348   virtual void setHeight (int h) { _h = h; }
349
350                                 // Transfer pointer ownership!!
351                                 // DEPRECATED
352   virtual void addTransformation (FGPanelTransformation * transformation);
353
354 protected:
355   int _w, _h;
356
357   typedef std::vector<FGPanelTransformation *> transformation_list;
358   transformation_list _transformations;
359 };
360
361
362 \f
363 ////////////////////////////////////////////////////////////////////////
364 // Instruments.
365 ////////////////////////////////////////////////////////////////////////
366
367
368 /**
369  * Abstract base class for a panel instrument.
370  *
371  * A panel instrument consists of zero or more actions, associated
372  * with mouse clicks in rectangular areas.  Currently, the only
373  * concrete class derived from this is FGLayeredInstrument, but others
374  * may show up in the future (some complex instruments could be 
375  * entirely hand-coded, for example).
376  */
377 class FGPanelInstrument : public SGConditional
378 {
379 public:
380   FGPanelInstrument ();
381   FGPanelInstrument (int x, int y, int w, int h);
382   virtual ~FGPanelInstrument ();
383
384   virtual void draw (osg::State& state) = 0;
385   virtual void drawHotspots(osg::State& state);
386
387   virtual void setPosition(int x, int y);
388   virtual void setSize(int w, int h);
389
390   virtual int getXPos () const;
391   virtual int getYPos () const;
392   virtual int getWidth () const;
393   virtual int getHeight () const;
394
395                                 // Coordinates relative to centre.
396                                 // Transfer pointer ownership!!
397   virtual void addAction (FGPanelAction * action);
398
399                                 // Coordinates relative to centre.
400   virtual bool doMouseAction (int button, int updown, int x, int y);
401
402   void extendRect(IntRect& r) const;
403 protected:
404   int _x, _y, _w, _h;
405   typedef std::vector<FGPanelAction *> action_list_type;
406   action_list_type _actions;
407 };
408
409
410 /**
411  * An instrument constructed of multiple layers.
412  *
413  * Each individual layer can be rotated or shifted to correspond
414  * to internal FGFS instrument readings.
415  */
416 class FGLayeredInstrument : public FGPanelInstrument
417 {
418 public:
419   FGLayeredInstrument (int x, int y, int w, int h);
420   virtual ~FGLayeredInstrument ();
421
422   virtual void draw (osg::State& state);
423
424                                 // Transfer pointer ownership!!
425   virtual int addLayer (FGInstrumentLayer *layer);
426   virtual int addLayer (const FGCroppedTexture &texture, int w = -1, int h = -1);
427
428                                 // Transfer pointer ownership!!
429   virtual void addTransformation (FGPanelTransformation * transformation);
430
431 protected:
432   typedef std::vector<FGInstrumentLayer *> layer_list;
433   layer_list _layers;
434 };
435
436
437 /**
438  * An empty-shell instrument that exists soley in
439  * order to redirect commands from the panel to a
440  * complex instrument inherited from SGSubsystem.
441  *
442  * Currently the only complex instrument is the KLN89,
443  * which we've hardwired this to for now.
444  */
445 class FGSpecialInstrument : public FGPanelInstrument
446 {
447 public:
448   FGSpecialInstrument(DCLGPS* sb);
449   //FGSpecialInstrument (int x, int y, int w, int h);
450   virtual ~FGSpecialInstrument ();
451
452   virtual void draw (osg::State& state);
453   
454 protected:
455   DCLGPS* complex;
456 };
457
458
459 /**
460  * An instrument layer containing a group of sublayers.
461  *
462  * This class is useful for gathering together a group of related
463  * layers, either to hold in an external file or to work under
464  * the same condition.
465  */
466 class FGGroupLayer : public FGInstrumentLayer
467 {
468 public:
469   FGGroupLayer ();
470   virtual ~FGGroupLayer ();
471   virtual void draw (osg::State& state);
472                                 // transfer pointer ownership
473   virtual void addLayer (FGInstrumentLayer * layer);
474 protected:
475   std::vector<FGInstrumentLayer *> _layers;
476 };
477
478
479 /**
480  * A textured layer of an instrument.
481  *
482  * This is a layer holding a single texture.  Normally, the texture's
483  * backgound should be transparent so that lower layers and the panel
484  * background can show through.
485  */
486 class FGTexturedLayer : public FGInstrumentLayer
487 {
488 public:
489   FGTexturedLayer (int w = -1, int h = -1) : FGInstrumentLayer(w, h) {}
490   FGTexturedLayer (const FGCroppedTexture &texture, int w = -1, int h = -1);
491   virtual ~FGTexturedLayer ();
492
493   virtual void draw (osg::State& state);
494
495   virtual void setTexture (const FGCroppedTexture &texture) {
496     _texture = texture;
497   }
498   virtual const FGCroppedTexture &getTexture () const { return _texture; }
499   virtual FGCroppedTexture *getTexture() { return &_texture; }
500
501   void setEmissive(bool e) { _emissive = e; }
502
503 private:
504   FGCroppedTexture _texture;
505   bool _emissive;
506 };
507
508
509 /**
510  * A text layer of an instrument.
511  *
512  * This is a layer holding a string of static and/or generated text.
513  * It is useful for instruments that have text displays, such as
514  * a chronometer, GPS, or NavCom radio.
515  */
516 class FGTextLayer : public FGInstrumentLayer
517 {
518 public:
519   enum ChunkType {
520     TEXT,
521     TEXT_VALUE,
522     DOUBLE_VALUE
523   };
524
525   class Chunk : public SGConditional
526   {
527   public:
528     Chunk (const std::string &text, const std::string &fmt = "%s");
529     Chunk (ChunkType type, const SGPropertyNode * node,
530            const std::string &fmt = "", float mult = 1.0, float offs = 0.0,
531            bool truncation = false);
532
533     const char * getValue () const;
534   private:
535     ChunkType _type;
536     std::string _text;
537     SGConstPropertyNode_ptr _node;
538     std::string _fmt;
539     float _mult;
540     float _offs;
541     bool _trunc;
542     mutable char _buf[1024];
543   };
544
545   FGTextLayer (int w = -1, int h = -1);
546   virtual ~FGTextLayer ();
547
548   virtual void draw (osg::State& state);
549
550                                 // Transfer pointer!!
551   virtual void addChunk (Chunk * chunk);
552   virtual void setColor (float r, float g, float b);
553   virtual void setPointSize (float size);
554   virtual void setFontName ( const std::string &name );
555   virtual void setFont (fntFont * font);
556
557 private:
558
559   void recalc_value () const;
560
561   typedef std::vector<Chunk *> chunk_list;
562   chunk_list _chunks;
563   float _color[4];
564
565   float _pointSize;
566   mutable std::string _font_name;
567   mutable std::string _value;
568   mutable SGTimeStamp _then;
569   mutable SGTimeStamp _now;
570 };
571
572
573 /**
574  * A group layer that switches among its children.
575  *
576  * The first layer that passes its condition will be drawn, and
577  * any following layers will be ignored.
578  */
579 class FGSwitchLayer : public FGGroupLayer
580 {
581 public:
582                                 // Transfer pointers!!
583   FGSwitchLayer ();
584   virtual void draw (osg::State& state);
585
586 };
587
588
589
590 \f
591 ////////////////////////////////////////////////////////////////////////
592 // Functions.
593 ////////////////////////////////////////////////////////////////////////
594
595 /**
596  * Test whether the panel should be visible.
597  */
598 bool fgPanelVisible ();
599
600
601 \f
602 #endif // __PANEL_HXX
603
604 // end of panel.hxx
605
606
607