From Jeremy Moles, updates to osgWidget

Merged my Robert Osfield from OpenSceneGraph-osgWidget-dev.
This commit is contained in:
Robert Osfield
2008-11-28 14:35:33 +00:00
parent d3b2d9b074
commit 9748fdd605
35 changed files with 1234 additions and 639 deletions

View File

@@ -1,11 +1,10 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: Box.cpp 64 2008-06-30 21:32:00Z cubicool $
#include <osgWidget/Box>
namespace osgWidget {
Box::Box(const std::string& name, BOX_TYPE bt, bool uniform):
Box::Box(const std::string& name, BoxType bt, bool uniform):
Window (name),
_boxType (bt),
_uniform (uniform),

View File

@@ -1,5 +1,4 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: Canvas.cpp 66 2008-07-14 21:54:09Z cubicool $
#include <osgWidget/Canvas>
@@ -20,13 +19,11 @@ void Canvas::_resizeImplementation(point_type w, point_type h) {
}
bool Canvas::addWidget(Widget* widget, point_type x, point_type y) {
if(Window::addWidget(widget)) {
widget->setOrigin(x, y);
if(!widget) return false;
return true;
}
return false;
widget->setOrigin(x, y);
return Window::addWidget(widget);
}
}

View File

@@ -1,13 +1,15 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: Frame.cpp 59 2008-05-15 20:55:31Z cubicool $
#include <osg/io_utils>
#include <osgDB/ReadFile>
#include <osgWidget/WindowManager>
#include <osgWidget/Frame>
#include <cassert>
namespace osgWidget {
std::string Frame::cornerToString(CORNER c) {
std::string Frame::cornerTypeToString(CornerType c)
{
if(c == CORNER_LOWER_LEFT) return "CornerLowerLeft";
else if(c == CORNER_LOWER_RIGHT) return "CornerLowerRight";
@@ -17,7 +19,8 @@ std::string Frame::cornerToString(CORNER c) {
else return "CornerUpperLeft";
}
std::string Frame::borderToString(BORDER b) {
std::string Frame::borderTypeToString(BorderType b)
{
if(b == BORDER_LEFT) return "BorderLeft";
else if(b == BORDER_RIGHT) return "BorderRight";
@@ -27,54 +30,44 @@ std::string Frame::borderToString(BORDER b) {
else return "BorderBottom";
}
Frame::Corner::Corner(CORNER corner, point_type width, point_type height):
Widget (cornerToString(corner), width, height),
_corner (corner) {
setEventMask(EVENT_MASK_MOUSE_DRAG);
Frame::Corner::Corner(CornerType corner, point_type width, point_type height):
Widget (cornerTypeToString(corner), width, height),
_corner (corner)
{
}
Frame::Corner::Corner(const Corner& corner, const osg::CopyOp& co):
Widget (corner, co),
_corner (corner._corner) {
_corner (corner._corner)
{
}
bool Frame::Corner::mouseDrag(double x, double y, WindowManager* wm) {
Window* parent = getParent();
void Frame::Corner::parented(Window* window) {
Frame* parent = dynamic_cast<Frame*>(getParent());
if(!parent) return false;
if(!parent) return;
if(wm->isInvertedY()) {
if(_corner == CORNER_UPPER_LEFT) {
if(parent->resizeAdd(-x, -y)) parent->addOrigin(x, y);
}
if(parent->canResize()) setEventMask(EVENT_MASK_MOUSE_DRAG);
}
else if(_corner == CORNER_UPPER_RIGHT) {
if(parent->resizeAdd(x, -y)) parent->addY(y);
}
bool Frame::Corner::mouseDrag(double x, double y, WindowManager* wm)
{
Frame* parent = dynamic_cast<Frame*>(getParent());
else if(_corner == CORNER_LOWER_RIGHT) parent->resizeAdd(x, y);
if(!parent || !parent->canResize()) return false;
else {
if(parent->resizeAdd(-x, y)) parent->addX(x);
}
if(_corner == CORNER_UPPER_LEFT) {
if(parent->resizeAdd(-x, y)) parent->addX(x);
}
else if(_corner == CORNER_UPPER_RIGHT) parent->resizeAdd(x, y);
else if(_corner == CORNER_LOWER_RIGHT) {
if(parent->resizeAdd(x, -y)) parent->addY(y);
}
// These are basically flipped-around versions of the above routines; we
// do it this way to avoid lots of uncessary if tests.
else {
if(_corner == CORNER_UPPER_LEFT) {
if(parent->resizeAdd(-x, y)) parent->addX(x);
}
else if(_corner == CORNER_UPPER_RIGHT) parent->resizeAdd(x, y);
else if(_corner == CORNER_LOWER_RIGHT) {
if(parent->resizeAdd(x, -y)) parent->addY(y);
}
else {
if(parent->resizeAdd(-x, -y)) parent->addOrigin(x, y);
}
if(parent->resizeAdd(-x, -y)) parent->addOrigin(x, y);
}
parent->update();
@@ -82,34 +75,84 @@ bool Frame::Corner::mouseDrag(double x, double y, WindowManager* wm) {
return true;
}
Frame::Border::Border(BORDER border, point_type width, point_type height):
Widget (borderToString(border), width, height),
_border (border) {
Frame::Border::Border(BorderType border, point_type width, point_type height):
Widget (borderTypeToString(border), width, height),
_border (border)
{
setCanFill(true);
setEventMask(EVENT_MASK_MOUSE_DRAG);
}
Frame::Border::Border(const Border& border, const osg::CopyOp& co):
Widget (border, co),
_border (border._border) {
_border (border._border)
{
}
bool Frame::Border::mouseDrag(double x, double y, WindowManager* wm) {
Window* parent = getParent();
void Frame::Border::parented(Window* window) {
Frame* parent = dynamic_cast<Frame*>(getParent());
if(!parent) return false;
if(!parent) return;
if(_border == BORDER_LEFT) {
if(parent->resizeAdd(-x, 0.0f)) parent->addX(x);
if(parent->canResize()) setEventMask(EVENT_MASK_MOUSE_DRAG);
}
void Frame::Border::positioned()
{
osg::Image* image = _image();
if(!image) return;
Frame* parent = dynamic_cast<Frame*>(getParent());
if(!parent || !parent->canTexture()) return;
point_type w = image->s() / 8.0f;
point_type h = getHeight();
if(_border == BORDER_LEFT) setTexCoordRegion(w * 3, 0.0f, w, h);
else if(_border == BORDER_RIGHT) setTexCoordRegion(w * 4, 0.0f, w, h);
else if(_border == BORDER_TOP) {
// TODO: Temporary; fix this.
point_type tx1 = (w * 2) / image->s();
point_type tx2 = w / image->s();
point_type tx3 = getWidth() / w;
setTexCoord(tx1, tx3, LL);
setTexCoord(tx1, 0.0f, LR);
setTexCoord(tx2, 0.0f, UR);
setTexCoord(tx2, tx3, UL);
}
else if(_border == BORDER_RIGHT) parent->resizeAdd(x, 0.0f);
else {
point_type tx1 = (w * 7) / image->s();
point_type tx2 = (w * 6) / image->s();
point_type tx3 = getWidth() / w;
else if(_border == BORDER_TOP) parent->addOrigin(x, y);
setTexCoord(tx1, tx3, LL);
setTexCoord(tx1, 0.0f, LR);
setTexCoord(tx2, 0.0f, UR);
setTexCoord(tx2, tx3, UL);
}
}
bool Frame::Border::mouseDrag(double x, double y, WindowManager* wm)
{
Frame* parent = dynamic_cast<Frame*>(getParent());
if(!parent) return false;
if(_border == BORDER_TOP && parent->canMove()) parent->addOrigin(x, y);
else {
// The only BORDER that inverted-Y affects is this...
if(wm->isInvertedY()) parent->resizeAdd(0.0f, y);
if(!parent->canResize()) return false;
if(_border == BORDER_LEFT) {
if(parent->resizeAdd(-x, 0.0f)) parent->addX(x);
}
else if(_border == BORDER_RIGHT) parent->resizeAdd(x, 0.0f);
else {
if(parent->resizeAdd(0.0f, -y)) parent->addY(y);
@@ -121,54 +164,29 @@ bool Frame::Border::mouseDrag(double x, double y, WindowManager* wm) {
return true;
}
Frame::Frame(const std::string& name):
Table(name, 3, 3) {
Frame::Frame(const std::string& name, unsigned int flags):
Table (name, 3, 3),
_flags (flags)
{
}
Frame::Frame(const Frame& frame, const osg::CopyOp& co):
Table(frame, co) {
Table(frame, co)
{
}
Widget* Frame::_getCorner(CORNER c) const {
return const_cast<Widget*>(getByName(cornerToString(c)));
Widget* Frame::_getCorner(CornerType c) const
{
return const_cast<Widget*>(getByName(cornerTypeToString(c)));
}
Widget* Frame::_getBorder(BORDER b) const {
return const_cast<Widget*>(getByName(borderToString(b)));
Widget* Frame::_getBorder(BorderType b) const
{
return const_cast<Widget*>(getByName(borderTypeToString(b)));
}
void Frame::managed(WindowManager* wm) {
Window::managed(wm);
// Our Frame is created in an inverted-Y environment, so if this is the case
// just return here.
if(wm->isInvertedY()) return;
Corner* ll = getCorner(CORNER_LOWER_LEFT);
Corner* lr = getCorner(CORNER_LOWER_RIGHT);
Corner* ul = getCorner(CORNER_UPPER_LEFT);
Corner* ur = getCorner(CORNER_UPPER_RIGHT);
Border* t = getBorder(BORDER_TOP);
Border* b = getBorder(BORDER_BOTTOM);
if(!ll || !lr || !ul || !ur || !t || !b) {
warn()
<< "One or more of your Corner/Border objects in the Frame ["
<< _name << "] are invalid; cannot invert orientation." << std::endl
;
return;
}
ll->setCornerAndName(CORNER_UPPER_LEFT);
lr->setCornerAndName(CORNER_UPPER_RIGHT);
ul->setCornerAndName(CORNER_LOWER_LEFT);
ur->setCornerAndName(CORNER_LOWER_RIGHT);
t->setBorderAndName(BORDER_BOTTOM);
b->setBorderAndName(BORDER_TOP);
}
bool Frame::setWindow(Window* window) {
bool Frame::setWindow(Window* window)
{
if(!window) return false;
EmbeddedWindow* ew = getEmbeddedWindow();
@@ -186,24 +204,25 @@ Frame* Frame::createSimpleFrame(
point_type ch,
point_type w,
point_type h,
unsigned int flags,
Frame* exFrame
) {
Frame* frame = 0;
// Use an "existing frame" if we have it (for example, if you've in inherited from
// Frame and want to use this stuff.
if(!exFrame) frame = new Frame(name);
if(!exFrame) frame = new Frame(name, flags);
else frame = exFrame;
frame->addWidget(new Corner(CORNER_UPPER_LEFT, cw, ch), 0, 0);
frame->addWidget(new Border(BORDER_TOP, w, ch), 0, 1);
frame->addWidget(new Corner(CORNER_UPPER_RIGHT, cw, ch), 0, 2);
frame->addWidget(new Border(BORDER_LEFT, cw, h), 1, 0);
frame->addWidget(new Border(BORDER_RIGHT, cw, h), 1, 2);
frame->addWidget(new Corner(CORNER_LOWER_LEFT, cw, ch), 2, 0);
frame->addWidget(new Border(BORDER_BOTTOM, w, ch), 2, 1);
frame->addWidget(new Corner(CORNER_LOWER_RIGHT, cw, ch), 2, 2);
frame->addWidget(new Corner(CORNER_LOWER_LEFT, cw, ch), 0, 0);
frame->addWidget(new Border(BORDER_BOTTOM, w, ch), 0, 1);
frame->addWidget(new Corner(CORNER_LOWER_RIGHT, cw, ch), 0, 2);
frame->addWidget(new Border(BORDER_LEFT, cw, h), 1, 0);
frame->addWidget(new Border(BORDER_RIGHT, cw, h), 1, 2);
frame->addWidget(new Corner(CORNER_UPPER_LEFT, cw, ch), 2, 0);
frame->addWidget(new Border(BORDER_TOP, w, ch), 2, 1);
frame->addWidget(new Corner(CORNER_UPPER_RIGHT, cw, ch), 2, 2);
EmbeddedWindow* ew = new EmbeddedWindow(name, w, h);
@@ -214,6 +233,7 @@ Frame* Frame::createSimpleFrame(
return frame;
}
/*
Frame* Frame::createSimpleFrameWithSingleTexture(
const std::string& name,
const std::string& texture,
@@ -247,5 +267,332 @@ Frame* Frame::createSimpleFrameWithSingleTexture(
return frame;
}
*/
// Inspired by: http://www.wowwiki.com/EdgeFiles
Frame* Frame::createSimpleFrameWithSingleTexture(
const std::string& name,
osg::Image* image,
point_type width,
point_type height,
unsigned int flags,
Frame* exFrame
) {
Frame* frame = 0;
double w = width;
double h = height;
if (image)
{
w = image->s() / 8.0f;
h = image->t();
}
// The same as above...
if(!exFrame) frame = createSimpleFrame(name, w, h, width, height, flags);
else frame = createSimpleFrame(name, w, h, width, height, 0, exFrame);
if (image)
{
for(unsigned int i = 0; i < 9; i++) frame->getObjects()[i]->setImage(image);
XYCoord twh(w, h);
frame->getCorner(CORNER_UPPER_LEFT )->setTexCoordRegion(0.0f, 0.0f, twh);
frame->getBorder(BORDER_TOP )->setTexCoordRegion(w, 0.0f, twh);
frame->getCorner(CORNER_UPPER_RIGHT)->setTexCoordRegion(w * 2, 0.0f, twh);
frame->getBorder(BORDER_LEFT )->setTexCoordRegion(w * 3, 0.0f, twh);
frame->getBorder(BORDER_RIGHT )->setTexCoordRegion(w * 4, 0.0f, twh);
frame->getCorner(CORNER_LOWER_LEFT )->setTexCoordRegion(w * 5, 0.0f, twh);
frame->getBorder(BORDER_BOTTOM )->setTexCoordRegion(w * 6, 0.0f, twh);
frame->getCorner(CORNER_LOWER_RIGHT)->setTexCoordRegion(w * 7, 0.0f, twh);
// We set all of these to wrap vertically, but the REAL texture coordinates will
// be generated properly in the positioned() method.
frame->getByRowCol(0, 1)->setTexCoordWrapVertical();
frame->getByRowCol(1, 0)->setTexCoordWrapVertical();
frame->getByRowCol(1, 2)->setTexCoordWrapVertical();
frame->getByRowCol(2, 1)->setTexCoordWrapVertical();
// frame->getEmbeddedWindow()->setTexCoordRegion(cw, ch, tw - (cw * 2.0f), th - (ch * 2.0f));
}
else
{
osg::notify(osg::WARN) << "createSimpleFrameWithSingleTexture with a null image, the frame " << name << " will be use texture" << std::endl;
}
return frame;
}
bool Frame::resizeFrame(point_type w, point_type h) {
Border* left = getBorder(BORDER_LEFT);
Border* right = getBorder(BORDER_RIGHT);
Border* top = getBorder(BORDER_TOP);
Border* bottom = getBorder(BORDER_BOTTOM);
if(!left || !right || !top || !bottom) return false;
return resize(
left->getWidth() + right->getWidth() + w,
top->getHeight() + bottom->getHeight() + h
);
}
osg::Image* createNatifEdgeImageFromTheme(osg::Image* theme);
Frame* Frame::createSimpleFrameFromTheme(
const std::string& name,
osg::Image* image,
point_type width,
point_type height,
unsigned int flags,
Frame* exFrame
) {
osg::ref_ptr<osg::Image> natifImage = createNatifEdgeImageFromTheme(image);
Frame* frame;
frame = createSimpleFrameWithSingleTexture(name, natifImage.get(), width, height, flags, exFrame);
if (frame && image && natifImage.valid())
{
const unsigned int bpps = image->getPixelSizeInBits() / 8;
const unsigned int one_third_s = image->s()/3;
unsigned char* srcdata = (unsigned char*)image->data();
osg::Vec4 color(0,0,0,1);
for (unsigned int d = 0; d < bpps; d++)
{
color[d] = srcdata[one_third_s * image->s() * bpps + (one_third_s) * bpps + d] * 1.0/255.0;
}
frame->getEmbeddedWindow()->setColor(color);
}
return frame;
}
// (c) 2006-2008 Jean-Sébastien Guay
// adapted by Cedric Pinson
/** Implementation of copyImage. */
template<typename T>
void copyDataImpl(const osg::Image* source,
const unsigned int x1, const unsigned int y1,
const unsigned int x2, const unsigned int y2,
osg::Image* destination,
const unsigned int xd = 0, const unsigned int yd = 0)
{
if ((unsigned int)destination->s() >= xd + (x2 - x1) &&
(unsigned int)destination->t() >= yd + (y2 - y1))
{
const unsigned int bpps = source->getPixelSizeInBits() / (8 * sizeof(T));
T* srcdata = (T*)source->data();
T* dstdata = (T*)destination->data();
for (unsigned int y = 0; y < y2 - y1; ++y)
{
for (unsigned int x = 0; x < x2 - x1; ++x)
{
for (unsigned int d = 0; d < bpps; d++)
{
T v = srcdata[(y + y1) * source->s() * bpps + (x + x1) * bpps + d];
dstdata[(yd + y) * destination->s() * bpps + (xd + x) * bpps + d] = v;
}
}
}
}
else
assert(false && "copyDataImpl: Incorrect image dimensions.");
}
/** Copies a rectangle of corners (x1, y1), (x2, y2) from an image into
another image starting at position (xd, yd). No scaling is done, the
pixels are just copied, so the destination image must be at least
(xd + (x2 - x1)) by (yd + (y2 - y1)) pixels. */
void copyData(const osg::Image* source,
const unsigned int x1, const unsigned int y1,
const unsigned int x2, const unsigned int y2,
osg::Image* destination,
const unsigned int xd, const unsigned int yd)
{
if (source->getDataType() == destination->getDataType())
{
if (source->getDataType() == GL_UNSIGNED_BYTE)
{
copyDataImpl<unsigned char>(source, x1, y1, x2, y2,
destination, xd, yd);
}
else
{
assert(false && "copyData not implemented for this data type");
}
}
else
{
assert(false && "source and destination images must be of the same type.");
return;
}
}
/** Implementation of rotateImage. */
template<typename T>
osg::Image* rotateImageImpl(osg::Image* image)
{
if (image->s() == image->t())
{
const unsigned int s = image->s();
const unsigned int bpp = image->getPixelSizeInBits() / (8 * sizeof(T));
osg::ref_ptr<osg::Image> destination = new osg::Image;
destination->allocateImage(s, s, 1,
image->getPixelFormat(), image->getDataType(),
image->getPacking());
destination->setInternalTextureFormat(image->getInternalTextureFormat());
T* srcdata = (T*)image->data();
T* dstdata = (T*)destination->data();
for (unsigned int y = 0; y < s; ++y)
{
for (unsigned int x = 0; x < s; ++x)
{
for (unsigned int p = 0; p < bpp; p++)
dstdata[y * s * bpp + x * bpp + p] = srcdata[x * s * bpp + y * bpp + p];
}
}
return destination.release();
}
else
{
assert(false && "rotateImageImpl: Image must be square.");
return 0;
}
}
/** Rotates an osg::Image by 90 degrees. Returns a new osg::Image, be sure to
store it in a ref_ptr so it will be freed correctly. */
osg::Image* rotateImage(osg::Image* image)
{
if (image->getDataType() == GL_UNSIGNED_BYTE)
{
return rotateImageImpl<unsigned char>(image);
}
else
{
assert(false && "rotateImage not implemented for this data type");
return 0;
}
}
// SOURCE
// +---+---+---+
// | 1 | 2 | 3 |
// +---+---+---+
// | 4 | | 5 |
// +---+---+---+
// | 6 | 7 | 8 |
// +---+---+---+
// FINAL
// +---+---+---+---+---+---+---+---+
// | 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.
osg::Image* createNatifEdgeImageFromTheme(osg::Image* theme)
{
if (!theme) {
osg::notify(osg::WARN) << "can't create a natif edge image from null image theme as argument" << std::endl;
return 0;
}
osg::ref_ptr<osg::Image> final = new osg::Image;
const int s = theme->s();
const int t = theme->t();
const GLenum pixelFormat = theme->getPixelFormat();
const GLenum dataType = theme->getDataType();
const GLint internalFormat = theme->getInternalTextureFormat();
unsigned int packing = theme->getPacking();
if (s != t)
{
osg::notify(osg::WARN) << "width and height are different, bad format theme image " << theme->getFileName() << std::endl;
return 0;
}
// check size
int ceilvalue = static_cast<int>(ceil(s * 1.0 / 3));
int intvalue = s/3;
if (intvalue != ceilvalue)
{
osg::notify(osg::WARN) << "the size of theme file " << theme->getFileName() << " can not be divided by 3, check the documentation about theme format" << std::endl;
return 0;
}
const unsigned int one_third_s = s/3;
const unsigned int one_third_t = t/3;
final->allocateImage(8 * one_third_s , one_third_t, 1, pixelFormat, dataType, packing);
final->setInternalTextureFormat(internalFormat);
// copy 1 (6 in source)
copyData(theme, 0, 2 * one_third_s, one_third_s, 3 * one_third_s, final.get(), 0, 0);
// rotate and copy 2
osg::ref_ptr<osg::Image> rotateandcopy2 = new osg::Image;
rotateandcopy2->allocateImage(one_third_s , one_third_t, 1, pixelFormat, dataType, packing);
rotateandcopy2->setInternalTextureFormat(internalFormat);
copyData(theme, one_third_s, 0, 2 * one_third_s , one_third_s, rotateandcopy2.get(), 0, 0);
rotateandcopy2 = rotateImage(rotateandcopy2.get());
rotateandcopy2->flipHorizontal();
copyData(rotateandcopy2.get(), 0, 0, one_third_s , one_third_s, final.get(), 6*one_third_s, 0);
// copy 3 (8 in source)
copyData(theme, 2*one_third_s , 2 *one_third_s, 3*one_third_s , 3 * one_third_s, final.get(), 2 * one_third_s, 0);
// copy 4
copyData(theme, 0, one_third_s, one_third_s , 2 * one_third_s, final.get(), 3 * one_third_s, 0);
// copy 5
copyData(theme, 2*one_third_s , one_third_s, 3 * one_third_s , 2 * one_third_s, final.get(), 4 * one_third_s, 0);
// copy 6 (1 in source)
copyData(theme, 0 , 0, one_third_s, one_third_s, final.get(), 5 * one_third_s, 0);
// rotate and copy 7
osg::ref_ptr<osg::Image> rotateandcopy7 = new osg::Image;
rotateandcopy7->allocateImage(one_third_s , one_third_t, 1, pixelFormat, dataType, packing);
rotateandcopy7->setInternalTextureFormat(internalFormat);
copyData(theme, one_third_s, 2*one_third_s, 2 * one_third_s , 3 * one_third_s, rotateandcopy7.get(), 0, 0);
rotateandcopy7 = rotateImage(rotateandcopy7.get());
rotateandcopy7->flipHorizontal();
copyData(rotateandcopy7.get(), 0, 0, one_third_s , one_third_s, final.get(), one_third_s, 0);
// copy 8 (3 in source)
copyData(theme, 2 * one_third_s, 0, 3 * one_third_s , one_third_s , final.get(), 7 * one_third_s, 0);
return final.release();
}
}

View File

@@ -1,5 +1,4 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: Input.cpp 65 2008-07-14 16:29:28Z cubicool $
#include <osg/io_utils>
#include <osgWidget/WindowManager>
@@ -22,7 +21,7 @@ _cursor (new Widget("cursor")) {
// Make the cursor un-copyable.
_cursor->setCanClone(false);
_cursor->setDataVariance(osg::Object::DYNAMIC);
_cursor->setColor(0.0f, 0.0f, 0.0f, 0.0f);
_cursor->setColor(0.0f, 0.0f, 0.0f, 1.0f);
setEventMask(
// For showing/hiding the "cursor."
@@ -46,9 +45,9 @@ void Input::_calculateSize(const XYCoord& size) {
point_type width = size.x() + _cursor->getWidth();
point_type height = _cursor->getHeight();
if(width > getWidth()) setWidth(osg::round(width));
// if(width > getWidth()) setWidth(osg::round(width));
if(height > getHeight()) setHeight(osg::round(height));
// if(height > getHeight()) setHeight(osg::round(height));
}
void Input::_calculateCursorOffsets() {
@@ -59,28 +58,22 @@ void Input::_calculateCursorOffsets() {
const osgText::Text::GlyphQuads& gq = tgqmi->second;
point_type accum = 0.0f;
osg::Vec3 pos = _text->getPosition();
std::ostream& os = warn() << "_offsets[ ";
for(unsigned int i = 0; i < _maxSize; i++) {
osg::Vec2 ul = gq.getCoords()[0 + (i * 4)];
osg::Vec2 ll = gq.getCoords()[1 + (i * 4)];
osg::Vec2 lr = gq.getCoords()[2 + (i * 4)];
osg::Vec2 ur = gq.getCoords()[3 + (i * 4)];
osg::Vec3 ul = gq.getTransformedCoords(0)[0 + (i * 4)];
osg::Vec3 ll = gq.getTransformedCoords(0)[1 + (i * 4)];
osg::Vec3 lr = gq.getTransformedCoords(0)[2 + (i * 4)];
osg::Vec3 ur = gq.getTransformedCoords(0)[3 + (i * 4)];
accum += osg::round(lr.x() - ll.x());
_offsets[i] = accum;
os << _offsets[i] << " (" << static_cast<char>(_text->getText()[i]) << ") ";
_offsets[i] = lr.x() - pos.x();
// warn() << "vb: " << gq.getGlyphs()[i]->getHorizontalBearing() << std::endl;
}
os << "]" << std::endl;
}
bool Input::focus(WindowManager*) {
_cursor->setColor(1.0f, 1.0f, 1.0f, 0.5f);
_cursor->setColor(0.0f, 0.0f, 0.0f, 1.0f);
return true;
}
@@ -112,7 +105,7 @@ void Input::positioned() {
;
point_type x = getX() + _xoff;
point_type y = getY() + th + _yoff;
point_type y = getY() + _yoff;
// XYCoord size = getTextSize();
@@ -129,7 +122,6 @@ bool Input::keyUp(int key, int mask, WindowManager*) {
}
bool Input::keyDown(int key, int mask, WindowManager*) {
/*
osgText::String& s = _text->getText();
if(key == osgGA::GUIEventAdapter::KEY_BackSpace) {
@@ -166,16 +158,30 @@ bool Input::keyDown(int key, int mask, WindowManager*) {
_calculateSize(getTextSize());
getParent()->resize();
*/
warn() << "Input is disabled until someone can help me understand how to use osgText; sorry..." << std::endl;
return false;
}
void Input::setCursor(Widget*)
{
warn() << "Input::setCursor(Widget*) not implemented yet."<<std::endl;
void Input::setCursor(Widget*) {
}
unsigned int Input::calculateBestYOffset(const std::string& s) {
const osgText::FontResolution fr(_text->getCharacterHeight(), _text->getCharacterHeight());
osgText::String utf(s);
unsigned int descent = 0;
for(osgText::String::iterator i = utf.begin(); i != utf.end(); i++) {
osgText::Font* font = const_cast<osgText::Font*>(_text->getFont());
osgText::Font::Glyph* glyph = font->getGlyph(fr, *i);
unsigned int d = abs(glyph->getHorizontalBearing().y());
if(d > descent) descent = d;
}
return descent;
}
}

View File

@@ -1,5 +1,4 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: Label.cpp 59 2008-05-15 20:55:31Z cubicool $
#include <osg/Math>
#include <osgWidget/WindowManager>
@@ -9,12 +8,17 @@ namespace osgWidget {
Label::Label(const std::string& name, const std::string& label):
Widget (name, 0, 0),
_textIndex (0),
_text (new osgText::Text()) {
_text->setText(label);
_text (new osgText::Text()),
_textIndex (0) {
_text->setAlignment(osgText::Text::LEFT_BOTTOM);
_text->setDataVariance(osg::Object::DYNAMIC);
if(label.size()) {
_text->setText(label);
_calculateSize(getTextSize());
}
// TODO: Make a patch for this!
// If you're wondering why we don't use this let me explain...
//
@@ -36,7 +40,7 @@ _textIndex (label._textIndex) {
}
void Label::_calculateSize(const XYCoord& size) {
if(size.x() && size.y()) setMinimumSize(size.x(), size.y());
// if(size.x() && size.y()) setMinimumSize(size.x(), size.y());
if(getWidth() < size.x()) setWidth(size.x());
@@ -45,8 +49,15 @@ void Label::_calculateSize(const XYCoord& size) {
// TODO: This will almost certainly get out of sync. :(
void Label::parented(Window* parent) {
// If we've been cloned, use the index of the old text Drawable.
if(_textIndex) parent->getGeode()->setDrawable(_textIndex, _text.get());
osg::Geode* geode = parent->getGeode();
// If we've been cloned, use the index of the old text Drawable if it's already there.
// However, we have a problem here: imagine a Label gets cloned AFTER being added to
// a Window; it'll have a _textIndex, but that _textIndex won't apply to the
// currently cloned object. In this case, we'll need to check to be SURE.
osgText::Text* text = dynamic_cast<osgText::Text*>(geode->getDrawable(_textIndex));
if(text) parent->getGeode()->setDrawable(_textIndex, _text.get());
// Otherwise, add it as new.
else _textIndex = parent->addDrawableAndGetIndex(_text.get());
@@ -58,33 +69,16 @@ void Label::unparented(Window* parent) {
_textIndex = 0;
}
void Label::managed(WindowManager* wm) {
if(wm->isInvertedY()) {
// We rotate along our X axis, so we need to make sure and translate the
// text later to preserve centering.
_text->setAxisAlignment(osgText::Text::USER_DEFINED_ROTATION);
_text->setRotation(osg::Quat(
osg::DegreesToRadians(180.0f),
osg::Vec3(1.0f, 0.0f, 0.0f)
));
}
}
void Label::positioned() {
XYCoord size = getTextSize();
point_type x = osg::round(((getWidth() - size.x()) / 2.0f) + getX());
point_type y = 0.0f;
point_type y = osg::round(((getHeight() - size.y()) / 2.0f) + getY());
point_type z = _calculateZ(getLayer() + 1);
if(getWindowManager() && getWindowManager()->isInvertedY()) y =
osg::round(((getHeight() - size.y()) / 2.0f) + getY() + size.y())
;
else y = osg::round(((getHeight() - size.y()) / 2.0f) + getY());
// These values are permisable with CENTER_CENTER mode is active.
// point_type x = round(getX() + (getWidth() / 2.0f));
// point_type y = round(getY() + (getHeight() / 2.0f));
/*
warn() << "Label widget size : " << getWidth() << " x " << getHeight() << std::endl;
warn() << "Label widget tsize: " << getWidthTotal() << " x " << getHeightTotal() << std::endl;
@@ -94,12 +88,18 @@ void Label::positioned() {
warn() << "------------------------------------" << std::endl;
*/
_text->setPosition(osg::Vec3(x, y, _calculateZ(getLayer() + 1)));
}
const WindowManager* wm = _getWindowManager();
void Label::update()
{
warn() << "Label::update() not implemented yet."<<std::endl;
if(wm && wm->isUsingRenderBins()) {
_text->getOrCreateStateSet()->setRenderBinDetails(
static_cast<int>(z * OSGWIDGET_RENDERBIN_MOD),
"RenderBin"
);
z = 0.0f;
}
_text->setPosition(osg::Vec3(x, y, z));
}
void Label::setLabel(const std::string& label) {

View File

@@ -1,5 +1,4 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: Lua.cpp 2 2008-01-24 16:11:26Z cubicool $
#include <osgDB/FileUtils>
#include <osgWidget/Lua>

View File

@@ -1,5 +1,4 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: Python.cpp 59 2008-05-15 20:55:31Z cubicool $
// Python.h needs to be included before anything else.
#ifdef OSGWIDGET_USEPYTHON
@@ -172,7 +171,7 @@ bool PythonEngine::runFile(const std::string& filePath) {
return false;
}
FILE* f = osgDB::fopen(filePath.c_str(), "r");
FILE* f = fopen(filePath.c_str(), "r");
PyObject* r = PyRun_File(f, filePath.c_str(), Py_file_input, _data->main, _data->main);
fclose(f);

View File

@@ -1,5 +1,4 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: StyleManager.cpp 55 2008-05-12 19:14:42Z cubicool $
#include <sstream>
#include <osg/io_utils>

View File

@@ -1,5 +1,4 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: Table.cpp 48 2008-05-05 14:13:20Z cubicool $
#include <osgWidget/Table>

View File

@@ -1,5 +1,4 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: Util.cpp 59 2008-05-15 20:55:31Z cubicool $
#include <osg/io_utils>
@@ -36,14 +35,6 @@ std::string generateRandomName(const std::string& base) {
return ss.str();
}
osg::Matrix createInvertedYOrthoProjectionMatrix(matrix_type width, matrix_type height) {
osg::Matrix m = osg::Matrix::ortho2D(0.0f, width, 0.0f, height);
osg::Matrix s = osg::Matrix::scale(1.0f, -1.0f, 1.0f);
osg::Matrix t = osg::Matrix::translate(0.0f, -height, 0.0f);
return t * s * m;
}
osg::Camera* createOrthoCamera(matrix_type width, matrix_type height) {
osg::Camera* camera = new osg::Camera();
@@ -61,20 +52,12 @@ osg::Camera* createOrthoCamera(matrix_type width, matrix_type height) {
return camera;
}
osg::Camera* createInvertedYOrthoCamera(matrix_type width, matrix_type height) {
osg::Camera* camera = createOrthoCamera(width, height);
int createExample(osgViewer::Viewer& viewer, WindowManager* wm, osg::Node* node) {
if(!wm) return 1;
camera->setProjectionMatrix(createInvertedYOrthoProjectionMatrix(width, height));
return camera;
}
osg::Group* _createExampleCommon(osgViewer::View* view, WindowManager* wm, osg::Node* node) {
if(!wm) return 0;
view->setUpViewInWindow(
0,
0,
viewer.setUpViewInWindow(
50,
50,
static_cast<int>(wm->getWidth()),
static_cast<int>(wm->getHeight())
);
@@ -86,87 +69,23 @@ osg::Group* _createExampleCommon(osgViewer::View* view, WindowManager* wm, osg::
if(node) group->addChild(node);
view->addEventHandler(new osgWidget::MouseHandler(wm));
view->addEventHandler(new osgWidget::KeyboardHandler(wm));
view->addEventHandler(new osgWidget::ResizeHandler(wm, camera));
view->addEventHandler(new osgViewer::StatsHandler());
view->addEventHandler(new osgViewer::WindowSizeHandler());
view->addEventHandler(new osgGA::StateSetManipulator(
view->getCamera()->getOrCreateStateSet()
viewer.addEventHandler(new osgWidget::MouseHandler(wm));
viewer.addEventHandler(new osgWidget::KeyboardHandler(wm));
viewer.addEventHandler(new osgWidget::ResizeHandler(wm, camera));
viewer.addEventHandler(new osgWidget::CameraSwitchHandler(wm, camera));
viewer.addEventHandler(new osgViewer::StatsHandler());
viewer.addEventHandler(new osgViewer::WindowSizeHandler());
viewer.addEventHandler(new osgGA::StateSetManipulator(
viewer.getCamera()->getOrCreateStateSet()
));
wm->resizeAllWindows();
return group;
}
int createExample(osgViewer::Viewer& viewer, WindowManager* wm, osg::Node* node) {
osg::Group* group = _createExampleCommon(&viewer, wm, node);
viewer.setSceneData(group);
return viewer.run();
}
// TODO: This function is totally broken; I don't really have any idea of how to do this.
// Incredibly frustrating stuff.
int createCompositeExample(
osgViewer::CompositeViewer& viewer,
osgViewer::View* view,
WindowManager* wm,
osg::Node* node
) {
osg::Group* group = _createExampleCommon(view, wm, node);
osg::MatrixTransform* watcher = new osg::MatrixTransform();
watcher->addChild(wm);
// Setup the main 2D view.
viewer.addView(view);
view->setSceneData(group);
// The view that "watches" the main view.
osgViewer::View* viewWatcher = new osgViewer::View();
viewer.addView(viewWatcher);
int w = static_cast<int>(wm->getWidth());
int h = static_cast<int>(wm->getHeight());
viewWatcher->setUpViewInWindow(0, 0, w, h);
// Setup our parent MatrixTransform so things look right in perspective.
watcher->setMatrix(
osg::Matrix::scale(1.0f, -1.0f, 1000.0f) *
osg::Matrix::rotate(osg::DegreesToRadians(90.0f), osg::Vec3d(1.0f, 0.0f, 0.0f))
);
watcher->getOrCreateStateSet()->setAttributeAndModes(
new osg::Scissor(0, 0, w, h),
osg::StateAttribute::OVERRIDE
);
osgGA::TrackballManipulator* tb = new osgGA::TrackballManipulator();
warn() << watcher->getMatrix() << std::endl;
/*
const osg::BoundingSphere& bs = watcher->getBound();
tb->setHomePosition(
bs.center() + osg::Vec3(0.0f, -3.5f * bs.radius(), 0.0f),
bs.center(),
osg::Vec3(0.0f, 1.0f, 0.0f)
);
*/
viewWatcher->setSceneData(watcher);
viewWatcher->setCameraManipulator(tb);
return viewer.run();
}
bool writeWindowManagerNode(WindowManager* wm) {
osgDB::writeNodeFile(*wm->getParent(0), "osgWidget.osg");

View File

@@ -1,5 +1,4 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: ViewerEventHandlers.cpp 59 2008-05-15 20:55:31Z cubicool $
#include <osgWidget/ViewerEventHandlers>
@@ -175,16 +174,87 @@ bool ResizeHandler::handle(
osg::Matrix::value_type w = gea.getWindowWidth();
osg::Matrix::value_type h = gea.getWindowHeight();
if(_wm->isInvertedY()) _camera->setProjectionMatrix(
createInvertedYOrthoProjectionMatrix(w, h)
);
if(_camera.valid()) {
_camera->setProjectionMatrix(osg::Matrix::ortho2D(0.0f, w, 0.0f, h));
else _camera->setProjectionMatrix(osg::Matrix::ortho2D(0.0f, w, 0.0f, h));
_wm->setSize(w, h);
}
_wm->setSize(w, h);
_wm->setWindowSize(w, h);
_wm->resizeAllWindows();
return true;
}
CameraSwitchHandler::CameraSwitchHandler(WindowManager* wm, osg::Camera* camera):
_wm (wm),
_camera (camera) {
}
bool CameraSwitchHandler::handle(
const osgGA::GUIEventAdapter& gea,
osgGA::GUIActionAdapter& gaa,
osg::Object* obj,
osg::NodeVisitor* nv
) {
if(
gea.getEventType() != osgGA::GUIEventAdapter::KEYDOWN ||
gea.getKey() != osgGA::GUIEventAdapter::KEY_F12
) return false;
osgViewer::View* view = dynamic_cast<osgViewer::View*>(&gaa);
if(!view) return false;
osg::Node* oldNode = view->getSceneData();
osg::MatrixTransform* oldTrans = dynamic_cast<osg::MatrixTransform*>(oldNode);
if(!oldTrans) {
// Imagine this is the number of pixels...
double scale = 2000.0f;
double width = _wm->getWidth();
double height = _wm->getHeight();
_oldNode = oldNode;
osg::MatrixTransform* mt = new osg::MatrixTransform();
mt->setMatrix(
osg::Matrix::translate(width / 2.0f, 0.0f, 0.0f) *
osg::Matrix::scale(1.0f, 1.0f, scale) *
osg::Matrix::rotate(osg::DegreesToRadians(45.0f), 0.0f, 1.0f, 0.0f)
);
mt->addChild(_wm.get());
mt->getOrCreateStateSet()->setMode(
GL_LIGHTING,
osg::StateAttribute::PROTECTED | osg::StateAttribute::OFF
);
mt->getOrCreateStateSet()->setMode(
GL_SCISSOR_TEST,
osg::StateAttribute::OVERRIDE | osg::StateAttribute::OFF
);
osgGA::MatrixManipulator* mm = view->getCameraManipulator();
// mm->setDistance(3000.0f);
// mm->setMinimumZoomScale(10.0f);
mm->setHomePosition(
// eye
osg::Vec3(width / 2.0f, height, 100.0f),
// center
osg::Vec3(0.0f, 0.0f, -(scale / 2.0f)),
// up
osg::Vec3(0.0f, 1.0f, 0.0f)
);
view->setSceneData(mt);
}
else view->setSceneData(_oldNode.get());
return true;
}
}

View File

@@ -3,8 +3,7 @@
#include <osg/io_utils>
#include <osg/Math>
#include <osg/BlendFunc>
#include <osg/TexMat>
#include <osg/TextureRectangle>
#include <osgDB/ReadFile>
#include <osgDB/FileUtils>
#include <osgWidget/WindowManager>
@@ -34,8 +33,8 @@ _canFill (false),
_canClone (true),
_isManaged (false),
_isStyled (false),
_minWidth (w),
_minHeight (h) {
_minWidth (0.0f),
_minHeight (0.0f) {
_name = name.size() ? name : generateRandomName("Widget");
if(!_norms.valid()) {
@@ -63,9 +62,6 @@ _minHeight (h) {
setDimensions(0.0f, 0.0f, w, h);
setColor(1.0f, 1.0f, 1.0f, 1.0f);
getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
}
Widget::Widget(const Widget& widget, const osg::CopyOp& co):
@@ -108,26 +104,13 @@ WindowManager* Widget::_getWindowManager() const {
}
osg::Image* Widget::_getImage() const {
const osg::Texture2D* texture = _texture();
const osg::Texture* texture = _texture();
if(texture) return const_cast<osg::Image*>(texture->getImage(0));
return 0;
}
void Widget::managed(WindowManager* wm) {
if(!wm->isInvertedY()) return;
osg::Matrix s = osg::Matrix::scale(1.0f, -1.0f, 1.0f);
osg::Matrix t = osg::Matrix::translate(0.0f, -1.0, 0.0f);
getOrCreateStateSet()->setTextureAttributeAndModes(
0,
new osg::TexMat(t * s),
osg::StateAttribute::ON
);
}
void Widget::setDimensions(point_type x, point_type y, point_type w, point_type h, point_type z) {
if(w != -1.0f && w < _minWidth) {
warn()
@@ -205,6 +188,14 @@ void Widget::setDimensions(point_type x, point_type y, point_type w, point_type
}
}
const WindowManager* wm = _getWindowManager();
if(wm && wm->isUsingRenderBins()) {
getOrCreateStateSet()->setRenderBinDetails(static_cast<int>(z), "RenderBin");
z = 0.0f;
}
(*verts)[LL].set(x, y, z);
(*verts)[LR].set(x + w, y, z);
(*verts)[UR].set(x + w, y + h, z);
@@ -221,7 +212,7 @@ void Widget::setColor(color_type r, color_type g, color_type b, color_type a, Co
(*cols)[UL].set(r, g, b, a);
}
else (*cols)[convertCorner(p)].set(r, g, b, a);
else (*cols)[p].set(r, g, b, a);
}
void Widget::addColor(color_type r, color_type g, color_type b, color_type a, Corner p) {
@@ -234,7 +225,7 @@ void Widget::addColor(color_type r, color_type g, color_type b, color_type a, Co
(*cols)[UL] += Color(r, g, b, a);
}
else (*cols)[convertCorner(p)] += Color(r, g, b, a);
else (*cols)[p] += Color(r, g, b, a);
}
void Widget::setTexCoord(texcoord_type tx, texcoord_type ty, Corner p) {
@@ -247,7 +238,15 @@ void Widget::setTexCoord(texcoord_type tx, texcoord_type ty, Corner p) {
(*texs)[UL].set(tx, ty);
}
else (*texs)[convertCorner(p)].set(tx, ty);
else (*texs)[p].set(tx, ty);
}
// TODO: We chop off any offset here if you use TOP; we need to do the same
// for BG, etc.
void Widget::setLayer(Layer layer, unsigned int offset) {
if(layer == LAYER_TOP) offset = 0;
_layer = layer + offset;
}
void Widget::setTexCoordRegion(point_type x, point_type y, point_type w, point_type h) {
@@ -263,27 +262,27 @@ void Widget::setTexCoordRegion(point_type x, point_type y, point_type w, point_t
// Set the LOWER_LEFT point.
XYCoord t(x / tw, y / tw);
(*texs)[UL] = t;
(*texs)[LL] = t;
// Set the LOWER_RIGHT point.
t += XYCoord(w / tw, 0.0f);
(*texs)[UR] = t;
(*texs)[LR] = t;
// Set the UPPER_RIGHT point.
t += XYCoord(0.0f, h / th);
(*texs)[LR] = t;
(*texs)[UR] = t;
// Set the UPPER_LEFT point.
t += XYCoord(-(w / tw), 0.0f);
(*texs)[LL] = t;
(*texs)[UL] = t;
}
void Widget::setTexCoordWrapHorizontal() {
osg::Image* image = _image();
osg::Texture2D* texture = _texture();
osg::Image* image = _image();
osg::Texture* texture = _texture();
if(!image || !texture || image->s() == 0.0f) return;
@@ -294,8 +293,8 @@ void Widget::setTexCoordWrapHorizontal() {
}
void Widget::setTexCoordWrapVertical() {
osg::Image* image = _image();
osg::Texture2D* texture = _texture();
osg::Image* image = _image();
osg::Texture* texture = _texture();
if(!image || !texture || image->t() == 0.0f) return;
@@ -311,35 +310,27 @@ XYCoord Widget::localXY(double _x, double _y) const {
return _parent->localXY(_x, _y) - getOrigin();
}
bool Widget::setImage(osg::Image* image, bool setTexCoords) {
bool Widget::setImage(osg::Image* image, bool setTexCoords, bool useTextRect) {
if(!image) {
warn() << "Widget [" << _name << "] cannot use a NULL image." << std::endl;
return false;
}
osg::Texture2D* texture = new osg::Texture2D();
osg::Texture* texture = 0;
texture->setDataVariance(osg::Object::DYNAMIC);
if(useTextRect) texture = new osg::TextureRectangle();
else texture = new osg::Texture2D();
if(!texture) return false;
texture->setImage(0, image);
getOrCreateStateSet()->setTextureAttributeAndModes(
0,
texture,
osg::StateAttribute::ON
);
if(setTexCoords) {
setTexCoord(0.0f, 0.0f, LOWER_LEFT);
setTexCoord(1.0f, 0.0f, LOWER_RIGHT);
setTexCoord(1.0f, 1.0f, UPPER_RIGHT);
setTexCoord(0.0f, 1.0f, UPPER_LEFT);
}
return true;
return setTexture(texture, setTexCoords, useTextRect);
}
bool Widget::setImage(const std::string& filePath, bool setTexCoords) {
bool Widget::setImage(const std::string& filePath, bool setTexCoords, bool useTextRect) {
if(!osgDB::findDataFile(filePath).size()) {
warn()
<< "Widget [" << _name
@@ -350,7 +341,37 @@ bool Widget::setImage(const std::string& filePath, bool setTexCoords) {
return false;
}
return setImage(osgDB::readImageFile(filePath), setTexCoords);
return setImage(osgDB::readImageFile(filePath), setTexCoords, useTextRect);
}
bool Widget::setTexture(osg::Texture* texture, bool setTexCoords, bool useTextRect) {
if(!texture) return false;
getOrCreateStateSet()->setTextureAttributeAndModes(
0,
texture,
osg::StateAttribute::ON
);
if(setTexCoords) {
if(useTextRect) {
osg::Image* image = texture->getImage(0);
setTexCoord(0.0f, 0.0f, LOWER_LEFT);
setTexCoord(image->s(), 0.0f, LOWER_RIGHT);
setTexCoord(image->s(), image->t(), UPPER_RIGHT);
setTexCoord(0.0f, image->t(), UPPER_LEFT);
}
else {
setTexCoord(0.0f, 0.0f, LOWER_LEFT);
setTexCoord(1.0f, 0.0f, LOWER_RIGHT);
setTexCoord(1.0f, 1.0f, UPPER_RIGHT);
setTexCoord(0.0f, 1.0f, UPPER_LEFT);
}
}
return true;
}
void Widget::setPadding(point_type pad) {
@@ -451,7 +472,7 @@ const Point& Widget::getPoint(Corner p) const {
if(p == ALL_CORNERS) point = UPPER_LEFT;
return (*_verts())[convertCorner(point)];
return (*_verts())[point];
}
const Color& Widget::getColor(Corner p) const {
@@ -459,7 +480,7 @@ const Color& Widget::getColor(Corner p) const {
if(p == ALL_CORNERS) point = UPPER_LEFT;
return (*_cols())[convertCorner(point)];
return (*_cols())[point];
}
const TexCoord& Widget::getTexCoord(Corner p) const {
@@ -467,25 +488,7 @@ const TexCoord& Widget::getTexCoord(Corner p) const {
if(p == ALL_CORNERS) point = UPPER_LEFT;
return (*_texs())[convertCorner(point)];
}
// This converts our points back and forth depding on whether or not we're in an
// inverted-Y WindowManager.
Widget::Corner Widget::convertCorner(Corner p) const {
const WindowManager* wm = getWindowManager();
if(!wm || !wm->isInvertedY()) return p;
if(p == UPPER_LEFT) return LOWER_LEFT;
else if(p == UPPER_RIGHT) return LOWER_RIGHT;
else if(p == LOWER_LEFT) return UPPER_LEFT;
else if(p == LOWER_RIGHT) return UPPER_RIGHT;
else return p;
return (*_texs())[point];
}
Color Widget::getImageColorAtXY(point_type x, point_type y) const {

View File

@@ -70,7 +70,11 @@ void Window::EmbeddedWindow::parented(Window* parent) {
}
void Window::EmbeddedWindow::unparented(Window*) {
// TODO: Figure out what's necessary here...
if(_window.valid()) {
_window->_parent = 0;
if(_parent) _parent->removeChild(_window.get());
}
}
void Window::EmbeddedWindow::managed(WindowManager* wm) {
@@ -95,6 +99,8 @@ void Window::EmbeddedWindow::positioned() {
// If the widget is fillable, ask the internal Window to resize itself.
// Whether or not the Window honors this reqest will be up to it.
_window->setOrigin(x, y);
_window->setZ(_calculateZ(getLayer() + 1));
_window->setZRange(_calculateZ(LAYER_TOP - (getLayer() + 1)));
_window->setVisibleArea(0, 0, static_cast<int>(w), static_cast<int>(h));
_window->resize(w, h);
}
@@ -109,7 +115,6 @@ bool Window::EmbeddedWindow::setWindow(Window* win) {
return false;
}
// TODO: I need to handle there already being a Window here.
_window = win;
_window->resize();
@@ -124,21 +129,27 @@ bool Window::EmbeddedWindow::setWindow(Window* win) {
return true;
}
void Window::EmbeddedWindow::updateSizeFromWindow() {
setSize(_window->getSize());
if(_parent) _parent->resize();
}
Window::Window(const std::string& name):
_parent (0),
_wm (0),
_index (0),
_x (0.0f),
_y (0.0f),
_z (0.0f),
_zRange (0.0f),
_strata (STRATA_NONE),
_vis (VM_FULL),
_r (0.0f),
_s (1.0f),
_scaleDenom (100.0f),
_vAnchor (VA_NONE),
_hAnchor (HA_NONE) {
_parent (0),
_wm (0),
_index (0),
_x (0.0f),
_y (0.0f),
_z (0.0f),
_zRange (0.0f),
_strata (STRATA_NONE),
_vis (VM_FULL),
_r (0.0f),
_s (1.0f),
_scaleDenom (100.0f),
_vAnchor (VA_NONE),
_hAnchor (HA_NONE) {
_name = name.size() ? name : generateRandomName("Window");
// TODO: Fix the "bg" name.
@@ -146,7 +157,7 @@ _hAnchor (HA_NONE) {
Widget* bg = new Widget(name + "bg", 0.0f, 0.0f);
bg->setLayer(Widget::LAYER_BG);
bg->setColor(0.0f, 0.0f, 0.0f, 0.5f);
bg->setColor(1.0f, 1.0f, 1.0f, 1.0f);
_setParented(bg);
@@ -201,7 +212,14 @@ _visibleArea (window._visibleArea) {
for(unsigned int i = 1; i < geode->getNumDrawables(); i++) {
Widget* widget = dynamic_cast<Widget*>(geode->getDrawable(i));
if(!widget || !widget->canClone()) continue;
if(!widget) continue;
// TODO: Properly test this...
if(!widget->canClone()) {
// geode->removeDrawable(widget);
continue;
}
_setParented(widget);
@@ -286,22 +304,11 @@ bool Window::resizePercent(point_type width, point_type height) {
}
void Window::update() {
// Update all embedded children; the zRange values continue to decrease in precision
// as you add more and more embedded Windows.
WindowList wl;
getEmbeddedList(wl);
// Each child Window gets half the zRange of it's parent Window. This means the more
// you embed Windows into other Windows, the less depth precision you're going to have.
for(WindowList::iterator w = wl.begin(); w != wl.end(); w++) {
Window* win = w->get();
win->_z = _zRange / 2.0f;
win->_zRange = _zRange / 2.0f;
win->update();
}
for(WindowList::iterator w = wl.begin(); w != wl.end(); w++) w->get()->update();
matrix_type x = _x;
matrix_type y = _y;
@@ -319,6 +326,42 @@ void Window::update() {
xy.set(x, y);
}
matrix_type z = _z;
// We can't do proper scissoring until we have access to our parent WindowManager, and
// we need to determine the sorting method we want to use.
if(_wm) {
if(_wm->isUsingRenderBins()) {
getOrCreateStateSet()->setRenderBinDetails(
static_cast<int>((1.0f - fabs(_z)) * OSGWIDGET_RENDERBIN_MOD),
"RenderBin"
);
z = 0.0f;
}
int sx = static_cast<int>(xy.x());
int sy = static_cast<int>(xy.y());
int sw = static_cast<int>(_width.current);
int sh = static_cast<int>(_height.current);
// This sets the Scissor area to some offset defined by the user.
if(_vis == VM_PARTIAL) {
sw = static_cast<int>(_visibleArea[2]);
sh = static_cast<int>(_visibleArea[3]);
}
// Otherwise, use the size of the WindowManager itself.
else if(_vis == VM_ENTIRE) {
sx = 0;
sy = 0;
sw = static_cast<int>(_wm->getWidth());
sh = static_cast<int>(_wm->getHeight());
}
_scissor()->setScissor(sx, sy, sw, sh);
}
// Update the Window itself, setting it's matrix according to translate, rotate, and
// scale values.
@@ -326,47 +369,11 @@ void Window::update() {
osg::DegreesToRadians(_r),
osg::Vec3d(0.0f, 0.0f, 1.0f)
);
osg::Matrix s = osg::Matrix::scale(_s, _s, 1.0f);
osg::Matrix t = osg::Matrix::translate(x - _visibleArea[0], y - _visibleArea[1], _z);
osg::Matrix t = osg::Matrix::translate(x - _visibleArea[0], y - _visibleArea[1], z);
setMatrix(r * s * t);
// We can't do proper scissoring until we have access to our parent WindowManager.
if(_wm) {
int x = static_cast<int>(xy.x());
int y = static_cast<int>(xy.y());
int w = static_cast<int>(_width.current);
int h = static_cast<int>(_height.current);
int wmh = static_cast<int>(_wm->getHeight());
int nx = x;
int ny = y;
int nw = w;
int nh = h;
// This sets the Scissor area to the full size of the Window.
if(_vis == VM_FULL && _wm->isInvertedY()) ny = wmh - h - y;
// This sets the Scissor area to some offset defined by the user.
else if(_vis == VM_PARTIAL) {
if(_wm->isInvertedY()) ny = wmh - y - static_cast<int>(_visibleArea[3]);
// else ny = static_cast<int>(_visibleArea[3]);
nw = static_cast<int>(_visibleArea[2]);
nh = static_cast<int>(_visibleArea[3]);
}
// Otherwise, use the size of the WindowManager itself.
else {
nx = 0;
ny = 0;
nw = static_cast<int>(_wm->getWidth());
nh = wmh;
}
_scissor()->setScissor(nx, ny, nw, nh);
}
}
void Window::_setWidthAndHeightUnknownSizeError(const std::string& size, point_type val) {
@@ -526,9 +533,9 @@ void Window::_setParented(Widget* widget, bool setUnparented) {
}
else {
widget->_parent = 0;
widget->unparented(this);
widget->_parent = 0;
}
}
@@ -639,6 +646,7 @@ void Window::addVisibleArea(int x, int y, int w, int h) {
_visibleArea[3] += h;
}
// The topmost Window always has this method called, instead of the embedded window directly.
bool Window::setFocused(const Widget* widget) {
// TODO: I've turned on the warn() here, but perhaps I shouldn't? I need to define
// the conditions under which it's okay to call setFocus() with a NULL widget.
@@ -650,7 +658,28 @@ bool Window::setFocused(const Widget* widget) {
ConstIterator i = std::find(begin(), end(), widget);
bool found = false;
if(i == end()) {
// We couldn't find the widget in the toplevel, so lets see if one of our
// EmbeddedWindow objects has it.
WindowList wl;
getEmbeddedList(wl);
for(WindowList::iterator w = wl.begin(); w != wl.end(); w++) {
ConstIterator ii = std::find(w->get()->begin(), w->get()->end(), widget);
if(ii != w->get()->end()) {
found = true;
i = ii;
}
}
}
else found = true;
if(!found) {
warn()
<< "Window [" << _name
<< "] couldn't find the Widget [" << widget->getName()
@@ -666,9 +695,31 @@ bool Window::setFocused(const Widget* widget) {
}
bool Window::setFocused(const std::string& name) {
Widget* w = getByName(name);
Widget* w1 = getByName(name);
if(!w) {
bool found = false;
if(!w1) {
// Just like above, we couldn't find the widget in the toplevel, so lets see if
// one of our EmbeddedWindow objects has it. The difference here is that we
// search by name.
WindowList wl;
getEmbeddedList(wl);
for(WindowList::iterator w = wl.begin(); w != wl.end(); w++) {
Widget* w2 = w->get()->getByName(name);
if(w2) {
found = true;
w1 = w2;
}
}
}
else found = true;
if(!found) {
warn()
<< "Window [" << _name
<< "] couldn't find a Widget named [" << name
@@ -678,11 +729,17 @@ bool Window::setFocused(const std::string& name) {
return false;
}
_setFocused(w);
_setFocused(w1);
return true;
}
bool Window::grabFocus() {
if(!_wm) return false;
return _wm->setFocused(this);
}
bool Window::setFirstFocusable() {
WidgetList focusList;
@@ -724,8 +781,6 @@ XYCoord Window::localXY(double absx, double absy) const {
double x = absx - xy.x();
double y = absy - xy.y();
if(_wm && _wm->isInvertedY()) y = (_wm->getHeight() - absy) - xy.y();
return XYCoord(x + _visibleArea[0], y + _visibleArea[1]);
}
@@ -746,13 +801,21 @@ XYCoord Window::getAbsoluteOrigin() const {
return xy;
}
Window::EmbeddedWindow* Window::embed() {
EmbeddedWindow* ew = new EmbeddedWindow(_name + "Embedded", getWidth(), getHeight());
Window::EmbeddedWindow* Window::embed(
const std::string& newName,
Widget::Layer layer,
unsigned int layerOffset
) {
EmbeddedWindow* ew = new EmbeddedWindow(
newName.size() > 0 ? newName : _name + "Embedded",
getWidth(),
getHeight()
);
ew->setWindow(this);
ew->setSize(getWidth(), getHeight());
ew->setMinimumSize(getMinWidth(), getMinHeight());
ew->setCanFill(true);
ew->setLayer(layer, layerOffset);
return ew;
}
@@ -779,7 +842,11 @@ bool Window::getEmbeddedList(WindowList& wl) const {
if(!ew || !ew->getWindow()) continue;
wl.push_back(ew->getWindow());
else {
wl.push_back(ew->getWindow());
ew->getWindow()->getEmbeddedList(wl);
}
}
return wl.size() != 0;
@@ -852,6 +919,12 @@ unsigned int Window::addDrawableAndGetIndex(osg::Drawable* drawable) {
return 0;
}
unsigned int Window::addChildAndGetIndex(osg::Node* node) {
if(addChild(node)) return getChildIndex(node);
return 0;
}
// All of the subsequent functions are very boring and uninteresting, although hopefully
// self-explanatory. They simply wrap calls to _compare<>() with the proper templates, and
// forward the optional iteration ranges...
@@ -945,7 +1018,7 @@ Window::Sizes Window::_getWidthImplementation() const {
point_type w = osg::round(bb.xMax() - bb.xMin());
return Sizes(w, w);
return Sizes(w, 0.0f);
}
Window::Sizes Window::_getHeightImplementation() const {
@@ -953,7 +1026,7 @@ Window::Sizes Window::_getHeightImplementation() const {
point_type h = osg::round(bb.yMax() - bb.yMin());
return Sizes(h, h);
return Sizes(h, 0.0f);
}
}

View File

@@ -23,8 +23,8 @@ WindowManager::WindowManager(
):
_width (width),
_height (height),
_zNear (0.0f),
_zFar (-1.0f),
_windowWidth (width),
_windowHeight (height),
_numForeground (0.0f),
_numBackground (0.0f),
_flags (flags),
@@ -56,6 +56,8 @@ _styleManager (new StyleManager()) {
if(!_python->initialize()) warn() << "Error creating PythonEngine." << std::endl;
}
if(_flags & WM_USE_RENDERBINS) getOrCreateStateSet()->setMode(GL_DEPTH_TEST, false);
// Setup our picking debug (is debug the right word here?) Window...
if(_flags & WM_PICK_DEBUG) {
_pickWindow = new Box("PickWindow", Box::VERTICAL);
@@ -79,28 +81,11 @@ _styleManager (new StyleManager()) {
_updatePickWindow(0, 0, 0);
}
if(!(_flags & WM_NO_BETA_WARN)) {
Box* box = new Box("BetaWarningBox", Box::VERTICAL);
Label* label = new Label("BetaWarning");
label->setFontSize(15);
label->setFontColor(0.0f, 0.0f, 1.0f, 1.0f);
label->setFont("fonts/arial.ttf");
label->setPadding(5.0f);
label->setCanFill(true);
label->setLabel("This is BETA software! Please see: http://osgwidget.googlecode.com");
box->getBackground()->setColor(1.0f, 0.7f, 0.0f, 1.0f);
box->addWidget(label);
box->setNodeMask(~_nodeMask);
box->removeEventMask(EVENT_MASK_FOCUS);
box->setStrata(Window::STRATA_BACKGROUND);
box->setOrigin(0.0f, 0.0f);
addChild(box);
box->resizePercent(100.0f, 0.0f);
}
getOrCreateStateSet()->setMode(
GL_BLEND,
osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE
);
getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
}
WindowManager::WindowManager(const WindowManager& wm, const osg::CopyOp& co):
@@ -140,7 +125,8 @@ bool WindowManager::_handleMousePushed(float x, float y, bool& down) {
if(!_lastPush) return false;
bool handled = _lastPush->callMethodAndCallbacks(ev);
// TODO: This is the old way; it didn't allow Event handler code to call grabFocus().
// bool handled = _lastPush->callMethodAndCallbacks(ev);
if(_focusMode != PFM_SLOPPY) {
if(ev._window) {
@@ -155,7 +141,7 @@ bool WindowManager::_handleMousePushed(float x, float y, bool& down) {
else if(_focusMode == PFM_UNFOCUS) setFocused(0);
}
return handled;
return _lastPush->callMethodAndCallbacks(ev);
}
bool WindowManager::_handleMouseReleased(float x, float y, bool& down) {
@@ -181,10 +167,7 @@ bool WindowManager::_handleMouseReleased(float x, float y, bool& down) {
void WindowManager::_getPointerXYDiff(float& x, float& y) {
x -= _lastX;
if(isInvertedY()) y = -(y - _lastY);
else y -= _lastY;
y -= _lastY;
}
void WindowManager::_updatePickWindow(const WidgetList* wl, point_type x, point_type y) {
@@ -299,9 +282,10 @@ bool WindowManager::pickAtXY(float x, float y, WidgetList& wl) {
// Make sure that our window is valid, and that our pick is within the
// "visible area" of the Window.
if(!win ||
(win->getVisibilityMode()==Window::VM_PARTIAL && !win->isPointerXYWithinVisible(x, y)))
{
if(
!win ||
(win->getVisibilityMode() == Window::VM_PARTIAL && !win->isPointerXYWithinVisible(x, y))
) {
continue;
}
@@ -334,6 +318,49 @@ bool WindowManager::pickAtXY(float x, float y, WidgetList& wl) {
return false;
}
/*
bool WindowManager::pickAtXY(float x, float y, WidgetList& wl) {
Intersections intr;
if(!_view->computeIntersections(x, y, intr, _nodeMask)) return false;
typedef std::vector<osg::observer_ptr<Window> > WindowVector;
WindowVector windows;
Window* activeWin = 0;
for(Intersections::iterator i = intr.begin(); i != intr.end(); i++) {
Window* win = dynamic_cast<Window*>(i->nodePath.back()->getParent(0));
if(
!win ||
(win->getVisibilityMode() == Window::VM_PARTIAL && !win->isPointerXYWithinVisible(x, y))
) {
continue;
}
if(activeWin != win) {
activeWin = win;
windows.push_back(win);
}
}
if(!windows.size()) return false;
std::sort(windows.begin(), windows.end(), WindowBinNumberCompare());
for(WindowVector::iterator i = windows.begin(); i != windows.end(); i++) {
warn() << "- " << i->get()->getName() << " " << i->get()->getOrCreateStateSet()->getBinNumber() << std::endl;
}
warn() << std::endl;
return false;
}
*/
bool WindowManager::setFocused(Window* window) {
Event ev(this);
@@ -371,7 +398,7 @@ bool WindowManager::setFocused(Window* window) {
// the Z space allocated to it so that it can properly arrange it's children. We
// add 2 additional Windows here for anything that should appear in the background
// and foreground areas.
matrix_type zRange = (_zNear - _zFar) / (focusable.size() + 2.0f);
matrix_type zRange = 1.0f / (focusable.size() + 2.0f);
// Our offset for the following for() loop.
unsigned int i = 3;
@@ -457,6 +484,16 @@ void WindowManager::resizeAllWindows(bool visible) {
}
}
// Returns the application window coordinates of the WindowManager XY position.
XYCoord WindowManager::windowXY(double x, double y) const {
return XYCoord((_windowWidth / _width) * x, (_windowHeight / _height) * y);
}
// Returns the WindowManager coordinates of the application window XY position.
XYCoord WindowManager::localXY(double x, double y) const {
return XYCoord((_width / _windowWidth) * x, (_height / _windowHeight) * y);
}
// This is called by a ViewerEventHandler/MouseHandler (or whatever) as the pointer moves
// around and intersects with objects. It also resets our state data (_widget, _leftDown,
// etc.) The return value of this method is mostly useless.
@@ -574,11 +611,7 @@ bool WindowManager::keyUp(int key, int mask) {
// A convenience wrapper for creating a proper orthographic camera using the current
// width and height.
osg::Camera* WindowManager::createParentOrthoCamera() {
osg::Camera* camera = 0;
if(isInvertedY()) camera = createInvertedYOrthoCamera(_width, _height);
else camera = createOrthoCamera(_width, _height);
osg::Camera* camera = createOrthoCamera(_width, _height);
camera->addChild(this);