2008-07-26 04:04:41 +08:00
|
|
|
/* -*-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.
|
|
|
|
*/
|
|
|
|
|
2008-11-28 22:35:33 +08:00
|
|
|
// Code by: Jeremy Moles (cubicool) 2007-2008
|
2008-07-16 01:21:25 +08:00
|
|
|
|
|
|
|
#ifndef OSGWIDGET_FRAME
|
|
|
|
#define OSGWIDGET_FRAME
|
|
|
|
|
|
|
|
#include <osgWidget/Table>
|
|
|
|
|
|
|
|
namespace osgWidget {
|
|
|
|
|
2008-11-28 22:35:33 +08:00
|
|
|
/*
|
|
|
|
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
|
|
|
|
*/
|
|
|
|
|
2008-07-26 03:57:17 +08:00
|
|
|
class OSGWIDGET_EXPORT Frame: public Table
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
2008-11-28 22:35:33 +08:00
|
|
|
enum CornerType
|
2008-07-26 03:57:17 +08:00
|
|
|
{
|
|
|
|
CORNER_LOWER_LEFT,
|
|
|
|
CORNER_LOWER_RIGHT,
|
|
|
|
CORNER_UPPER_LEFT,
|
|
|
|
CORNER_UPPER_RIGHT
|
|
|
|
};
|
|
|
|
|
2008-11-28 22:35:33 +08:00
|
|
|
enum BorderType
|
2008-07-26 03:57:17 +08:00
|
|
|
{
|
|
|
|
BORDER_LEFT,
|
|
|
|
BORDER_RIGHT,
|
|
|
|
BORDER_TOP,
|
|
|
|
BORDER_BOTTOM
|
|
|
|
};
|
|
|
|
|
2008-11-28 22:35:33 +08:00
|
|
|
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);
|
2008-07-26 03:57:17 +08:00
|
|
|
|
|
|
|
class OSGWIDGET_EXPORT Corner: public Widget
|
|
|
|
{
|
|
|
|
public:
|
2008-11-28 22:35:33 +08:00
|
|
|
META_Object(osgWidget, Corner);
|
2008-07-26 03:57:17 +08:00
|
|
|
|
2008-11-28 22:35:33 +08:00
|
|
|
Corner (CornerType = CORNER_LOWER_LEFT, point_type = 0.0f, point_type = 0.0f);
|
2008-07-26 03:57:17 +08:00
|
|
|
Corner (const Corner&, const osg::CopyOp&);
|
|
|
|
|
2008-11-28 22:35:33 +08:00
|
|
|
virtual void parented (Window*);
|
|
|
|
virtual bool mouseDrag (double, double, WindowManager*);
|
2008-07-26 03:57:17 +08:00
|
|
|
|
2008-11-28 22:35:33 +08:00
|
|
|
CornerType getCornerType() const
|
|
|
|
{
|
2008-07-26 03:57:17 +08:00
|
|
|
return _corner;
|
|
|
|
}
|
|
|
|
|
2008-11-28 22:35:33 +08:00
|
|
|
void setCornerType(CornerType corner)
|
|
|
|
{
|
2008-07-26 03:57:17 +08:00
|
|
|
_corner = corner;
|
|
|
|
}
|
|
|
|
|
2008-11-28 22:35:33 +08:00
|
|
|
void setCornerTypeAndName(CornerType corner)
|
|
|
|
{
|
2008-07-26 03:57:17 +08:00
|
|
|
_corner = corner;
|
2008-11-28 22:35:33 +08:00
|
|
|
_name = cornerTypeToString(corner);
|
2008-07-26 03:57:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
2008-11-28 22:35:33 +08:00
|
|
|
|
|
|
|
CornerType _corner;
|
2008-07-26 03:57:17 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
class OSGWIDGET_EXPORT Border: public Widget
|
|
|
|
{
|
|
|
|
public:
|
2008-11-28 22:35:33 +08:00
|
|
|
META_Object(osgWidget, Border);
|
2008-07-26 03:57:17 +08:00
|
|
|
|
2008-11-28 22:35:33 +08:00
|
|
|
Border (BorderType = BORDER_LEFT, point_type = 0.0f, point_type = 0.0f);
|
2008-07-26 03:57:17 +08:00
|
|
|
Border (const Border&, const osg::CopyOp&);
|
|
|
|
|
2008-11-28 22:35:33 +08:00
|
|
|
virtual void parented (Window*);
|
|
|
|
virtual void positioned ();
|
|
|
|
virtual bool mouseDrag (double, double, WindowManager*);
|
2008-07-26 03:57:17 +08:00
|
|
|
|
2008-11-28 22:35:33 +08:00
|
|
|
BorderType getBorderType() const
|
|
|
|
{
|
2008-07-26 03:57:17 +08:00
|
|
|
return _border;
|
|
|
|
}
|
|
|
|
|
2008-11-28 22:35:33 +08:00
|
|
|
void setBorderType(BorderType border)
|
|
|
|
{
|
2008-07-26 03:57:17 +08:00
|
|
|
_border = border;
|
|
|
|
}
|
|
|
|
|
2008-11-28 22:35:33 +08:00
|
|
|
void setBorderTypeAndName(BorderType border)
|
|
|
|
{
|
2008-07-26 03:57:17 +08:00
|
|
|
_border = border;
|
2008-11-28 22:35:33 +08:00
|
|
|
_name = borderTypeToString(border);
|
2008-07-26 03:57:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
2008-11-28 22:35:33 +08:00
|
|
|
BorderType _border;
|
2008-07-26 03:57:17 +08:00
|
|
|
};
|
|
|
|
|
2008-11-28 22:35:33 +08:00
|
|
|
META_Object(osgWidget, Frame);
|
2008-07-26 03:57:17 +08:00
|
|
|
|
2008-11-28 22:35:33 +08:00
|
|
|
Frame (const std::string& = "", unsigned int = 0);
|
2008-07-26 03:57:17 +08:00
|
|
|
Frame (const Frame&, const osg::CopyOp&);
|
|
|
|
|
|
|
|
static Frame* createSimpleFrame(
|
|
|
|
const std::string&,
|
|
|
|
point_type,
|
|
|
|
point_type,
|
|
|
|
point_type,
|
|
|
|
point_type,
|
2008-11-28 22:35:33 +08:00
|
|
|
unsigned int = 0,
|
|
|
|
Frame* = 0
|
2008-07-26 03:57:17 +08:00
|
|
|
);
|
|
|
|
|
|
|
|
static Frame* createSimpleFrameWithSingleTexture(
|
|
|
|
const std::string&,
|
2008-11-28 22:35:33 +08:00
|
|
|
osg::Image*,
|
2008-07-26 03:57:17 +08:00
|
|
|
point_type,
|
|
|
|
point_type,
|
2008-11-28 22:35:33 +08:00
|
|
|
unsigned int = 0,
|
|
|
|
Frame* = 0
|
|
|
|
);
|
|
|
|
|
|
|
|
static Frame* createSimpleFrameFromTheme(
|
|
|
|
const std::string&,
|
|
|
|
osg::Image*,
|
2008-07-26 03:57:17 +08:00
|
|
|
point_type,
|
|
|
|
point_type,
|
2008-11-28 22:35:33 +08:00
|
|
|
unsigned int = 0,
|
|
|
|
Frame* = 0
|
2008-07-26 03:57:17 +08:00
|
|
|
);
|
|
|
|
|
|
|
|
void createSimpleFrame(point_type cw, point_type ch, point_type w, point_type h)
|
|
|
|
{
|
2008-11-28 22:35:33 +08:00
|
|
|
createSimpleFrame(_name, cw, ch, w, h, 0, this);
|
2008-07-26 03:57:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void createSimpleFrameWithSingleTexture(
|
2008-11-28 22:35:33 +08:00
|
|
|
osg::Image* image,
|
|
|
|
point_type w,
|
|
|
|
point_type h
|
2008-07-26 03:57:17 +08:00
|
|
|
)
|
|
|
|
{
|
2008-11-28 22:35:33 +08:00
|
|
|
createSimpleFrameWithSingleTexture(_name, image, w, h, 0, this);
|
2008-07-26 03:57:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool setWindow(Window*);
|
|
|
|
|
|
|
|
EmbeddedWindow* getEmbeddedWindow() { return dynamic_cast<EmbeddedWindow*>(getByRowCol(1, 1)); }
|
|
|
|
|
|
|
|
const EmbeddedWindow* getEmbeddedWindow() const { return dynamic_cast<const EmbeddedWindow*>(getByRowCol(1, 1)); }
|
|
|
|
|
2008-11-28 22:35:33 +08:00
|
|
|
Corner* getCorner(CornerType c) { return dynamic_cast<Corner*>(_getCorner(c)); }
|
|
|
|
|
|
|
|
const Corner* getCorner(CornerType c) const { return dynamic_cast<const Corner*>(_getCorner(c)); }
|
2008-07-26 03:57:17 +08:00
|
|
|
|
2008-11-28 22:35:33 +08:00
|
|
|
Border* getBorder(BorderType b) { return dynamic_cast<Border*>(_getBorder(b)); }
|
2008-07-26 03:57:17 +08:00
|
|
|
|
2008-11-28 22:35:33 +08:00
|
|
|
const Border* getBorder(BorderType b) const { return dynamic_cast<const Border*>(_getBorder(b)); }
|
2008-07-26 03:57:17 +08:00
|
|
|
|
2008-11-28 22:35:33 +08:00
|
|
|
// 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;
|
|
|
|
}
|
2008-07-26 03:57:17 +08:00
|
|
|
|
|
|
|
protected:
|
|
|
|
|
2008-11-28 22:35:33 +08:00
|
|
|
Widget* _getCorner (CornerType) const;
|
|
|
|
Widget* _getBorder (BorderType) const;
|
2008-07-26 03:57:17 +08:00
|
|
|
|
2008-11-28 22:35:33 +08:00
|
|
|
unsigned int _flags;
|
2008-07-16 01:21:25 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|