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