| 1 | /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2008 Robert Osfield |
|---|
| 2 | * |
|---|
| 3 | * This library is open source and may be redistributed and/or modified under |
|---|
| 4 | * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or |
|---|
| 5 | * (at your option) any later version. The full license is in LICENSE file |
|---|
| 6 | * included with this distribution, and on the openscenegraph.org website. |
|---|
| 7 | * |
|---|
| 8 | * This library is distributed in the hope that it will be useful, |
|---|
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 11 | * OpenSceneGraph Public License for more details. |
|---|
| 12 | */ |
|---|
| 13 | |
|---|
| 14 | // Code by: Jeremy Moles (cubicool) 2007-2008 |
|---|
| 15 | |
|---|
| 16 | #ifndef OSGWIDGET_FRAME |
|---|
| 17 | #define OSGWIDGET_FRAME |
|---|
| 18 | |
|---|
| 19 | #include <osgWidget/Table> |
|---|
| 20 | |
|---|
| 21 | namespace osgWidget { |
|---|
| 22 | |
|---|
| 23 | /* |
|---|
| 24 | Lets take a moment and explain how Frame texturing works. When you create a Frame, you use |
|---|
| 25 | a specially designed texture that is "chopped" up horizontally by the Frame code into 8 equal |
|---|
| 26 | regions. Each region is then textured to a corresponding portion of the Frame, in the |
|---|
| 27 | following order: |
|---|
| 28 | |
|---|
| 29 | +---+---+---+---+---+---+---+---+ |
|---|
| 30 | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | |
|---|
| 31 | +---+---+---+---+---+---+---+---+ |
|---|
| 32 | |
|---|
| 33 | 1. Upper-Left corner. |
|---|
| 34 | 2. Top border (rotated 90 degrees CCW). |
|---|
| 35 | 3. Upper-Right corner. |
|---|
| 36 | 4. Left border. |
|---|
| 37 | 5. Right border. |
|---|
| 38 | 6. Bottom-Left corner. |
|---|
| 39 | 7. Bottom border (rotated 90 degrees CCW). |
|---|
| 40 | 8. Bottom-Right corner. |
|---|
| 41 | |
|---|
| 42 | Now, these should be pretty self-explanatory if you visualize a frame as a 3x3 "table" |
|---|
| 43 | (which is exactly what it is), but note how regions 2 and 7 are rotated counter-clockwise. |
|---|
| 44 | We do this for a VERY important reason: we want to enable texture repeat on the border |
|---|
| 45 | regions, so that when the frame is resized the borders cleanly paint the texture over |
|---|
| 46 | the entire are (and don't stretch it). However, it is impossible in OpenGL to repeat a |
|---|
| 47 | sub-region of a texture without including either the vertical or horizontal bounds, so the |
|---|
| 48 | artist is required to rotate the region during their rendering so that our code can properly |
|---|
| 49 | rotate it back internally and have it repeat in the desired way. |
|---|
| 50 | |
|---|
| 51 | This method of texturing a Frame object is inspired by World of Warcraft "edge files", and it |
|---|
| 52 | is both efficient and easy-to-use--once you understand the basics. If you're still confused, |
|---|
| 53 | take a look at this URL, or any of the example themes: |
|---|
| 54 | |
|---|
| 55 | http://www.wowwiki.com/EdgeFiles |
|---|
| 56 | */ |
|---|
| 57 | |
|---|
| 58 | class OSGWIDGET_EXPORT Frame: public Table |
|---|
| 59 | { |
|---|
| 60 | public: |
|---|
| 61 | |
|---|
| 62 | enum CornerType |
|---|
| 63 | { |
|---|
| 64 | CORNER_LOWER_LEFT, |
|---|
| 65 | CORNER_LOWER_RIGHT, |
|---|
| 66 | CORNER_UPPER_LEFT, |
|---|
| 67 | CORNER_UPPER_RIGHT |
|---|
| 68 | }; |
|---|
| 69 | |
|---|
| 70 | enum BorderType |
|---|
| 71 | { |
|---|
| 72 | BORDER_LEFT, |
|---|
| 73 | BORDER_RIGHT, |
|---|
| 74 | BORDER_TOP, |
|---|
| 75 | BORDER_BOTTOM |
|---|
| 76 | }; |
|---|
| 77 | |
|---|
| 78 | enum FrameOptions |
|---|
| 79 | { |
|---|
| 80 | FRAME_RESIZE = 1, |
|---|
| 81 | FRAME_MOVE = 2, |
|---|
| 82 | FRAME_TEXTURE = 4, |
|---|
| 83 | FRAME_ALL = FRAME_RESIZE | FRAME_MOVE | FRAME_TEXTURE |
|---|
| 84 | }; |
|---|
| 85 | |
|---|
| 86 | static std::string cornerTypeToString (CornerType); |
|---|
| 87 | static std::string borderTypeToString (BorderType); |
|---|
| 88 | |
|---|
| 89 | class OSGWIDGET_EXPORT Corner: public Widget |
|---|
| 90 | { |
|---|
| 91 | public: |
|---|
| 92 | META_Object(osgWidget, Corner); |
|---|
| 93 | |
|---|
| 94 | Corner (CornerType = CORNER_LOWER_LEFT, point_type = 0.0f, point_type = 0.0f); |
|---|
| 95 | Corner (const Corner&, const osg::CopyOp&); |
|---|
| 96 | |
|---|
| 97 | virtual void parented (Window*); |
|---|
| 98 | virtual bool mouseDrag (double, double, const WindowManager*); |
|---|
| 99 | |
|---|
| 100 | CornerType getCornerType() const |
|---|
| 101 | { |
|---|
| 102 | return _corner; |
|---|
| 103 | } |
|---|
| 104 | |
|---|
| 105 | void setCornerType(CornerType corner) |
|---|
| 106 | { |
|---|
| 107 | _corner = corner; |
|---|
| 108 | } |
|---|
| 109 | |
|---|
| 110 | void setCornerTypeAndName(CornerType corner) |
|---|
| 111 | { |
|---|
| 112 | _corner = corner; |
|---|
| 113 | _name = cornerTypeToString(corner); |
|---|
| 114 | } |
|---|
| 115 | |
|---|
| 116 | protected: |
|---|
| 117 | |
|---|
| 118 | CornerType _corner; |
|---|
| 119 | }; |
|---|
| 120 | |
|---|
| 121 | class OSGWIDGET_EXPORT Border: public Widget |
|---|
| 122 | { |
|---|
| 123 | public: |
|---|
| 124 | META_Object(osgWidget, Border); |
|---|
| 125 | |
|---|
| 126 | Border (BorderType = BORDER_LEFT, point_type = 0.0f, point_type = 0.0f); |
|---|
| 127 | Border (const Border&, const osg::CopyOp&); |
|---|
| 128 | |
|---|
| 129 | virtual void parented (Window*); |
|---|
| 130 | virtual void positioned (); |
|---|
| 131 | virtual bool mouseDrag (double, double, const WindowManager*); |
|---|
| 132 | |
|---|
| 133 | BorderType getBorderType() const |
|---|
| 134 | { |
|---|
| 135 | return _border; |
|---|
| 136 | } |
|---|
| 137 | |
|---|
| 138 | void setBorderType(BorderType border) |
|---|
| 139 | { |
|---|
| 140 | _border = border; |
|---|
| 141 | } |
|---|
| 142 | |
|---|
| 143 | void setBorderTypeAndName(BorderType border) |
|---|
| 144 | { |
|---|
| 145 | _border = border; |
|---|
| 146 | _name = borderTypeToString(border); |
|---|
| 147 | } |
|---|
| 148 | |
|---|
| 149 | protected: |
|---|
| 150 | |
|---|
| 151 | BorderType _border; |
|---|
| 152 | }; |
|---|
| 153 | |
|---|
| 154 | META_Object(osgWidget, Frame); |
|---|
| 155 | |
|---|
| 156 | Frame (const std::string& = "", unsigned int = 0); |
|---|
| 157 | Frame (const Frame&, const osg::CopyOp&); |
|---|
| 158 | |
|---|
| 159 | static Frame* createSimpleFrame( |
|---|
| 160 | const std::string&, |
|---|
| 161 | point_type, |
|---|
| 162 | point_type, |
|---|
| 163 | point_type, |
|---|
| 164 | point_type, |
|---|
| 165 | unsigned int = 0, |
|---|
| 166 | Frame* = 0 |
|---|
| 167 | ); |
|---|
| 168 | |
|---|
| 169 | static Frame* createSimpleFrameWithSingleTexture( |
|---|
| 170 | const std::string&, |
|---|
| 171 | osg::Image*, |
|---|
| 172 | point_type, |
|---|
| 173 | point_type, |
|---|
| 174 | unsigned int = 0, |
|---|
| 175 | Frame* = 0 |
|---|
| 176 | ); |
|---|
| 177 | |
|---|
| 178 | static Frame* createSimpleFrameFromTheme( |
|---|
| 179 | const std::string&, |
|---|
| 180 | osg::Image*, |
|---|
| 181 | point_type, |
|---|
| 182 | point_type, |
|---|
| 183 | unsigned int = 0, |
|---|
| 184 | Frame* = 0 |
|---|
| 185 | ); |
|---|
| 186 | |
|---|
| 187 | void createSimpleFrame(point_type cw, point_type ch, point_type w, point_type h) |
|---|
| 188 | { |
|---|
| 189 | createSimpleFrame(_name, cw, ch, w, h, 0, this); |
|---|
| 190 | } |
|---|
| 191 | |
|---|
| 192 | void createSimpleFrameWithSingleTexture( |
|---|
| 193 | osg::Image* image, |
|---|
| 194 | point_type w, |
|---|
| 195 | point_type h |
|---|
| 196 | ) |
|---|
| 197 | { |
|---|
| 198 | createSimpleFrameWithSingleTexture(_name, image, w, h, 0, this); |
|---|
| 199 | } |
|---|
| 200 | |
|---|
| 201 | bool setWindow(Window*); |
|---|
| 202 | |
|---|
| 203 | EmbeddedWindow* getEmbeddedWindow() { return dynamic_cast<EmbeddedWindow*>(getByRowCol(1, 1)); } |
|---|
| 204 | |
|---|
| 205 | const EmbeddedWindow* getEmbeddedWindow() const { return dynamic_cast<const EmbeddedWindow*>(getByRowCol(1, 1)); } |
|---|
| 206 | |
|---|
| 207 | Corner* getCorner(CornerType c) { return dynamic_cast<Corner*>(_getCorner(c)); } |
|---|
| 208 | |
|---|
| 209 | const Corner* getCorner(CornerType c) const { return dynamic_cast<const Corner*>(_getCorner(c)); } |
|---|
| 210 | |
|---|
| 211 | Border* getBorder(BorderType b) { return dynamic_cast<Border*>(_getBorder(b)); } |
|---|
| 212 | |
|---|
| 213 | const Border* getBorder(BorderType b) const { return dynamic_cast<const Border*>(_getBorder(b)); } |
|---|
| 214 | |
|---|
| 215 | // This method resizes the internal EmbeddedWindow object and then properly resizes |
|---|
| 216 | // the reset of the Frame based on the sizes of the Corners, Borders, etc. |
|---|
| 217 | bool resizeFrame(point_type, point_type); |
|---|
| 218 | |
|---|
| 219 | unsigned int getFlags() const |
|---|
| 220 | { |
|---|
| 221 | return _flags; |
|---|
| 222 | } |
|---|
| 223 | |
|---|
| 224 | void setFlags(unsigned int flags) |
|---|
| 225 | { |
|---|
| 226 | _flags = flags; |
|---|
| 227 | } |
|---|
| 228 | |
|---|
| 229 | bool canResize() const |
|---|
| 230 | { |
|---|
| 231 | return (_flags & FRAME_RESIZE) != 0; |
|---|
| 232 | } |
|---|
| 233 | |
|---|
| 234 | bool canMove() const |
|---|
| 235 | { |
|---|
| 236 | return (_flags & FRAME_MOVE) != 0; |
|---|
| 237 | } |
|---|
| 238 | |
|---|
| 239 | bool canTexture() const |
|---|
| 240 | { |
|---|
| 241 | return (_flags & FRAME_TEXTURE) != 0; |
|---|
| 242 | } |
|---|
| 243 | |
|---|
| 244 | protected: |
|---|
| 245 | |
|---|
| 246 | Widget* _getCorner (CornerType) const; |
|---|
| 247 | Widget* _getBorder (BorderType) const; |
|---|
| 248 | |
|---|
| 249 | unsigned int _flags; |
|---|
| 250 | }; |
|---|
| 251 | |
|---|
| 252 | } |
|---|
| 253 | |
|---|
| 254 | #endif |
|---|