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/SGBinding.hxx> 33 #include <simgear/math/interpolater.hxx> 34 #include <simgear/timing/timestamp.hxx> 35 36 #include <cmath> 37 #include <vector> 38 #include <map> 39 40 #include <Main/fg_props.hxx> 41 42 class FGPanelInstrument; 43 class fntFont; 44 class DCLGPS; 45 class IntRect; 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 setPath(const std::string & path)83 virtual void setPath (const std::string &path) { _path = path; } 84 getPath() const85 virtual const std::string &getPath () const { return _path; } 86 87 virtual osg::StateSet* getTexture (); 88 setCrop(float minX,float minY,float maxX,float maxY)89 virtual void setCrop (float minX, float minY, float maxX, float maxY) { 90 _minX = minX; _minY = minY; _maxX = maxX; _maxY = maxY; 91 } 92 getMinX() const93 virtual float getMinX () const { return _minX; } getMinY() const94 virtual float getMinY () const { return _minY; } getMaxX() const95 virtual float getMaxX () const { return _maxX; } getMaxY() const96 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 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 SGReferenced 121 { 122 public: 123 124 FGPanel (); 125 virtual ~FGPanel (); 126 127 virtual void draw (osg::State& state); 128 129 virtual void updateMouseDelay(double dt); 130 131 // transfer pointer ownership!!! 132 virtual void addInstrument (FGPanelInstrument * instrument); 133 134 // Background texture. 135 virtual void setBackground (osg::Texture2D* texture); 136 137 // Background multiple textures. 138 virtual void setMultiBackground (osg::Texture2D* texture, int idx); 139 setWidth(int width)140 virtual void setWidth (int width) { _width = width; } getWidth() const141 virtual int getWidth () const { return _width; } 142 143 // Full height of panel. setHeight(int height)144 virtual void setHeight (int height) { _height = height; } getHeight() const145 virtual int getHeight () const { return _height; } 146 147 // X-offset 148 virtual void setXOffset (int offset); getXOffset() const149 virtual int getXOffset () const { return _x_offset->getIntValue(); } 150 151 // Y-offset. 152 virtual void setYOffset (int offset); getYOffset() const153 virtual int getYOffset () const { return _y_offset->getIntValue(); } 154 155 // View height. 156 // virtual void setViewHeight (int height) { _view_height = height; } 157 // virtual int getViewHeight () const { return _view_height; } 158 159 /** 160 * find the actual logical extend of the panel, including all instruments 161 * and actions. 162 */ 163 void getLogicalExtent(int &x0, int& y0, int& x1, int &y1); 164 165 // Handle a mouse click. 166 virtual bool doMouseAction (int button, int updown, int x, int y); 167 virtual bool doLocalMouseAction(int button, int updown, int x, int y); 168 169 virtual void setDepthTest (bool enable); 170 getAutohide(void) const171 bool getAutohide(void) const { return _autohide; }; setAutohide(bool enable)172 void setAutohide(bool enable) { _autohide = enable; }; 173 174 double getAspectScale() const; 175 176 private: 177 void setupVirtualCockpit(); 178 void cleanupVirtualCockpit(); 179 180 mutable bool _mouseDown; 181 mutable int _mouseButton, _mouseX, _mouseY; 182 double _mouseActionRepeat; 183 184 mutable FGPanelInstrument * _mouseInstrument; 185 typedef std::vector<FGPanelInstrument *> instrument_list_type; 186 int _width; 187 int _height; 188 // int _view_height; 189 190 SGPropertyNode_ptr _x_offset; 191 SGPropertyNode_ptr _y_offset; 192 SGPropertyNode_ptr _jitter; 193 SGPropertyNode_ptr _flipx; 194 195 SGConstPropertyNode_ptr _xsize_node; 196 SGConstPropertyNode_ptr _ysize_node; 197 198 osg::ref_ptr<osg::StateSet> _bg; 199 osg::ref_ptr<osg::StateSet> _mbg[8]; 200 // List of instruments in panel. 201 instrument_list_type _instruments; 202 bool _enable_depth_test; 203 bool _autohide; 204 205 SGPropObjBool _drawPanelHotspots; 206 }; 207 208 209 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. getButton() const230 virtual int getButton () const { return _button; } getX() const231 virtual int getX () const { return _x; } getY() const232 virtual int getY () const { return _y; } getWidth() const233 virtual int getWidth () const { return _w; } getHeight() const234 virtual int getHeight () const { return _h; } 235 236 // Setters. 237 238 // transfer pointer ownership 239 virtual void addBinding (SGBinding * binding, int updown); setButton(int button)240 virtual void setButton (int button) { _button = button; } setX(int x)241 virtual void setX (int x) { _x = x; } setY(int y)242 virtual void setY (int y) { _y = y; } setWidth(int w)243 virtual void setWidth (int w) { _w = w; } setHeight(int h)244 virtual void setHeight (int h) { _h = h; } 245 246 // Check whether we're in the area. inArea(int button,int x,int y)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 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 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 getWidth() const331 virtual int getWidth () const { return _w; } getHeight() const332 virtual int getHeight () const { return _h; } setWidth(int w)333 virtual void setWidth (int w) { _w = w; } setHeight(int h)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 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 void extendRect(IntRect& r) const; 389 protected: 390 int _x, _y, _w, _h; 391 typedef std::vector<FGPanelAction *> action_list_type; 392 action_list_type _actions; 393 }; 394 395 396 /** 397 * An instrument constructed of multiple layers. 398 * 399 * Each individual layer can be rotated or shifted to correspond 400 * to internal FGFS instrument readings. 401 */ 402 class FGLayeredInstrument : public FGPanelInstrument 403 { 404 public: 405 FGLayeredInstrument (int x, int y, int w, int h); 406 virtual ~FGLayeredInstrument (); 407 408 virtual void draw (osg::State& state); 409 410 // Transfer pointer ownership!! 411 virtual int addLayer (FGInstrumentLayer *layer); 412 virtual int addLayer (const FGCroppedTexture &texture, int w = -1, int h = -1); 413 414 // Transfer pointer ownership!! 415 virtual void addTransformation (FGPanelTransformation * transformation); 416 417 protected: 418 typedef std::vector<FGInstrumentLayer *> layer_list; 419 layer_list _layers; 420 }; 421 422 423 /** 424 * An empty-shell instrument that exists soley in 425 * order to redirect commands from the panel to a 426 * complex instrument inherited from SGSubsystem. 427 * 428 * Currently the only complex instrument is the KLN89, 429 * which we've hardwired this to for now. 430 */ 431 class FGSpecialInstrument : public FGPanelInstrument 432 { 433 public: 434 FGSpecialInstrument(DCLGPS* sb); 435 //FGSpecialInstrument (int x, int y, int w, int h); 436 virtual ~FGSpecialInstrument (); 437 438 virtual void draw (osg::State& state); 439 440 protected: 441 DCLGPS* complex; 442 }; 443 444 445 /** 446 * An instrument layer containing a group of sublayers. 447 * 448 * This class is useful for gathering together a group of related 449 * layers, either to hold in an external file or to work under 450 * the same condition. 451 */ 452 class FGGroupLayer : public FGInstrumentLayer 453 { 454 public: 455 FGGroupLayer (); 456 virtual ~FGGroupLayer (); 457 virtual void draw (osg::State& state); 458 // transfer pointer ownership 459 virtual void addLayer (FGInstrumentLayer * layer); 460 protected: 461 std::vector<FGInstrumentLayer *> _layers; 462 }; 463 464 465 /** 466 * A textured layer of an instrument. 467 * 468 * This is a layer holding a single texture. Normally, the texture's 469 * backgound should be transparent so that lower layers and the panel 470 * background can show through. 471 */ 472 class FGTexturedLayer : public FGInstrumentLayer 473 { 474 public: FGTexturedLayer(int w=-1,int h=-1)475 FGTexturedLayer (int w = -1, int h = -1) : FGInstrumentLayer(w, h) {} 476 FGTexturedLayer (const FGCroppedTexture &texture, int w = -1, int h = -1); 477 virtual ~FGTexturedLayer (); 478 479 virtual void draw (osg::State& state); 480 setTexture(const FGCroppedTexture & texture)481 virtual void setTexture (const FGCroppedTexture &texture) { 482 _texture = texture; 483 } getTexture() const484 virtual const FGCroppedTexture &getTexture () const { return _texture; } getTexture()485 virtual FGCroppedTexture *getTexture() { return &_texture; } 486 setEmissive(bool e)487 void setEmissive(bool e) { _emissive = e; } 488 489 private: 490 FGCroppedTexture _texture; 491 bool _emissive; 492 }; 493 494 495 /** 496 * A text layer of an instrument. 497 * 498 * This is a layer holding a string of static and/or generated text. 499 * It is useful for instruments that have text displays, such as 500 * a chronometer, GPS, or NavCom radio. 501 */ 502 class FGTextLayer : public FGInstrumentLayer 503 { 504 public: 505 enum ChunkType { 506 TEXT, 507 TEXT_VALUE, 508 DOUBLE_VALUE 509 }; 510 511 class Chunk : public SGConditional 512 { 513 public: 514 Chunk (const std::string &text, const std::string &fmt = "%s"); 515 Chunk (ChunkType type, const SGPropertyNode * node, 516 const std::string &fmt = "", float mult = 1.0, float offs = 0.0, 517 bool truncation = false); 518 519 const char * getValue () const; 520 private: 521 ChunkType _type; 522 std::string _text; 523 SGConstPropertyNode_ptr _node; 524 std::string _fmt; 525 float _mult; 526 float _offs; 527 bool _trunc; 528 mutable char _buf[1024]; 529 }; 530 531 FGTextLayer (int w = -1, int h = -1); 532 virtual ~FGTextLayer (); 533 534 virtual void draw (osg::State& state); 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 setFontName ( const std::string &name ); 541 virtual void setFont (fntFont * font); 542 543 private: 544 545 void recalc_value () const; 546 547 typedef std::vector<Chunk *> chunk_list; 548 chunk_list _chunks; 549 float _color[4]; 550 551 float _pointSize; 552 mutable std::string _font_name; 553 mutable std::string _value; 554 mutable SGTimeStamp _then; 555 mutable SGTimeStamp _now; 556 }; 557 558 559 /** 560 * A group layer that switches among its children. 561 * 562 * The first layer that passes its condition will be drawn, and 563 * any following layers will be ignored. 564 */ 565 class FGSwitchLayer : public FGGroupLayer 566 { 567 public: 568 // Transfer pointers!! 569 FGSwitchLayer (); 570 virtual void draw (osg::State& state); 571 572 }; 573 #endif // __PANEL_HXX 574 575 // end of panel.hxx 576 577 578 579