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