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