You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
254 lines
7.5 KiB
254 lines
7.5 KiB
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2008 Robert Osfield |
|
* |
|
* This library is open source and may be redistributed and/or modified under |
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or |
|
* (at your option) any later version. The full license is in LICENSE file |
|
* included with this distribution, and on the openscenegraph.org website. |
|
* |
|
* This library is distributed in the hope that it will be useful, |
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
* OpenSceneGraph Public License for more details. |
|
*/ |
|
|
|
// Code by: Jeremy Moles (cubicool) 2007-2008 |
|
|
|
#ifndef OSGWIDGET_FRAME |
|
#define OSGWIDGET_FRAME |
|
|
|
#include <osgWidget/Table> |
|
|
|
namespace osgWidget { |
|
|
|
/* |
|
Lets take a moment and explain how Frame texturing works. When you create a Frame, you use |
|
a specially designed texture that is "chopped" up horizontally by the Frame code into 8 equal |
|
regions. Each region is then textured to a corresponding portion of the Frame, in the |
|
following order: |
|
|
|
+---+---+---+---+---+---+---+---+ |
|
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | |
|
+---+---+---+---+---+---+---+---+ |
|
|
|
1. Upper-Left corner. |
|
2. Top border (rotated 90 degrees CCW). |
|
3. Upper-Right corner. |
|
4. Left border. |
|
5. Right border. |
|
6. Bottom-Left corner. |
|
7. Bottom border (rotated 90 degrees CCW). |
|
8. Bottom-Right corner. |
|
|
|
Now, these should be pretty self-explanatory if you visualize a frame as a 3x3 "table" |
|
(which is exactly what it is), but note how regions 2 and 7 are rotated counter-clockwise. |
|
We do this for a VERY important reason: we want to enable texture repeat on the border |
|
regions, so that when the frame is resized the borders cleanly paint the texture over |
|
the entire are (and don't stretch it). However, it is impossible in OpenGL to repeat a |
|
sub-region of a texture without including either the vertical or horizontal bounds, so the |
|
artist is required to rotate the region during their rendering so that our code can properly |
|
rotate it back internally and have it repeat in the desired way. |
|
|
|
This method of texturing a Frame object is inspired by World of Warcraft "edge files", and it |
|
is both efficient and easy-to-use--once you understand the basics. If you're still confused, |
|
take a look at this URL, or any of the example themes: |
|
|
|
http://www.wowwiki.com/EdgeFiles |
|
*/ |
|
|
|
class OSGWIDGET_EXPORT Frame: public Table |
|
{ |
|
public: |
|
|
|
enum CornerType |
|
{ |
|
CORNER_LOWER_LEFT, |
|
CORNER_LOWER_RIGHT, |
|
CORNER_UPPER_LEFT, |
|
CORNER_UPPER_RIGHT |
|
}; |
|
|
|
enum BorderType |
|
{ |
|
BORDER_LEFT, |
|
BORDER_RIGHT, |
|
BORDER_TOP, |
|
BORDER_BOTTOM |
|
}; |
|
|
|
enum FrameOptions |
|
{ |
|
FRAME_RESIZE = 1, |
|
FRAME_MOVE = 2, |
|
FRAME_TEXTURE = 4, |
|
FRAME_ALL = FRAME_RESIZE | FRAME_MOVE | FRAME_TEXTURE |
|
}; |
|
|
|
static std::string cornerTypeToString (CornerType); |
|
static std::string borderTypeToString (BorderType); |
|
|
|
class OSGWIDGET_EXPORT Corner: public Widget |
|
{ |
|
public: |
|
META_Object(osgWidget, Corner); |
|
|
|
Corner (CornerType = CORNER_LOWER_LEFT, point_type = 0.0f, point_type = 0.0f); |
|
Corner (const Corner&, const osg::CopyOp&); |
|
|
|
virtual void parented (Window*); |
|
virtual bool mouseDrag (double, double, const WindowManager*); |
|
|
|
CornerType getCornerType() const |
|
{ |
|
return _corner; |
|
} |
|
|
|
void setCornerType(CornerType corner) |
|
{ |
|
_corner = corner; |
|
} |
|
|
|
void setCornerTypeAndName(CornerType corner) |
|
{ |
|
_corner = corner; |
|
_name = cornerTypeToString(corner); |
|
} |
|
|
|
protected: |
|
|
|
CornerType _corner; |
|
}; |
|
|
|
class OSGWIDGET_EXPORT Border: public Widget |
|
{ |
|
public: |
|
META_Object(osgWidget, Border); |
|
|
|
Border (BorderType = BORDER_LEFT, point_type = 0.0f, point_type = 0.0f); |
|
Border (const Border&, const osg::CopyOp&); |
|
|
|
virtual void parented (Window*); |
|
virtual void positioned (); |
|
virtual bool mouseDrag (double, double, const WindowManager*); |
|
|
|
BorderType getBorderType() const |
|
{ |
|
return _border; |
|
} |
|
|
|
void setBorderType(BorderType border) |
|
{ |
|
_border = border; |
|
} |
|
|
|
void setBorderTypeAndName(BorderType border) |
|
{ |
|
_border = border; |
|
_name = borderTypeToString(border); |
|
} |
|
|
|
protected: |
|
|
|
BorderType _border; |
|
}; |
|
|
|
META_Object(osgWidget, Frame); |
|
|
|
Frame (const std::string& = "", unsigned int = 0); |
|
Frame (const Frame&, const osg::CopyOp&); |
|
|
|
static Frame* createSimpleFrame( |
|
const std::string&, |
|
point_type, |
|
point_type, |
|
point_type, |
|
point_type, |
|
unsigned int = 0, |
|
Frame* = 0 |
|
); |
|
|
|
static Frame* createSimpleFrameWithSingleTexture( |
|
const std::string&, |
|
osg::Image*, |
|
point_type, |
|
point_type, |
|
unsigned int = 0, |
|
Frame* = 0 |
|
); |
|
|
|
static Frame* createSimpleFrameFromTheme( |
|
const std::string&, |
|
osg::Image*, |
|
point_type, |
|
point_type, |
|
unsigned int = 0, |
|
Frame* = 0 |
|
); |
|
|
|
void createSimpleFrame(point_type cw, point_type ch, point_type w, point_type h) |
|
{ |
|
createSimpleFrame(_name, cw, ch, w, h, 0, this); |
|
} |
|
|
|
void createSimpleFrameWithSingleTexture( |
|
osg::Image* image, |
|
point_type w, |
|
point_type h |
|
) |
|
{ |
|
createSimpleFrameWithSingleTexture(_name, image, w, h, 0, this); |
|
} |
|
|
|
bool setWindow(Window*); |
|
|
|
EmbeddedWindow* getEmbeddedWindow() { return dynamic_cast<EmbeddedWindow*>(getByRowCol(1, 1)); } |
|
|
|
const EmbeddedWindow* getEmbeddedWindow() const { return dynamic_cast<const EmbeddedWindow*>(getByRowCol(1, 1)); } |
|
|
|
Corner* getCorner(CornerType c) { return dynamic_cast<Corner*>(_getCorner(c)); } |
|
|
|
const Corner* getCorner(CornerType c) const { return dynamic_cast<const Corner*>(_getCorner(c)); } |
|
|
|
Border* getBorder(BorderType b) { return dynamic_cast<Border*>(_getBorder(b)); } |
|
|
|
const Border* getBorder(BorderType b) const { return dynamic_cast<const Border*>(_getBorder(b)); } |
|
|
|
// This method resizes the internal EmbeddedWindow object and then properly resizes |
|
// the reset of the Frame based on the sizes of the Corners, Borders, etc. |
|
bool resizeFrame(point_type, point_type); |
|
|
|
unsigned int getFlags() const |
|
{ |
|
return _flags; |
|
} |
|
|
|
void setFlags(unsigned int flags) |
|
{ |
|
_flags = flags; |
|
} |
|
|
|
bool canResize() const |
|
{ |
|
return (_flags & FRAME_RESIZE) != 0; |
|
} |
|
|
|
bool canMove() const |
|
{ |
|
return (_flags & FRAME_MOVE) != 0; |
|
} |
|
|
|
bool canTexture() const |
|
{ |
|
return (_flags & FRAME_TEXTURE) != 0; |
|
} |
|
|
|
protected: |
|
|
|
Widget* _getCorner (CornerType) const; |
|
Widget* _getBorder (BorderType) const; |
|
|
|
unsigned int _flags; |
|
}; |
|
|
|
} |
|
|
|
#endif
|
|
|