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