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