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