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