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