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