From Jeremy Moles, updates to osgWidget
Merged my Robert Osfield from OpenSceneGraph-osgWidget-dev.
This commit is contained in:
@@ -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),
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user