From Jeremy Moles, import of the osgWidget NodeKit, sourced from the original http://osgwidget.googlecode.com/svn/trunk

Notes from Robert Osfield, I've merged osgWidget trunk, and added/changed CMakeLists.txt file to make it suitable for inclusion in the core OSG, and moved imagery/scripts/shaders out into OpenSceneGraph-Data
This commit is contained in:
Robert Osfield 2008-07-15 17:21:25 +00:00
parent 0c3d119cea
commit c2b77aa08e
77 changed files with 9643 additions and 15 deletions

View File

@ -149,6 +149,24 @@ IF(DYNAMIC_OPENSCENEGRAPH)
ADD_SUBDIRECTORY(osgviewerCocoa)
ENDIF(APPLE)
IF (BUILD_OSGWIDGET))
ADD_SUBDIRECTORY(osgwidgetaddremove)
ADD_SUBDIRECTORY(osgwidgetbox)
ADD_SUBDIRECTORY(osgwidgetcanvas)
ADD_SUBDIRECTORY(osgwidgetframe)
ADD_SUBDIRECTORY(osgwidgetinput)
ADD_SUBDIRECTORY(osgwidgetlabel)
ADD_SUBDIRECTORY(osgwidgetmenu)
ADD_SUBDIRECTORY(osgwidgetnotebook)
ADD_SUBDIRECTORY(osgwidgetscrolled)
ADD_SUBDIRECTORY(osgwidgetshader)
ADD_SUBDIRECTORY(osgwidgetstyled)
ADD_SUBDIRECTORY(osgwidgettable)
ADD_SUBDIRECTORY(osgwidgetversion)
ADD_SUBDIRECTORY(osgwidgetwindow
ENDIF(BUILD_OSGWIDGET)
#ADD_SUBDIRECTORY(osgcegui)
#to add subject to find socket#ADD_SUBDIRECTORY(osgcluster)

View File

@ -0,0 +1,9 @@
PROJECT(osgwidgetaddremove)
LINK_LIBRARIES(debug osgWidgetd optimized osgWidget)
ADD_EXECUTABLE(osgwidgetaddremove osgwidgetaddremove.cpp)
SET_TARGET_PROPERTIES(osgwidgetaddremove PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
INSTALL(TARGETS osgwidgetaddremove DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)

View File

@ -0,0 +1,134 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: osgwidgetaddremove.cpp 45 2008-04-23 16:46:11Z cubicool $
#include <osgWidget/Util>
#include <osgWidget/WindowManager>
#include <osgWidget/Table>
#include <osgWidget/Box>
#include <osgWidget/Label>
const unsigned int MASK_2D = 0xF0000000;
class ABCWidget: public osgWidget::Label {
public:
ABCWidget(const std::string& label):
osgWidget::Label("", label) {
setFont("fonts/Calibri1.ttf");
setFontSize(20);
setCanFill(true);
setShadow(0.08f);
addSize(10.0f, 10.0f);
}
};
class Button: public osgWidget::Label {
public:
Button(const std::string& label):
osgWidget::Label("", label) {
setFont("fonts/Calibri1.ttf");
setFontSize(30);
setColor(0.8f, 0.2f, 0.2f, 0.8f);
setCanFill(true);
setShadow(0.1f);
setEventMask(osgWidget::EVENT_MASK_MOUSE_CLICK);
addSize(20.0f, 20.0f);
}
// NOTE! I need to make it clearer than Push/Release can happen so fast that
// the changes you make aren't visible with your refresh rate. Throttling state
// changes and what-have-you on mousePush/mouseRelease/etc. is going to be
// annoying...
virtual bool mousePush(double, double, osgWidget::WindowManager*) {
addColor(0.2f, 0.2f, 0.2f, 0.0f);
return true;
}
virtual bool mouseRelease(double, double, osgWidget::WindowManager*) {
addColor(-0.2f, -0.2f, -0.2f, 0.0f);
return true;
}
};
class AddRemove: public osgWidget::Box {
osg::ref_ptr<osgWidget::Window> _win1;
public:
AddRemove():
osgWidget::Box ("buttons", osgWidget::Box::VERTICAL),
_win1 (new osgWidget::Box("win1", osgWidget::Box::VERTICAL)) {
addWidget(new Button("Add Widget"));
addWidget(new Button("Remove Widget"));
// Take special note here! Not only do the Button objects have their
// own overridden methods for changing the color, but they have attached
// callbacks for doing the work with local data.
getByName("Widget_1")->addCallback(osgWidget::Callback(
&AddRemove::handlePressAdd,
this,
osgWidget::EVENT_MOUSE_PUSH
));
getByName("Widget_2")->addCallback(osgWidget::Callback(
&AddRemove::handlePressRemove,
this,
osgWidget::EVENT_MOUSE_PUSH
));
}
virtual void managed(osgWidget::WindowManager* wm) {
osgWidget::Box::managed(wm);
_win1->setOrigin(250.0f, 0.0f);
wm->addChild(_win1.get());
}
bool handlePressAdd(osgWidget::Event& ev) {
static unsigned int num = 0;
std::stringstream ss;
ss << "a random widget " << num;
_win1->addWidget(new ABCWidget(ss.str()));
_win1->resize();
num++;
return true;
}
bool handlePressRemove(osgWidget::Event& ev) {
// TODO: Temporary hack!
const osgWidget::Box::Vector& v = _win1->getObjects();
if(!v.size()) return false;
osgWidget::Widget* w = _win1->getObjects()[v.size() - 1].get();
_win1->removeWidget(w);
_win1->resize();
return true;
}
};
int main(int argc, char** argv) {
osgViewer::Viewer viewer;
osgWidget::WindowManager* wm = new osgWidget::WindowManager(
&viewer,
1280.0f,
1024.0f,
MASK_2D
);
osgWidget::Box* buttons = new AddRemove();
wm->addChild(buttons);
return createExample(viewer, wm);
}

View File

@ -0,0 +1,9 @@
PROJECT(osgwidgetbox)
LINK_LIBRARIES(debug osgWidgetd optimized osgWidget)
ADD_EXECUTABLE(osgwidgetbox osgwidgetbox.cpp)
SET_TARGET_PROPERTIES(osgwidgetbox PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
INSTALL(TARGETS osgwidgetbox DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)

View File

@ -0,0 +1,122 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: osgwidgetbox.cpp 59 2008-05-15 20:55:31Z cubicool $
// NOTE: You'll find this example very similar to osgwidgetwindow. However, here we
// demonstrate a bit of subclassing of Widget so that we can respond to events
// such as mouseEnter and mouseLeave. We also demonstrate the use of padding, though
// fill and alignment should be working too.
#include <osg/io_utils>
#include <osgDB/ReadFile>
#include <osgWidget/Util>
#include <osgWidget/WindowManager>
#include <osgWidget/Box>
const unsigned int MASK_2D = 0xF0000000;
const unsigned int MASK_3D = 0x0F000000;
struct ColorWidget: public osgWidget::Widget {
ColorWidget():
osgWidget::Widget("", 256.0f, 256.0f) {
}
bool mouseEnter(double, double, osgWidget::WindowManager*) {
addColor(-osgWidget::Color(0.4f, 0.4f, 0.4f, 0.0f));
// osgWidget::warn() << "enter: " << getColor() << std::endl;
return true;
}
bool mouseLeave(double, double, osgWidget::WindowManager*) {
addColor(osgWidget::Color(0.4f, 0.4f, 0.4f, 0.0f));
// osgWidget::warn() << "leave: " << getColor() << std::endl;
return true;
}
bool mouseOver(double x, double y, osgWidget::WindowManager*) {
osgWidget::Color c = getImageColorAtPointerXY(x, y);
if(c.a() < 0.001f) {
// osgWidget::warn() << "Transparent Pixel: " << x << " " << y << std::endl;
return false;
}
return true;
}
bool keyUp(int key, int keyMask, osgWidget::WindowManager*) {
// osgWidget::warn() << "..." << key << " - " << keyMask << std::endl;
return true;
}
};
osgWidget::Box* createBox(const std::string& name, osgWidget::Box::BOX_TYPE bt) {
osgWidget::Box* box = new osgWidget::Box(name, bt, true);
osgWidget::Widget* widget1 = new osgWidget::Widget(name + "_widget1", 100.0f, 100.0f);
osgWidget::Widget* widget2 = new osgWidget::Widget(name + "_widget2", 100.0f, 100.0f);
osgWidget::Widget* widget3 = new ColorWidget();
widget1->setColor(0.3f, 0.3f, 0.3f, 1.0f);
widget2->setColor(0.6f, 0.6f, 0.6f, 1.0f);
widget3->setImage("osgWidget/natascha.png");
widget3->setTexCoord(0.0f, 0.0f, osgWidget::Widget::LOWER_LEFT);
widget3->setTexCoord(1.0f, 0.0f, osgWidget::Widget::LOWER_RIGHT);
widget3->setTexCoord(1.0f, 1.0f, osgWidget::Widget::UPPER_RIGHT);
widget3->setTexCoord(0.0f, 1.0f, osgWidget::Widget::UPPER_LEFT);
box->addWidget(widget1);
box->addWidget(widget2);
box->addWidget(widget3);
return box;
}
int main(int argc, char** argv) {
osgViewer::CompositeViewer viewer;
osgViewer::View* view = new osgViewer::View();
osgWidget::WindowManager* wm = new osgWidget::WindowManager(
view,
1280.0f,
1024.0f,
MASK_2D,
osgWidget::WindowManager::WM_PICK_DEBUG |
osgWidget::WindowManager::WM_NO_INVERT_Y
);
wm->setPointerFocusMode(osgWidget::WindowManager::PFM_SLOPPY);
osgWidget::Window* box1 = createBox("HBOX", osgWidget::Box::HORIZONTAL);
osgWidget::Window* box2 = createBox("VBOX", osgWidget::Box::VERTICAL);
osgWidget::Window* box3 = createBox("HBOX2", osgWidget::Box::HORIZONTAL);
osgWidget::Window* box4 = createBox("VBOX2", osgWidget::Box::VERTICAL);
box1->getBackground()->setColor(1.0f, 0.0f, 0.0f, 0.8f);
box1->attachMoveCallback();
box2->getBackground()->setColor(0.0f, 1.0f, 0.0f, 0.8f);
box2->attachMoveCallback();
box3->getBackground()->setColor(0.0f, 0.0f, 1.0f, 0.8f);
box3->attachMoveCallback();
wm->addChild(box1);
wm->addChild(box2);
wm->addChild(box3);
wm->addChild(box4);
box4->hide();
osg::Node* model = osgDB::readNodeFile("spaceship.osg");
model->setNodeMask(MASK_3D);
return osgWidget::createCompositeExample(viewer, view, wm, model);
}

View File

@ -0,0 +1,9 @@
PROJECT(osgwidgetcanvas)
LINK_LIBRARIES(debug osgWidgetd optimized osgWidget)
ADD_EXECUTABLE(osgwidgetcanvas osgwidgetcanvas.cpp)
SET_TARGET_PROPERTIES(osgwidgetcanvas PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
INSTALL(TARGETS osgwidgetcanvas DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)

View File

@ -0,0 +1,118 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: osgwidgetcanvas.cpp 33 2008-04-04 19:03:12Z cubicool $
#include <osgWidget/Util>
#include <osgWidget/WindowManager>
#include <osgWidget/Canvas>
const unsigned int MASK_2D = 0xF0000000;
bool colorWidgetEnter(osgWidget::Event& event) {
event.getWidget()->addColor(0.5f, 0.2f, 0.3f, 0.0f);
// osgWidget::warn() << "WIDGET mouseEnter " << event.getWidget()->getName() << std::endl;
return true;
}
bool colorWidgetLeave(osgWidget::Event& event) {
event.getWidget()->addColor(-0.5f, -0.2f, -0.3f, 0.0f);
// osgWidget::warn() << "WIDGET mouseLeave" << std::endl;
return true;
}
bool windowMouseOver(osgWidget::Event& event) {
osgWidget::XYCoord xy = event.getWindow()->localXY(event.x, event.y);
// osgWidget::warn() << "WINDOW " << xy.x() << " - " << xy.y() << std::endl;
return true;
}
bool widgetMouseOver(osgWidget::Event& event) {
osgWidget::XYCoord xy = event.getWidget()->localXY(event.x, event.y);
// osgWidget::warn() << "WIDGET mouseOver " << xy.x() << " - " << xy.y() << std::endl;
return true;
}
osgWidget::Widget* createWidget(
const std::string& name,
osgWidget::color_type col,
osgWidget::Widget::LAYER layer
) {
osgWidget::Widget* widget = new osgWidget::Widget(name, 200.0f, 200.0f);
widget->setEventMask(osgWidget::EVENT_ALL);
widget->addCallback(osgWidget::Callback(&colorWidgetEnter, osgWidget::EVENT_MOUSE_PUSH));
widget->addCallback(osgWidget::Callback(&colorWidgetLeave, osgWidget::EVENT_MOUSE_RELEASE));
widget->addCallback(osgWidget::Callback(&colorWidgetEnter, osgWidget::EVENT_MOUSE_ENTER));
widget->addCallback(osgWidget::Callback(&colorWidgetLeave, osgWidget::EVENT_MOUSE_LEAVE));
widget->addCallback(osgWidget::Callback(&widgetMouseOver, osgWidget::EVENT_MOUSE_OVER));
widget->setColor(col, col, col, 0.5f);
widget->setLayer(layer);
return widget;
}
int main(int argc, char** argv) {
osgViewer::Viewer viewer;
osgWidget::WindowManager* wm = new osgWidget::WindowManager(
&viewer,
1280.0f,
1024.0f,
MASK_2D,
osgWidget::WindowManager::WM_PICK_DEBUG
);
osgWidget::Canvas* canvas = new osgWidget::Canvas("canvas");
canvas->addCallback(osgWidget::Callback(&windowMouseOver, osgWidget::EVENT_MOUSE_OVER));
canvas->attachMoveCallback();
canvas->attachRotateCallback();
canvas->attachScaleCallback();
canvas->addWidget(
createWidget("w1", 0.2f, osgWidget::Widget::LAYER_LOW),
0.0f,
0.0f
);
canvas->addWidget(
createWidget("w2", 0.4f, osgWidget::Widget::LAYER_MIDDLE),
200.0f,
0.0f
);
canvas->addWidget(
createWidget("w3", 0.6f, osgWidget::Widget::LAYER_HIGH),
400.0f,
0.0f
);
// Add a child and then resize it relatively to the size of the parent Window.
osgWidget::Widget* relWidget = new osgWidget::Widget("relative");
relWidget->setLayer(osgWidget::Widget::LAYER_LOW, 1);
relWidget->setCoordinateMode(osgWidget::Widget::CM_RELATIVE);
relWidget->setSize(0.2f, 0.2f);
relWidget->setColor(0.5f, 0.5f, 0.1f, 0.9f);
osgWidget::warn() << canvas->getWidth() << std::endl;
canvas->addWidget(relWidget, 0.4f, 0.4f);
relWidget->addOrigin(0.1f, 0.1f);
relWidget->addSize(0.2f, 0.2f);
canvas->resize();
// Finally, add the whole thing to the WindowManager.
wm->addChild(canvas);
return osgWidget::createExample(viewer, wm);
}

View File

@ -0,0 +1,9 @@
PROJECT(osgwidgetframe)
LINK_LIBRARIES(debug osgWidgetd optimized osgWidget)
ADD_EXECUTABLE(osgwidgetframe osgwidgetframe.cpp)
SET_TARGET_PROPERTIES(osgwidgetframe PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
INSTALL(TARGETS osgwidgetframe DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)

View File

@ -0,0 +1,89 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: osgwidgetframe.cpp 40 2008-04-11 14:05:11Z cubicool $
#include <osgWidget/Util>
#include <osgWidget/WindowManager>
#include <osgWidget/Frame>
#include <osgWidget/Box>
const unsigned int MASK_2D = 0xF0000000;
int main(int argc, char** argv) {
osgViewer::Viewer viewer;
osgWidget::WindowManager* wm = new osgWidget::WindowManager(
&viewer,
1280.0f,
1024.0f,
MASK_2D,
osgWidget::WindowManager::WM_PICK_DEBUG
);
osgWidget::Frame* frame = osgWidget::Frame::createSimpleFrame(
"frame",
32.0f,
32.0f,
300.0f,
300.0f
);
osgWidget::Table* table = new osgWidget::Table("table", 2, 2);
osgWidget::Box* bottom = new osgWidget::Box("panel", osgWidget::Box::HORIZONTAL);
table->addWidget(new osgWidget::Widget("red", 300.0f, 300.0f), 0, 0);
table->addWidget(new osgWidget::Widget("white", 300.0f, 300.0f), 0, 1);
table->addWidget(new osgWidget::Widget("yellow", 300.0f, 300.0f), 1, 0);
table->addWidget(new osgWidget::Widget("purple", 300.0f, 300.0f), 1, 1);
table->getByRowCol(0, 0)->setColor(1.0f, 0.0f, 0.0f, 1.0f);
table->getByRowCol(0, 1)->setColor(1.0f, 1.0f, 1.0f, 1.0f);
table->getByRowCol(1, 0)->setColor(1.0f, 1.0f, 0.0f, 1.0f);
table->getByRowCol(1, 1)->setColor(1.0f, 0.0f, 1.0f, 1.0f);
table->getByRowCol(0, 0)->setMinimumSize(100.0f, 100.0f);
table->getByRowCol(0, 1)->setMinimumSize(100.0f, 100.0f);
table->getByRowCol(1, 0)->setMinimumSize(100.0f, 100.0f);
table->getByRowCol(1, 1)->setMinimumSize(100.0f, 100.0f);
frame->setWindow(table);
// Give frame some nice textures.
// TODO: This has to be done after setWindow(); wtf?
frame->getBackground()->setColor(0.0f, 0.0f, 0.0f, 0.0f);
osgWidget::Widget* l = frame->getBorder(osgWidget::Frame::BORDER_LEFT);
osgWidget::Widget* r = frame->getBorder(osgWidget::Frame::BORDER_RIGHT);
osgWidget::Widget* t = frame->getBorder(osgWidget::Frame::BORDER_TOP);
osgWidget::Widget* b = frame->getBorder(osgWidget::Frame::BORDER_BOTTOM);
l->setImage("../examples/osgwidgetframe/images/border-left.tga", true);
r->setImage("../examples/osgwidgetframe/images/border-right.tga", true);
t->setImage("../examples/osgwidgetframe/images/border-top.tga", true);
b->setImage("../examples/osgwidgetframe/images/border-bottom.tga", true);
l->setTexCoordWrapVertical();
r->setTexCoordWrapVertical();
t->setTexCoordWrapHorizontal();
b->setTexCoordWrapHorizontal();
// Create the bottom, XArt panel.
osgWidget::Widget* left = new osgWidget::Widget("left", 512.0f, 256.0f);
osgWidget::Widget* center = new osgWidget::Widget("center", 256.0f, 256.0f);
osgWidget::Widget* right = new osgWidget::Widget("right", 512.0f, 256.0f);
left->setImage("../examples/osgwidgetframe/images/panel-left.tga", true);
center->setImage("../examples/osgwidgetframe/images/panel-center.tga", true);
right->setImage("../examples/osgwidgetframe/images/panel-right.tga", true);
center->setTexCoordWrapHorizontal();
bottom->addWidget(left);
bottom->addWidget(center);
bottom->addWidget(right);
bottom->getBackground()->setColor(0.0f, 0.0f, 0.0f, 0.0f);
bottom->setOrigin(0.0f, 1024.0f - 256.0f);
// Add everything to the WindowManager.
wm->addChild(frame);
wm->addChild(bottom);
return osgWidget::createExample(viewer, wm);
}

View File

@ -0,0 +1,9 @@
PROJECT(osgwidgetinput)
LINK_LIBRARIES(debug osgWidgetd optimized osgWidget)
ADD_EXECUTABLE(osgwidgetinput osgwidgetinput.cpp)
SET_TARGET_PROPERTIES(osgwidgetinput PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
INSTALL(TARGETS osgwidgetinput DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)

View File

@ -0,0 +1,186 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: osgwidgetinput.cpp 50 2008-05-06 05:06:36Z cubicool $
#include <osgDB/WriteFile>
#include <osgWidget/Util>
#include <osgWidget/WindowManager>
#include <osgWidget/Box>
#include <osgWidget/Table>
#include <osgWidget/Frame>
#include <osgWidget/Label>
#include <osgWidget/Input>
const unsigned int MASK_2D = 0xF0000000;
const char* INFO =
"Use the Input Wigets below to enter the X, Y, and Z position of a\n"
"sphere to be inserted into the scene. Once you've done this, use\n"
"the button below to add it!"
;
void setupLabel(osgWidget::Label* label) {
label->setFontSize(16);
label->setFontColor(1.0f, 1.0f, 1.0f, 1.0f);
// label->setFont("fonts/monospace.ttf");
label->setFont("fonts/Calibri1.ttf");
label->setPadding(2.0f);
label->setHeight(18.0f);
label->setCanFill(true);
}
osgWidget::Input* createTableRow(
osgWidget::Table* table,
unsigned int rowNum,
const std::string& valName
) {
std::stringstream ssLabel;
std::stringstream ssInput;
ssLabel << "Label_Row" << rowNum;
ssInput << "Input_Row" << rowNum;
osgWidget::Label* label = new osgWidget::Label(ssLabel.str(), valName);
osgWidget::Input* input = new osgWidget::Input(ssInput.str(), "", 20);
setupLabel(label);
setupLabel(input);
label->setWidth(50.0f);
label->setColor(0.1f, 0.1f, 0.1f, 1.0f);
input->setWidth(150.0f);
input->setColor(0.4f, 0.4f, 0.4f, 1.0f);
table->addWidget(label, rowNum, 0);
table->addWidget(input, rowNum, 1);
return input;
}
osgWidget::Label* createLabel(const std::string& text) {
osgWidget::Label* label = new osgWidget::Label("", text);
setupLabel(label);
return label;
}
class Button: public osgWidget::Label {
public:
typedef std::vector<osgWidget::Input*> Inputs;
private:
Inputs _xyz;
public:
Button(const std::string& text, const Inputs& inputs):
osgWidget::Label("", text),
_xyz(inputs) {
setupLabel(this);
setEventMask(osgWidget::EVENT_MASK_MOUSE_CLICK);
setShadow(0.1f);
addHeight(4.0f);
}
bool mousePush(double, double, osgWidget::WindowManager*) {
osgWidget::warn()
<< "x: " << _xyz[0]->getLabel() << std::endl
<< "y: " << _xyz[1]->getLabel() << std::endl
<< "z: " << _xyz[2]->getLabel() << std::endl
;
return false;
}
};
// TODO: Testing our _parent/EmbeddedWindow stuff.
bool info(osgWidget::Event& ev) {
osgWidget::warn() << "MousePush @ Window: " << ev.getWindow()->getName() << std::endl;
return true;
}
int main(int argc, char** argv) {
osgViewer::Viewer viewer;
osgWidget::WindowManager* wm = new osgWidget::WindowManager(
&viewer,
1280.0f,
1024.0f,
MASK_2D,
osgWidget::WindowManager::WM_PICK_DEBUG
);
osgWidget::Box* box = new osgWidget::Box("vbox", osgWidget::Box::VERTICAL);
osgWidget::Table* table = new osgWidget::Table("table", 3, 2);
osgWidget::Box* lbox1 = new osgWidget::Box("lbox1", osgWidget::Box::HORIZONTAL);
osgWidget::Box* lbox2 = new osgWidget::Box("lbox2", osgWidget::Box::HORIZONTAL);
osgWidget::Frame* frame = osgWidget::Frame::createSimpleFrameWithSingleTexture(
"frame",
"osgWidget/theme.png",
64.0f,
64.0f,
16.0f,
16.0f,
100.0f,
100.0f
);
osgWidget::Input* x = createTableRow(table, 0, "X Position");
osgWidget::Input* y = createTableRow(table, 1, "Y Position");
osgWidget::Input* z = createTableRow(table, 2, "Z Position");
Button::Inputs inputs;
inputs.push_back(x);
inputs.push_back(y);
inputs.push_back(z);
table->addCallback(osgWidget::Callback(&info, osgWidget::EVENT_MOUSE_PUSH));
lbox1->addWidget(createLabel(INFO));
lbox2->addWidget(new Button("Add To Scene...", inputs));
box->addWidget(lbox1->embed());
box->addWidget(table->embed());
box->addWidget(lbox2->embed());
box->addCallback(osgWidget::Callback(&info, osgWidget::EVENT_MOUSE_PUSH));
frame->setWindow(box);
frame->getEmbeddedWindow()->setSize(box->getWidth(), box->getHeight());
frame->getBackground()->setColor(0.0f, 0.0f, 0.0f, 0.0f);
frame->attachTabFocusCallback();
for(osgWidget::Frame::Iterator i = frame->begin(); i != frame->end(); i++) {
if(i->valid()) i->get()->setColor(0.5f, 0.7f, 1.0f, 1.0f);
}
wm->addChild(frame);
/*
// Print out our focus list, it should just have 3 widgets.
osgWidget::WidgetList wl;
box->getFocusList(wl);
for(osgWidget::WidgetList::iterator i = wl.begin(); i != wl.end(); i++) {
osgWidget::warn() << i->get()->getName() << std::endl;
}
*/
lbox1->getBackground()->setColor(1.0f, 0.0f, 0.0f, 1.0f, osgWidget::Widget::UPPER_LEFT);
lbox1->getBackground()->setColor(0.0f, 1.0f, 0.0f, 1.0f, osgWidget::Widget::LOWER_LEFT);
lbox1->getBackground()->setColor(0.0f, 0.0f, 1.0f, 1.0f, osgWidget::Widget::LOWER_RIGHT);
lbox1->getBackground()->setColor(1.0f, 1.0f, 1.0f, 1.0f, osgWidget::Widget::UPPER_RIGHT);
lbox1->setVisibilityMode(osgWidget::Window::VM_ENTIRE);
lbox1->update();
int r = osgWidget::createExample(viewer, wm);
// osgWidget::writeWindowManagerNode(wm);
// osgDB::writeNodeFile(*box, "osgWidget.osg");
return r;
}

View File

@ -0,0 +1,9 @@
PROJECT(osgwidgetlabel)
LINK_LIBRARIES(debug osgWidgetd optimized osgWidget)
ADD_EXECUTABLE(osgwidgetlabel osgwidgetlabel.cpp)
SET_TARGET_PROPERTIES(osgwidgetlabel PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
INSTALL(TARGETS osgwidgetlabel DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)

View File

@ -0,0 +1,120 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: osgwidgetlabel.cpp 66 2008-07-14 21:54:09Z cubicool $
#include <osg/io_utils>
#include <osgWidget/Util>
#include <osgWidget/WindowManager>
#include <osgWidget/Box>
#include <osgWidget/Label>
const unsigned int MASK_2D = 0xF0000000;
const char* LABEL1 =
"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed\n"
"do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n"
"Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris\n"
"nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in..."
;
const char* LABEL2 =
"...reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla\n"
"pariatur. Excepteur sint occaecat cupidatat non proident, sunt in \n"
"culpa qui officia deserunt mollit anim id est laborum. BBBBB"
;
osgWidget::Label* createLabel(const std::string& l, unsigned int size=13) {
osgWidget::Label* label = new osgWidget::Label("", "");
label->setFont("fonts/arial.ttf");
label->setFontSize(size);
label->setFontColor(1.0f, 1.0f, 1.0f, 1.0f);
label->setLabel(l);
/*
text->setBackdropType(osgText::Text::DROP_SHADOW_BOTTOM_RIGHT);
text->setBackdropImplementation(osgText::Text::NO_DEPTH_BUFFER);
text->setBackdropOffset(0.2f);
*/
return label;
}
int main(int argc, char** argv) {
osgViewer::Viewer viewer;
osgWidget::WindowManager* wm = new osgWidget::WindowManager(
&viewer,
1280.0f,
1024.0f,
MASK_2D,
osgWidget::WindowManager::WM_PICK_DEBUG |
osgWidget::WindowManager::WM_NO_INVERT_Y
);
osgWidget::Box* box = new osgWidget::Box("HBOX", osgWidget::Box::HORIZONTAL);
osgWidget::Box* vbox = new osgWidget::Box("vbox", osgWidget::Box::VERTICAL);
osgWidget::Label* label1 = createLabel(LABEL1);
osgWidget::Label* label2 = createLabel(LABEL2);
// Setup the labels for horizontal box.
label1->setPadding(10.0f);
label2->setPadding(10.0f);
label1->addSize(21.0f, 22.0f);
label2->addSize(21.0f, 22.0f);
label1->setColor(1.0f, 0.5f, 0.0f, 0.0f);
label2->setColor(1.0f, 0.5f, 0.0f, 0.0f);
box->addWidget(label1);
box->addWidget(label2);
box->attachMoveCallback();
box->attachScaleCallback();
box->attachRotateCallback();
// Setup the labels for the vertical box.
osgWidget::Label* label3 = createLabel("Label 3", 80);
osgWidget::Label* label4 = createLabel("Label 4", 60);
osgWidget::Label* label5 = createLabel("ABCDEFGHIJK", 93);
label3->setPadding(3.0f);
label4->setPadding(3.0f);
label5->setPadding(3.0f);
label3->setColor(0.0f, 0.0f, 0.5f, 0.5f);
label4->setColor(0.0f, 0.0f, 0.5f, 0.5f);
label5->setColor(0.0f, 0.0f, 0.5f, 0.5f);
label5->setAlignHorizontal(osgWidget::Widget::HA_LEFT);
label5->setAlignVertical(osgWidget::Widget::VA_BOTTOM);
// Test our label copy construction...
osgWidget::Label* label6 = label5->cloneAs("label6");
label6->setLabel("abcdefghijklmnopqrs");
vbox->addWidget(label3);
vbox->addWidget(label4);
vbox->addWidget(label5);
vbox->addWidget(label6);
vbox->attachMoveCallback();
vbox->attachScaleCallback();
vbox->resize();
// vbox->setVisibilityMode(osgWidget::Window::VM_ENTIRE);
// vbox->setVisibleArea(50, 50, 500, 200);
// vbox->setAnchorVertical(osgWidget::Window::VA_TOP);
// vbox->setAnchorHorizontal(osgWidget::Window::HA_RIGHT);
// Test our label-in-window copy construction...
osgWidget::Box* clonedBox = box->cloneAs("HBOX-new");
clonedBox->getBackground()->setColor(0.0f, 1.0f, 0.0f, 0.5f);
wm->addChild(box);
wm->addChild(vbox);
wm->addChild(clonedBox);
return osgWidget::createExample(viewer, wm);
}

View File

@ -0,0 +1,9 @@
PROJECT(osgwidgetmenu)
LINK_LIBRARIES(debug osgWidgetd optimized osgWidget)
ADD_EXECUTABLE(osgwidgetmenu osgwidgetmenu.cpp)
SET_TARGET_PROPERTIES(osgwidgetmenu PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
INSTALL(TARGETS osgwidgetmenu DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)

View File

@ -0,0 +1,129 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: osgwidgetmenu.cpp 66 2008-07-14 21:54:09Z cubicool $
#include <iostream>
#include <osgDB/ReadFile>
#include <osgWidget/Util>
#include <osgWidget/WindowManager>
#include <osgWidget/Box>
#include <osgWidget/Label>
// For now this is just an example, but osgWidget::Menu will later be it's own Window.
// I just wanted to get this out there so that people could see it was possible.
const unsigned int MASK_2D = 0xF0000000;
const unsigned int MASK_3D = 0x0F000000;
struct ColorLabel: public osgWidget::Label {
ColorLabel(const char* label):
osgWidget::Label("", "") {
setFont("fonts/Calibri1.ttf");
setFontSize(14);
setFontColor(1.0f, 1.0f, 1.0f, 1.0f);
setColor(0.3f, 0.3f, 0.3f, 1.0f);
addHeight(18.0f);
setCanFill(true);
setLabel(label);
setEventMask(osgWidget::EVENT_MOUSE_PUSH | osgWidget::EVENT_MASK_MOUSE_MOVE);
}
bool mousePush(double, double, osgWidget::WindowManager*) {
return true;
}
bool mouseEnter(double, double, osgWidget::WindowManager*) {
setColor(0.6f, 0.6f, 0.6f, 1.0f);
return true;
}
bool mouseLeave(double, double, osgWidget::WindowManager*) {
setColor(0.3f, 0.3f, 0.3f, 1.0f);
return true;
}
};
class ColorLabelMenu: public ColorLabel {
osg::ref_ptr<osgWidget::Window> _window;
public:
ColorLabelMenu(const char* label):
ColorLabel(label) {
_window = new osgWidget::Box(
std::string("Menu_") + label,
osgWidget::Box::VERTICAL,
true
);
_window->addWidget(new ColorLabel("Open Some Stuff"));
_window->addWidget(new ColorLabel("Do It Now"));
_window->addWidget(new ColorLabel("Hello, How Are U?"));
_window->addWidget(new ColorLabel("Hmmm..."));
_window->addWidget(new ColorLabel("Option 5"));
_window->resize();
setColor(0.8f, 0.8f, 0.8f, 0.8f);
}
void managed(osgWidget::WindowManager* wm) {
osgWidget::Label::managed(wm);
wm->addChild(_window.get());
_window->hide();
}
void positioned() {
osgWidget::Label::positioned();
_window->setOrigin(getX(), getHeight());
_window->resize(getWidth());
}
bool mousePush(double, double, osgWidget::WindowManager*) {
if(!_window->isVisible()) _window->show();
else _window->hide();
return true;
}
bool mouseLeave(double, double, osgWidget::WindowManager*) {
if(!_window->isVisible()) setColor(0.8f, 0.8f, 0.8f, 0.8f);
return true;
}
};
int main(int argc, char** argv) {
osgViewer::Viewer viewer;
osgWidget::WindowManager* wm = new osgWidget::WindowManager(
&viewer,
1280.0f,
1024.0f,
MASK_2D,
osgWidget::WindowManager::WM_PICK_DEBUG |
osgWidget::WindowManager::WM_NO_BETA_WARN
);
osgWidget::Window* menu = new osgWidget::Box("menu", osgWidget::Box::HORIZONTAL);
menu->addWidget(new ColorLabelMenu("Pick me!"));
menu->addWidget(new ColorLabelMenu("No, wait, pick me!"));
menu->addWidget(new ColorLabelMenu("Dont pick them..."));
menu->addWidget(new ColorLabelMenu("Grarar!?!"));
wm->addChild(menu);
menu->getBackground()->setColor(1.0f, 1.0f, 1.0f, 0.0f);
menu->resizePercent(100.0f);
osg::Node* model = osgDB::readNodeFile("osgcool.osg");
model->setNodeMask(MASK_3D);
return osgWidget::createExample(viewer, wm, model);
}

View File

@ -0,0 +1,9 @@
PROJECT(osgwidgetnotebook)
LINK_LIBRARIES(debug osgWidgetd optimized osgWidget)
ADD_EXECUTABLE(osgwidgetnotebook osgwidgetnotebook.cpp)
SET_TARGET_PROPERTIES(osgwidgetnotebook PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
INSTALL(TARGETS osgwidgetnotebook DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)

View File

@ -0,0 +1,134 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: osgwidgetnotebook.cpp 45 2008-04-23 16:46:11Z cubicool $
#include <osg/io_utils>
#include <osgWidget/Util>
#include <osgWidget/WindowManager>
#include <osgWidget/Box>
#include <osgWidget/Canvas>
#include <osgWidget/Label>
const unsigned int MASK_2D = 0xF0000000;
const unsigned int MASK_3D = 0x0F000000;
class Notebook: public osgWidget::Box {
osg::ref_ptr<osgWidget::Box> _tabs;
osg::ref_ptr<osgWidget::Canvas> _windows;
public:
// NOTE: This whole thing is just a hack to demonstrate a concept. The real
// implementation would need to be much cleaner.
bool callbackTabPressed(osgWidget::Event& ev) {
osgWidget::Canvas::Vector& objs = _windows->getObjects();
for(unsigned int i = 0; i < objs.size(); i++) objs[i]->setLayer(
osgWidget::Widget::LAYER_MIDDLE,
i
);
_windows->getByName(ev.getWidget()->getName())->setLayer(
osgWidget::Widget::LAYER_MIDDLE,
objs.size()
);
_windows->resize();
return true;
}
Notebook(const std::string& name):
osgWidget::Box(name, osgWidget::Box::VERTICAL) {
_tabs = new osgWidget::Box("tabs", osgWidget::Box::HORIZONTAL);
_windows = new osgWidget::Canvas("canvas");
for(unsigned int i = 0; i < 4; i++) {
std::stringstream ss;
// Setup everything for our Tab...
ss << "Tab_" << i;
osgWidget::Label* label1 = new osgWidget::Label(ss.str());
label1->setFont("fonts/monospace.ttf");
label1->setFontSize(20);
label1->setFontColor(1.0f, 1.0f, 1.0f, 1.0f);
label1->setColor(0.0f, i / 4.0f, 0.3f, 1.0f);
label1->setLabel(ss.str());
label1->addSize(20.0f, 20.0f);
label1->setShadow(0.1f);
label1->setCanFill(true);
_tabs->addWidget(label1);
// Setup everything for the Window corresponding to the Tab
// in the Canvas down below.
std::stringstream descr;
descr
<< "This is some text" << std::endl
<< "for the Tab_" << i << " tab." << std::endl
<< "Press the button up top" << std::endl
<< "And this should go to the next Window!" << std::endl
;
osgWidget::Label* label2 = new osgWidget::Label(ss.str());
label2->setFont("fonts/monospace.ttf");
label2->setFontSize(15);
label2->setFontColor(1.0f, 1.0f, 1.0f, 1.0f);
label2->setColor(0.0f, i / 4.0f, 0.3f, 1.0f);
label2->setLabel(descr.str());
label2->setLayer(osgWidget::Widget::LAYER_MIDDLE, i);
label2->addSize(50.0f, 50.0f);
_windows->addWidget(label2, 0.0f, 0.0f);
label1->setEventMask(osgWidget::EVENT_MOUSE_PUSH);
label1->addCallback(osgWidget::Callback(
&Notebook::callbackTabPressed,
this,
osgWidget::EVENT_MOUSE_PUSH
));
}
osgWidget::Label* label = new osgWidget::Label("label");
label->setFont("fonts/monospace.ttf");
label->setFontSize(15);
label->setFontColor(1.0f, 1.0f, 1.0f, 1.0f);
label->setLabel("Drag the window here...");
label->addSize(20.0f, 20.0f);
label->setShadow(0.08f);
label->setCanFill(true);
addWidget(label);
addWidget(_tabs->embed());
addWidget(_windows->embed());
}
};
int main(int argc, char** argv) {
osgViewer::Viewer viewer;
osgWidget::WindowManager* wm = new osgWidget::WindowManager(
&viewer,
1280.0f,
720.0f,
MASK_2D,
osgWidget::WindowManager::WM_PICK_DEBUG
);
Notebook* notebook = new Notebook("notebook");
osgWidget::warn()
<< "Sizes are..." << std::endl
<< "Cur: " << notebook->getSize() << std::endl
<< "Min: " << notebook->getMinSize() << std::endl
;
notebook->attachMoveCallback();
wm->addChild(notebook);
return osgWidget::createExample(viewer, wm);
}

View File

@ -0,0 +1,9 @@
PROJECT(osgwidgetscrolled)
LINK_LIBRARIES(debug osgWidgetd optimized osgWidget)
ADD_EXECUTABLE(osgwidgetscrolled osgwidgetscrolled.cpp)
SET_TARGET_PROPERTIES(osgwidgetscrolled PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
INSTALL(TARGETS osgwidgetscrolled DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)

View File

@ -0,0 +1,134 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: osgwidgetframe.cpp 34 2008-04-07 03:12:41Z cubicool $
#include <osgWidget/Util>
#include <osgWidget/WindowManager>
#include <osgWidget/Frame>
#include <osgWidget/Box>
const unsigned int MASK_2D = 0xF0000000;
// NOTE: THIS IS JUST A TEMPORARY HACK! :) This functionality will all eventually be
// encapsulate into another class in osgWidget proper.
bool scrollWindow(osgWidget::Event& ev) {
// The first thing we need to do is make sure we have a Frame object...
osgWidget::Frame* frame = dynamic_cast<osgWidget::Frame*>(ev.getWindow());
if(!frame) return false;
// And now we need to make sure our Frame has a valid internal EmbeddedWindow widget.
osgWidget::Window::EmbeddedWindow* ew =
dynamic_cast<osgWidget::Window::EmbeddedWindow*>(frame->getEmbeddedWindow())
;
if(!ew) return false;
// Lets get the visible area so that we can use it to make sure our scrolling action
// is necessary in the first place.
const osgWidget::Quad& va = ew->getWindow()->getVisibleArea();
// The user wants to scroll up; make sure that the visible area's Y origin isn't already
// at 0.0f, 0.0f.
if(ev.getWindowManager()->isMouseScrollingUp() && va[1] != 0.0f)
ew->getWindow()->addVisibleArea(0, -20)
;
else if(va[1] <= (ew->getWindow()->getHeight() - ew->getHeight()))
ew->getWindow()->addVisibleArea(0, 20)
;
// We need to manually call update to make sure the visible area scissoring is done
// properly.
frame->update();
return true;
}
bool changeTheme(osgWidget::Event& ev) {
std::string theme;
if(ev.key == osgGA::GUIEventAdapter::KEY_Right)
theme = "osgWidget/theme-1.png"
;
else if(ev.key == osgGA::GUIEventAdapter::KEY_Left)
theme = "osgWidget/theme-2.png"
;
else return false;
osgWidget::Frame* frame = dynamic_cast<osgWidget::Frame*>(ev.getWindow());
if(!frame) return false;
// This is just one way to access all our Widgets; we could just as well have used:
//
// for(osgWidget::Frame::Iterator i = frame.begin(); i != frame.end() i++) {}
//
// ...and it have worked, too.
for(unsigned int row = 0; row < 3; row++) {
for(unsigned int col = 0; col < 3; col++) {
frame->getByRowCol(row, col)->setImage(theme);
}
}
return true;
}
int main(int argc, char** argv) {
osgViewer::Viewer viewer;
osgWidget::WindowManager* wm = new osgWidget::WindowManager(
&viewer,
1280.0f,
1024.0f,
MASK_2D,
osgWidget::WindowManager::WM_PICK_DEBUG
);
osgWidget::Frame* frame = osgWidget::Frame::createSimpleFrameWithSingleTexture(
"frame",
"../examples/osgwidgetscrolled/theme-2.png",
64.0f,
64.0f,
16.0f,
16.0f,
100.0f,
100.0f
);
frame->getBackground()->setColor(0.0f, 0.0f, 0.0f, 0.0f);
// This is our Transformers box. :)
osgWidget::Box* box = new osgWidget::Box("images", osgWidget::Box::VERTICAL);
osgWidget::Widget* img1 = new osgWidget::Widget("im1", 256.0f, 256.0f);
osgWidget::Widget* img2 = new osgWidget::Widget("im2", 256.0f, 256.0f);
osgWidget::Widget* img3 = new osgWidget::Widget("im3", 256.0f, 256.0f);
osgWidget::Widget* img4 = new osgWidget::Widget("im4", 256.0f, 256.0f);
img1->setImage("../examples/osgwidgetscrolled/images/starscream.jpg", true);
img2->setImage("../examples/osgwidgetscrolled/images/optimus.jpg", true);
img3->setImage("../examples/osgwidgetscrolled/images/megatron.jpg", true);
img4->setImage("../examples/osgwidgetscrolled/images/bumblebee.jpg", true);
img1->setMinimumSize(10.0f, 10.0f);
img2->setMinimumSize(10.0f, 10.0f);
img3->setMinimumSize(10.0f, 10.0f);
img4->setMinimumSize(10.0f, 10.0f);
box->addWidget(img1);
box->addWidget(img2);
box->addWidget(img3);
box->addWidget(img4);
box->setEventMask(osgWidget::EVENT_NONE);
frame->getEmbeddedWindow()->setWindow(box);
frame->getEmbeddedWindow()->setColor(1.0f, 1.0f, 1.0f, 1.0f);
frame->resize(300.0f, 300.0f);
frame->addCallback(osgWidget::Callback(&scrollWindow, osgWidget::EVENT_MOUSE_SCROLL));
frame->addCallback(osgWidget::Callback(&changeTheme, osgWidget::EVENT_KEY_DOWN));
wm->addChild(frame);
return osgWidget::createExample(viewer, wm);
}

View File

@ -0,0 +1,9 @@
PROJECT(osgwidgetshader)
LINK_LIBRARIES(debug osgWidgetd optimized osgWidget)
ADD_EXECUTABLE(osgwidgetshader osgwidgetshader.cpp)
SET_TARGET_PROPERTIES(osgwidgetshader PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
INSTALL(TARGETS osgwidgetshader DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)

View File

@ -0,0 +1,74 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: osgwidgetshader.cpp 28 2008-03-26 15:26:48Z cubicool $
#include <osgWidget/Util>
#include <osgWidget/WindowManager>
#include <osgWidget/Canvas>
const unsigned int MASK_2D = 0xF0000000;
osgWidget::Widget* createWidget(
const std::string& name,
osgWidget::color_type col,
osgWidget::Widget::LAYER layer
) {
osgWidget::Widget* widget = new osgWidget::Widget(name, 200.0f, 200.0f);
widget->setColor(col, col, col, 0.2f);
widget->setLayer(layer);
return widget;
}
int main(int argc, char** argv) {
osgViewer::Viewer viewer;
osgWidget::WindowManager* wm = new osgWidget::WindowManager(
&viewer,
1280.0f,
1024.0f,
MASK_2D
);
osgWidget::Canvas* canvas = new osgWidget::Canvas("canvas");
canvas->attachMoveCallback();
canvas->attachScaleCallback();
canvas->addWidget(
createWidget("w1", 0.2f, osgWidget::Widget::LAYER_LOW),
0.0f,
0.0f
);
canvas->addWidget(
createWidget("w2", 0.4f, osgWidget::Widget::LAYER_MIDDLE),
200.0f,
0.0f
);
canvas->addWidget(
createWidget("w3", 0.6f, osgWidget::Widget::LAYER_HIGH),
400.0f,
0.0f
);
wm->addChild(canvas);
osg::Program* program = new osg::Program();
program->addShader(osg::Shader::readShaderFile(
osg::Shader::VERTEX,
"osgWidget/osgwidgetshader-vert.glsl"
));
program->addShader(osg::Shader::readShaderFile(
osg::Shader::FRAGMENT,
"osgWidget/osgwidgetshader-frag.glsl"
));
canvas->getGeode()->getOrCreateStateSet()->setAttribute(program);
return osgWidget::createExample(viewer, wm);
}

View File

@ -0,0 +1,9 @@
PROJECT(osgwidgetstyled)
LINK_LIBRARIES(debug osgWidgetd optimized osgWidget)
ADD_EXECUTABLE(osgwidgetstyled osgwidgetstyled.cpp)
SET_TARGET_PROPERTIES(osgwidgetstyled PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
INSTALL(TARGETS osgwidgetstyled DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)

View File

@ -0,0 +1,83 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: osgwidgetshader.cpp 28 2008-03-26 15:26:48Z cubicool $
#include <osgWidget/Util>
#include <osgWidget/WindowManager>
#include <osgWidget/StyleManager>
#include <osgWidget/Box>
const unsigned int MASK_2D = 0xF0000000;
const std::string& STYLE1 =
"color 0 0 0 128\n"
"padding 5\n"
;
const std::string& STYLE2 =
"color 1.0 0.5 0.0\n"
;
const std::string& STYLE3 =
"fill true\n"
;
const std::string& STYLE4 =
"pos 100.0 100.0\n"
"size 600 600\n"
;
class CustomStyled: public osgWidget::Widget {
};
class CustomStyle: public osgWidget::Style {
virtual bool applyStyle(osgWidget::Widget* w, osgWidget::Reader r) {
CustomStyled* cs = dynamic_cast<CustomStyled*>(w);
if(!cs) return false;
osgWidget::warn() << "Here, okay." << std::endl;
return true;
}
};
int main(int argc, char** argv) {
osgViewer::Viewer viewer;
osgWidget::WindowManager* wm = new osgWidget::WindowManager(
&viewer,
1280.0f,
1024.0f,
MASK_2D
);
osgWidget::Box* box = new osgWidget::Box("box", osgWidget::Box::VERTICAL);
osgWidget::Widget* widget1 = new osgWidget::Widget("w1", 200.0f, 200.0f);
osgWidget::Widget* widget2 = new osgWidget::Widget("w2", 100.0f, 100.0f);
osgWidget::Widget* widget3 = new osgWidget::Widget("w3", 0.0f, 0.0f);
CustomStyled* cs = new CustomStyled();
// Yep.
wm->getStyleManager()->addStyle(new osgWidget::Style("widget.style1", STYLE1));
wm->getStyleManager()->addStyle(new osgWidget::Style("widget.style2", STYLE2));
wm->getStyleManager()->addStyle(new osgWidget::Style("spacer", STYLE3));
wm->getStyleManager()->addStyle(new osgWidget::Style("window", STYLE4));
// wm->getStyleManager()->addStyle(new CustomStyle("widget", ""));
widget1->setStyle("widget.style1");
widget2->setStyle("widget.style2");
widget3->setStyle("spacer");
box->setStyle("window");
box->addWidget(widget1);
box->addWidget(widget2);
box->addWidget(widget3);
wm->addChild(box);
// box->resizePercent(0.0f, 100.0f);
return osgWidget::createExample(viewer, wm);
}

View File

@ -0,0 +1,9 @@
PROJECT(osgwidgettable)
LINK_LIBRARIES(debug osgWidgetd optimized osgWidget)
ADD_EXECUTABLE(osgwidgettable osgwidgettable.cpp)
SET_TARGET_PROPERTIES(osgwidgettable PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
INSTALL(TARGETS osgwidgettable DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)

View File

@ -0,0 +1,69 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: osgwidgettable.cpp 43 2008-04-17 03:40:05Z cubicool $
#include <osgWidget/Util>
#include <osgWidget/WindowManager>
#include <osgWidget/Table>
const unsigned int MASK_2D = 0xF0000000;
// This examples demonstrates the use of an osgWidget::Table, which differs from a Box in
// many ways. First and foremost, a Table's size is intially known, whereas a Box can be
// dynamically added to. Secondly, a table is matrix Layout, with both vertical and
// horizontal placement cells. A Box, on the other hand, can only be vertical or horizontal.
int main(int argc, char** argv) {
osgViewer::Viewer viewer;
osgWidget::WindowManager* wm = new osgWidget::WindowManager(
&viewer,
1280.0f,
1024.0f,
MASK_2D,
osgWidget::WindowManager::WM_PICK_DEBUG
);
osgWidget::Table* table = new osgWidget::Table("table", 3, 3);
// Here we create our "cells" manually, though it will often be convenient to
// do so algorithmically. Also, notice how we set the text name of each widget to
// correspond with it's "index" in the table. This is merely a convenience, which
// we use later...
table->addWidget(new osgWidget::Widget("0, 0", 100.0f, 25.0f), 0, 0);
table->addWidget(new osgWidget::Widget("0, 1", 100.0f, 25.0f), 0, 1);
table->addWidget(new osgWidget::Widget("0, 2", 100.0f, 75.0f), 0, 2);
table->addWidget(new osgWidget::Widget("1, 0", 200.0f, 45.0f), 1, 0);
table->addWidget(new osgWidget::Widget("1, 1", 200.0f, 45.0f), 1, 1);
table->addWidget(new osgWidget::Widget("1, 2", 200.0f, 45.0f), 1, 2);
table->addWidget(new osgWidget::Widget("2, 0", 300.0f, 65.0f), 2, 0);
table->addWidget(new osgWidget::Widget("2, 1", 300.0f, 65.0f), 2, 1);
table->addWidget(new osgWidget::Widget("2, 2", 300.0f, 65.0f), 2, 2);
table->getBackground()->setColor(0.0f, 0.0f, 0.5f, 1.0f);
table->attachMoveCallback();
// Use a hackish method of setting the spacing for all Widgets.
for(osgWidget::Table::Iterator i = table->begin(); i != table->end(); i++)
i->get()->setPadding(1.0f)
;
// Now we fetch the very first 0, 0 Widget in the table using an awkward method.
// This is merely one way to fetch a Widget from a Window, there are many others.
// The osgWidget::Window::getByName interface will be very handy in scripting languages
// where users will want to retrieve handles to existing Windows using a useful
// textual name, such as "MainGUIParent" or something.
table->getByName("0, 0")->setAlignHorizontal(osgWidget::Widget::HA_LEFT);
table->getByName("0, 0")->setAlignVertical(osgWidget::Widget::VA_BOTTOM);
table->getByName("0, 0")->setPadding(10.0f);
// Change the colors a bit to differentiate this row from the others.
table->getByName("2, 0")->setColor(1.0f, 0.0f, 0.0f, 1.0f, osgWidget::Widget::LOWER_LEFT);
table->getByName("2, 1")->setColor(1.0f, 0.0f, 0.0f, 0.5f);
table->getByName("2, 2")->setColor(1.0f, 0.0f, 0.0f, 0.5f);
wm->addChild(table);
return createExample(viewer, wm);
}

View File

@ -0,0 +1,9 @@
PROJECT(osgwidgetversion)
LINK_LIBRARIES(debug osgWidgetd optimized osgWidget)
ADD_EXECUTABLE(osgwidgetversion osgwidgetversion.cpp)
SET_TARGET_PROPERTIES(osgwidgetversion PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
INSTALL(TARGETS osgwidgetversion DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)

View File

@ -0,0 +1,14 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: osgwidgetversion.cpp 2 2008-01-24 16:11:26Z cubicool $
#include <osg/Notify>
#include <osgWidget/Version>
int main(int argc, char** argv) {
osg::notify(osg::NOTICE)
<< osgWidgetGetLibraryName() << " "
<< osgWidgetGetVersion() << std::endl
;
return 0;
}

View File

@ -0,0 +1,9 @@
PROJECT(osgwidgetwindow)
LINK_LIBRARIES(debug osgWidgetd optimized osgWidget)
ADD_EXECUTABLE(osgwidgetwindow osgwidgetwindow.cpp)
SET_TARGET_PROPERTIES(osgwidgetwindow PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
INSTALL(TARGETS osgwidgetwindow DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)

View File

@ -0,0 +1,204 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: osgwidgetwindow.cpp 66 2008-07-14 21:54:09Z cubicool $
#include <iostream>
#include <osgDB/ReadFile>
#include <osgGA/StateSetManipulator>
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgWidget/WindowManager>
#include <osgWidget/ViewerEventHandlers>
#include <osgWidget/Box>
const unsigned int MASK_2D = 0xF0000000;
const unsigned int MASK_3D = 0x0F000000;
// Here we create (and later demonstrate) the use of a simple function callback.
bool windowClicked(osgWidget::Event& ev) {
std::cout << "windowClicked: " << ev.getWindow()->getName() << std::endl;
if(ev.getData()) {
std::string* s = static_cast<std::string*>(ev.getData());
std::cout << "This is data attached to the event: " << *s << std::endl;
}
return true;
}
bool windowScrolled(osgWidget::Event& ev) {
osgWidget::warn()
<< "scrolling up? " << ev.getWindowManager()->isMouseScrollingUp()
<< std::endl
;
return true;
}
// Here we dcreate a new class and show how to use a method callback (which differs from
// a function callback in that we are required to also pass the "this" argument).
struct Object {
bool windowClicked(osgWidget::Event& ev) {
std::cout << "Object::windowClicked " << ev.getWindow()->getName() << std::endl;
return true;
}
};
int main(int argc, char** argv) {
osgViewer::Viewer viewer;
// Let's get busy! The WindowManager class is actually an osg::Switch,
// so you can add it to (ideally) an orthographic camera and have it behave as
// expected. Note that you create a WindowManager with a NodeMask--it is very important
// that this be unique for picking to work properly. This also makes it possible to have
// multiple WindowManagers each operating on their own, unique set of Window objects.
// The final bool argument is a group of flags that introduce optional functionality
// for the WindowManager. In our case we include the flags USE_PYTHON and USE_LUA,
// to demonstrate (and test) their usage. Finally, we pass the temporary WM_NO_BETA_WARN
// argument, which prevents creating the orange warning window. :) It will be shown
// in other examples...
osgWidget::WindowManager* wm = new osgWidget::WindowManager(
&viewer,
1280.0f,
1024.0f,
MASK_2D,
osgWidget::WindowManager::WM_USE_LUA |
osgWidget::WindowManager::WM_USE_PYTHON |
osgWidget::WindowManager::WM_PICK_DEBUG |
osgWidget::WindowManager::WM_NO_BETA_WARN
);
// An actual osgWidget::Window is pure virtual, so we've got to use the osgWidget::Box
// implementation for now. At a later time, support for Tables and other kinds of
// advanced layout Window types will be added.
osgWidget::Window* box = new osgWidget::Box("box", osgWidget::Box::HORIZONTAL);
// Now we actually attach our two types of callbacks to the box instance. The first
// uses the simple function signature, the second uses a bound method, passing "this"
// as the second argument to the Callback constructor.
Object obj;
static std::string data = "lol ur face!";
box->addCallback(osgWidget::Callback(&windowClicked, osgWidget::EVENT_MOUSE_PUSH, &data));
box->addCallback(osgWidget::Callback(&windowScrolled, osgWidget::EVENT_MOUSE_SCROLL));
box->addCallback(osgWidget::Callback(
&Object::windowClicked,
&obj,
osgWidget::EVENT_MOUSE_PUSH
));
// Create some of our "testing" Widgets; included are two Widget subclasses I made
// during testing which I've kept around for testing purposes. You'll notice
// that you cannot move the box using the NullWidget, and that the NotifyWidget
// is a bit verbose. :)
osgWidget::Widget* widget1 = new osgWidget::NotifyWidget("widget1", 300.0f, 100.0f);
osgWidget::Widget* widget2 = new osgWidget::NullWidget("widget2", 400.0f, 75.0f);
osgWidget::Widget* widget3 = new osgWidget::Widget("widget3", 100.0f, 100.0f);
// Set the colors of widget1 and widget3 to green.
widget1->setColor(0.0f, 1.0f, 0.0f, 1.0f);
widget1->setCanFill(true);
widget3->setColor(0.0f, 1.0f, 0.0f, 1.0f);
widget1->setImage(osgDB::readImageFile("Images/Saturn.TGA"), true);
// Set the color of widget2, to differentiate it and make it sassy. This is
// like a poor man's gradient!
widget2->setColor(0.9f, 0.0f, 0.0f, 0.9f, osgWidget::Widget::LOWER_LEFT);
widget2->setColor(0.9f, 0.0f, 0.0f, 0.9f, osgWidget::Widget::LOWER_RIGHT);
widget2->setColor(0.0f, 0.0f, 0.9f, 0.9f, osgWidget::Widget::UPPER_RIGHT);
widget2->setColor(0.0f, 0.0f, 0.9f, 0.9f, osgWidget::Widget::UPPER_LEFT);
// Now add our newly created widgets to our box.
box->addWidget(widget1);
box->addWidget(widget2);
box->addWidget(widget3);
// For maximum efficiency, Windows don't automatically reallocate their geometry
// and internal positioning every time a widget is added. Thus, we either have to
// call the WindowManger::resizeAllWindows method or manually call
// Window::resize when we're ready.
box->resize();
// Now, lets clone our existing box and create a new copy of of it, also adding that
// to the WindowManager. This demonstrates the usages of OSG's ->clone() support,
// though that is abstracted by our META_UIObject macro.
osgWidget::Window* boxCopy = box->cloneAs("newBox");
// Move our copy to make it visible.
boxCopy->setOrigin(0.0f, 125.0f);
boxCopy->getByName("widget1")->setColor(0.5f, 0.0f, 1.0f, 1.0f);
boxCopy->getByName("widget3")->setColor(0.5f, 0.0f, 1.0f, 1.0f);
// Add the successfully created Box (if we get this far) into the WindowManager, so
// that they can receive events.
wm->addChild(box);
wm->addChild(boxCopy);
// Now, ask our new box to be 100% the width of the WindowManager.
boxCopy->resizePercent(100.0f, 0.0f);
// Here we demonstrate the use of osgWidget/io_utils. This is really only useful for
// debugging at the moment, but later I'll make it more generic for .osg and .ive
// creation.
// std::cout << *box << std::endl << *boxCopy << std::endl;
// Add our event handler; is this better as a MatrixManipulator? Add a few other
// helpful ViewerEventHandlers.
viewer.addEventHandler(new osgWidget::MouseHandler(wm));
viewer.addEventHandler(new osgWidget::KeyboardHandler(wm));
viewer.addEventHandler(new osgViewer::StatsHandler());
viewer.addEventHandler(new osgViewer::WindowSizeHandler());
viewer.addEventHandler(new osgGA::StateSetManipulator(
viewer.getCamera()->getOrCreateStateSet()
));
// Setup our OSG objects for our scene; note the use of the utility function
// createOrthoCamera, which is just a helper for setting up a proper viewing area.
// An alternative (and a MUCH easier alternative at that!) is to
// simply use the createParentOrthoCamera method of the WindowManager class,
// which will wrap the calls to createOrthoCamera and addChild for us! Check out
// some of the other examples to see this in action...
osg::Group* group = new osg::Group();
osg::Camera* camera = osgWidget::createInvertedYOrthoCamera(1280.0f, 1024.0f);
osg::Node* model = osgDB::readNodeFile("cow.osg");
// Set our first non-UI node to be something other than the mask we created our
// WindowManager with to avoid picking.
// TODO: Do I need to create a mechanism for doing this automatically, or should
// that be the responsibility of the users of osgWidget?
model->setNodeMask(MASK_3D);
// Add the WindowManager instance to the 2D camera. This isn't strictly necessary,
// and you can get some cool results putting the WindowManager directly into a
// 3D scene. This is not necessary if you use WindowManager::createParentOrthoCamera.
camera->addChild(wm);
// Add our camera and a testing 3D model to the scene.
group->addChild(camera);
group->addChild(model);
// Here we show how to both run simple strings of code AND run entire files. These
// assume that you're running the osgwidgetwindow example from the build directory,
// otherwise you'll need to adjust the file path below in the call to runFile().
wm->getLuaEngine()->eval("window = osgwidget.newWindow()");
wm->getLuaEngine()->runFile("osgWidget/osgwidgetwindow.lua");
wm->getPythonEngine()->eval("import osgwidget");
wm->getPythonEngine()->runFile("osgWidget/osgwidgetwindow.py");
viewer.setUpViewInWindow(0, 0, 1280, 1024);
viewer.setSceneData(group);
/*
osgViewer::Viewer::Cameras cameras;
viewer.getCameras(cameras);
osg::Camera* c = cameras[0];
osg::Matrix s = osg::Matrix::scale(1.0f, -1.0f, 1.0f);
c->setProjectionMatrix(s * c->getProjectionMatrix());
*/
return viewer.run();
}

39
include/osgWidget/Box Normal file
View File

@ -0,0 +1,39 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: Box 46 2008-04-30 16:11:51Z cubicool $
#ifndef OSGWIDGET_BOX
#define OSGWIDGET_BOX
#include <osgWidget/Window>
namespace osgWidget {
class OSGWIDGET_EXPORT Box: public Window {
public:
enum BOX_TYPE {
VERTICAL,
HORIZONTAL
};
private:
BOX_TYPE _boxType;
bool _uniform;
unsigned int _lastAdd;
protected:
virtual void _resizeImplementation(point_type, point_type);
virtual Sizes _getWidthImplementation () const;
virtual Sizes _getHeightImplementation () const;
public:
META_Object (osgWidget, Box);
META_UIObject (Box);
Box (const std::string& = "", BOX_TYPE = HORIZONTAL, bool = false);
Box (const Box&, const osg::CopyOp&);
};
}
#endif

28
include/osgWidget/Canvas Normal file
View File

@ -0,0 +1,28 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: Canvas 66 2008-07-14 21:54:09Z cubicool $
#ifndef OSGWIDGET_CANVAS
#define OSGWIDGET_CANVAS
#include <osgWidget/Window>
namespace osgWidget {
class OSGWIDGET_EXPORT Canvas: public Window {
protected:
virtual void _resizeImplementation(point_type, point_type);
public:
META_Object (osgWidget, Canvas);
META_UIObject (Canvas);
Canvas (const std::string& = "");
Canvas (const Canvas&, const osg::CopyOp&);
// This would conflict with the normal addWidget if there were default values. :(
virtual bool addWidget(Widget*, point_type, point_type);
};
}
#endif

View File

@ -0,0 +1,376 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: EventInterface 64 2008-06-30 21:32:00Z cubicool $
#ifndef OSGWIDGET_EVENT_INTERFACE
#define OSGWIDGET_EVENT_INTERFACE
#include <list>
#include <osg/ref_ptr>
#include <osg/Referenced>
#include <osgWidget/Export>
namespace osgWidget {
class WindowManager;
class Window;
class Widget;
enum EVENT_TYPE {
EVENT_NONE = 0x0000,
EVENT_FOCUS = 0x0001,
EVENT_UNFOCUS = 0x0002,
EVENT_MOUSE_ENTER = 0x0004,
EVENT_MOUSE_OVER = 0x0008,
EVENT_MOUSE_LEAVE = 0x0010,
EVENT_MOUSE_DRAG = 0x0020,
EVENT_MOUSE_PUSH = 0x0040,
EVENT_MOUSE_RELEASE = 0x0080,
EVENT_MOUSE_SCROLL = 0x0100,
EVENT_KEY_DOWN = 0x0200,
EVENT_KEY_UP = 0x0400,
EVENT_ALL = 0xFFFF
};
// Helpful wrapper around using the raw types, since it often doesn't make sense to
// use some without the others.
enum EVENT_MASK {
EVENT_MASK_FOCUS = EVENT_FOCUS | EVENT_UNFOCUS,
EVENT_MASK_MOUSE_MOVE = EVENT_MOUSE_ENTER | EVENT_MOUSE_OVER | EVENT_MOUSE_LEAVE,
EVENT_MASK_MOUSE_CLICK = EVENT_MOUSE_PUSH | EVENT_MOUSE_RELEASE,
EVENT_MASK_MOUSE_DRAG = EVENT_MASK_MOUSE_MOVE | EVENT_MASK_MOUSE_CLICK | EVENT_MOUSE_DRAG,
EVENT_MASK_KEY = EVENT_KEY_UP | EVENT_KEY_DOWN
};
class OSGWIDGET_EXPORT Event {
friend class WindowManager;
friend class Window;
WindowManager* _wm;
Window* _window;
Widget* _widget;
void* _data;
public:
EVENT_TYPE type;
double x;
double y;
int key;
int keyMask;
Event(WindowManager* wm, EVENT_TYPE _type = EVENT_NONE):
_wm (wm),
_window (0),
_widget (0),
_data (0),
type (_type),
x (0.0f),
y (0.0f),
key (-1),
keyMask (-1) {
}
Event& makeType(EVENT_TYPE _type) {
if(_type != EVENT_NONE) type = _type;
return *this;
}
Event& makeMouse(double _x, double _y, EVENT_TYPE _type = EVENT_NONE) {
x = _x;
y = _y;
if(_type != EVENT_NONE) type = _type;
return *this;
}
Event& makeKey(int _key, int _keyMask, EVENT_TYPE _type = EVENT_NONE) {
key = _key;
keyMask = _keyMask;
if(_type != EVENT_NONE) type = _type;
return *this;
}
WindowManager* getWindowManager() {
return _wm;
}
const WindowManager* getWindowManager() const {
return _wm;
}
Window* getWindow() {
return _window;
}
const Window* getWindow() const {
return _window;
}
Widget* getWidget() {
return _widget;
}
const Widget* getWidget() const {
return _widget;
}
void* getData() {
return _data;
}
const void* getData() const {
return _data;
}
void setData(void* data) {
_data = data;
}
};
// The Callback interface was inspired by the CEGUI project:
//
// http://www.cegui.org.uk/wiki/index.php/Main_Page
//
// It's a great little way to cleanly implement callbacks for events, although
// I did change the names a bit to make them more appropriate for OSG. MANY THANKS
// to the CEGUI project!
// The CallbackInterface, which the highest-level functor keeps a pointer to.
struct CallbackInterface: public osg::Referenced {
virtual ~CallbackInterface() {
}
virtual bool operator()(Event&) = 0;
};
// The object that facilitates a class method as a callback.
template<typename T>
class ObjectCallback: public CallbackInterface {
public:
typedef bool (T::*ObjectCallbackType)(Event&);
private:
ObjectCallbackType _callback;
T* _object;
public:
ObjectCallback(ObjectCallbackType callback, T* obj):
_callback (callback),
_object (obj) {
}
virtual bool operator()(Event& ev) {
return (_object->*_callback)(ev);
}
};
// The object that facilitates general functions as callbacks.
template<typename T>
class FunctionCallback: public CallbackInterface {
T* _callback;
public:
FunctionCallback(T* callback):
_callback(callback) {
}
virtual bool operator()(Event& ev) {
return (*_callback)(ev);
}
};
// The highlevel functor.
class OSGWIDGET_EXPORT Callback {
EVENT_TYPE _type;
void* _data;
// We use a ref_ptr here so that we don't have to worry about memory.
osg::ref_ptr<CallbackInterface> _callback;
public:
// Creates a Callback that is bound to a member function.
template<typename T>
Callback(bool (T::*function)(Event&), T* obj, EVENT_TYPE type, void* data=0):
_type (type),
_data (data),
_callback (new ObjectCallback<T>(function, obj)) {
}
// Creates a Callback that is bound to a functor pointer.
template<typename T>
Callback(T* functor, EVENT_TYPE type, void* data=0):
_type (type),
_data (data),
_callback (new FunctionCallback<T>(functor)) {
}
bool operator()(Event& ev) {
return (*_callback)(ev);
}
EVENT_TYPE getType() const {
return _type;
}
void* getData() {
return _data;
}
const void* getData() const {
return _data;
}
};
class OSGWIDGET_EXPORT EventInterface {
private:
typedef std::list<Callback> CallbackList;
unsigned int _eventMask;
CallbackList _callbacks;
public:
EventInterface():
_eventMask(EVENT_NONE) {
}
EventInterface(const EventInterface& ei):
_eventMask (ei._eventMask),
_callbacks (ei._callbacks) {
}
virtual ~EventInterface() {
}
// These functions take as their final argument the WindowManager which issued the
// request. This is sometimes useful to get information about key state, etc.
// Notify the EventInterface object that is has been focused or unfocused; since
// this isn't always bound to a mouse event (i.e., if you want to be able to use
// the TAB key to focus), we need seperate events here.
virtual bool focus (WindowManager*) { return false; }
virtual bool unfocus (WindowManager*) { return false; }
// Mouse events, pretty self-explanatory.
virtual bool mouseEnter (double, double, WindowManager*) { return false; }
virtual bool mouseOver (double, double, WindowManager*) { return false; }
virtual bool mouseLeave (double, double, WindowManager*) { return false; }
virtual bool mouseDrag (double, double, WindowManager*) { return false; }
virtual bool mousePush (double, double, WindowManager*) { return false; }
virtual bool mouseRelease (double, double, WindowManager*) { return false; }
virtual bool mouseScroll (double, double, WindowManager*) { return false; }
// These functions pass the osgGA::GUIEventAdapter::KeySymbol and KeyModMask and,
// as above, the WindowManager.
virtual bool keyDown (int, int, WindowManager*) { return false; }
virtual bool keyUp (int, int, WindowManager*) { return false; }
void setEventMask(unsigned int mask) {
_eventMask = mask;
}
void addEventMask(unsigned int mask) {
_eventMask |= mask;
}
void removeEventMask(unsigned int mask) {
_eventMask ^= mask;
}
unsigned int getEventMask() const {
return _eventMask;
}
void addCallback(const Callback& cb) {
_callbacks.push_back(cb);
}
bool callCallbacks(Event& ev) {
if(ev.type == EVENT_NONE || !(_eventMask & ev.type)) return false;
for(CallbackList::iterator i = _callbacks.begin(); i != _callbacks.end(); i++) {
// This is the OLD method; testing a new method below.
// if(i->getType() == ev.type && (*i)(ev)) return true;
if(i->getType() == ev.type) {
ev.setData(i->getData());
if((*i)(ev)) return true;
}
}
return false;
}
bool callMethodAndCallbacks(Event& ev) {
if(ev.type == EVENT_NONE || !(_eventMask & ev.type)) return false;
bool handled = false;
if(ev.type == EVENT_FOCUS) handled = focus(ev.getWindowManager());
else if(ev.type == EVENT_UNFOCUS) handled = unfocus(ev.getWindowManager());
else if(ev.type == EVENT_MOUSE_ENTER)
handled = mouseEnter(ev.x, ev.y, ev.getWindowManager())
;
else if(ev.type == EVENT_MOUSE_OVER)
handled = mouseOver(ev.x, ev.y, ev.getWindowManager())
;
else if(ev.type == EVENT_MOUSE_LEAVE)
handled = mouseLeave(ev.x, ev.y, ev.getWindowManager())
;
else if(ev.type == EVENT_MOUSE_DRAG)
handled = mouseDrag(ev.x, ev.y, ev.getWindowManager())
;
else if(ev.type == EVENT_MOUSE_PUSH)
handled = mousePush(ev.x, ev.y, ev.getWindowManager())
;
else if(ev.type == EVENT_MOUSE_RELEASE)
handled = mouseRelease(ev.x, ev.y, ev.getWindowManager())
;
else if(ev.type == EVENT_MOUSE_SCROLL)
handled = mouseScroll(ev.x, ev.y, ev.getWindowManager())
;
else if(ev.type == EVENT_KEY_DOWN)
handled = keyDown(ev.key, ev.keyMask, ev.getWindowManager())
;
else if(ev.type == EVENT_KEY_UP)
handled = keyUp(ev.key, ev.keyMask, ev.getWindowManager())
;
else return false;
return callCallbacks(ev) || handled;
}
bool canFocus () const { return (_eventMask & EVENT_FOCUS) != 0; }
bool canUnfocus () const { return (_eventMask & EVENT_UNFOCUS) != 0; }
bool canMouseEnter () const { return (_eventMask & EVENT_MOUSE_ENTER) != 0; }
bool canMouseOver () const { return (_eventMask & EVENT_MOUSE_OVER) != 0; }
bool canMouseLeave () const { return (_eventMask & EVENT_MOUSE_LEAVE) != 0; }
bool canMouseDrag () const { return (_eventMask & EVENT_MOUSE_DRAG) != 0; }
bool canMousePush () const { return (_eventMask & EVENT_MOUSE_PUSH) != 0; }
bool canMouseRelease () const { return (_eventMask & EVENT_MOUSE_RELEASE) != 0; }
bool canMouseScroll () const { return (_eventMask & EVENT_MOUSE_SCROLL) != 0; }
bool canKeyDown () const { return (_eventMask & EVENT_KEY_DOWN) != 0; }
bool canKeyUp () const { return (_eventMask & EVENT_KEY_UP) != 0; }
};
}
#endif

47
include/osgWidget/Export Normal file
View File

@ -0,0 +1,47 @@
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* OpenSceneGraph Public License for more details.
*/
#ifndef OSGWIDGET_EXPORT_
#define OSGWIDGET_EXPORT_ 1
#if defined(_MSC_VER)
#pragma warning( disable : 4244 )
#pragma warning( disable : 4251 )
#pragma warning( disable : 4267 )
#pragma warning( disable : 4275 )
#pragma warning( disable : 4290 )
#pragma warning( disable : 4786 )
#pragma warning( disable : 4305 )
#pragma warning( disable : 4996 )
#endif
#if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__) || defined( __BCPLUSPLUS__)
# if defined( OSG_LIBRARY_STATIC )
# define OSGWIDGET_EXPORT
# elif defined( OSGWIDGET_LIBRARY )
# define OSGWIDGET_EXPORT __declspec(dllexport)
# else
# define OSGWIDGET_EXPORT __declspec(dllimport)
# endif
#else
# define OSGWIDGET_EXPORT
#endif
/**
\namespace osgWidet
The osgWidget is a NodeKit library that extends the core scene graph to support 3D widget set.
*/
#endif

161
include/osgWidget/Frame Normal file
View File

@ -0,0 +1,161 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: Frame 59 2008-05-15 20:55:31Z cubicool $
#ifndef OSGWIDGET_FRAME
#define OSGWIDGET_FRAME
#include <osgWidget/Table>
namespace osgWidget {
class OSGWIDGET_EXPORT Frame: public Table {
public:
enum CORNER {
CORNER_LOWER_LEFT,
CORNER_LOWER_RIGHT,
CORNER_UPPER_LEFT,
CORNER_UPPER_RIGHT
};
enum BORDER {
BORDER_LEFT,
BORDER_RIGHT,
BORDER_TOP,
BORDER_BOTTOM
};
protected:
Widget* _getCorner (CORNER) const;
Widget* _getBorder (BORDER) const;
public:
static std::string cornerToString (CORNER);
static std::string borderToString (BORDER);
class OSGWIDGET_EXPORT Corner: public Widget {
CORNER _corner;
public:
META_Object (osgWidget, Corner);
META_UIObject (Corner);
Corner (CORNER = CORNER_LOWER_LEFT, point_type = 0.0f, point_type = 0.0f);
Corner (const Corner&, const osg::CopyOp&);
bool mouseDrag(double, double, WindowManager*);
CORNER getCorner() const {
return _corner;
}
void setCorner(CORNER corner) {
_corner = corner;
}
void setCornerAndName(CORNER corner) {
_corner = corner;
_name = cornerToString(corner);
}
};
class OSGWIDGET_EXPORT Border: public Widget {
BORDER _border;
public:
META_Object (osgWidget, Border);
META_UIObject (Border);
Border (BORDER = BORDER_LEFT, point_type = 0.0f, point_type = 0.0f);
Border (const Border&, const osg::CopyOp&);
bool mouseDrag(double, double, WindowManager*);
BORDER getBorder() const {
return _border;
}
void setBorder(BORDER border) {
_border = border;
}
void setBorderAndName(BORDER border) {
_border = border;
_name = borderToString(border);
}
};
META_Object (osgWidget, Frame);
META_UIObject (Frame);
Frame (const std::string& = "");
Frame (const Frame&, const osg::CopyOp&);
virtual void managed(WindowManager*);
static Frame* createSimpleFrame(
const std::string&,
point_type,
point_type,
point_type,
point_type,
Frame* = 0
);
static Frame* createSimpleFrameWithSingleTexture(
const std::string&,
const std::string&,
point_type,
point_type,
point_type,
point_type,
point_type,
point_type,
Frame* = 0
);
void createSimpleFrame(point_type cw, point_type ch, point_type w, point_type h) {
createSimpleFrame(_name, cw, ch, w, h, this);
}
void createSimpleFrameWithSingleTexture(
const std::string& tex,
point_type tw,
point_type th,
point_type cw,
point_type ch,
point_type w,
point_type h
) {
createSimpleFrameWithSingleTexture(_name, tex, tw, th, cw, ch, w, h, this);
}
bool setWindow(Window*);
EmbeddedWindow* getEmbeddedWindow() {
return dynamic_cast<EmbeddedWindow*>(getByRowCol(1, 1));
}
const EmbeddedWindow* getEmbeddedWindow() const {
return dynamic_cast<const EmbeddedWindow*>(getByRowCol(1, 1));
}
Corner* getCorner(CORNER c) {
return dynamic_cast<Corner*>(_getCorner(c));
}
const Corner* getCorner(CORNER c) const {
return dynamic_cast<const Corner*>(_getCorner(c));
}
Border* getBorder(BORDER b) {
return dynamic_cast<Border*>(_getBorder(b));
}
const Border* getBorder(BORDER b) const {
return dynamic_cast<const Border*>(_getBorder(b));
}
};
}
#endif

77
include/osgWidget/Input Normal file
View File

@ -0,0 +1,77 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: Input 45 2008-04-23 16:46:11Z cubicool $
#ifndef OSGWIDGET_INPUT
#define OSGWIDGET_INPUT
#include <osgWidget/Label>
namespace osgWidget {
class OSGWIDGET_EXPORT Input: public Label {
point_type _xoff;
point_type _yoff;
unsigned int _index;
unsigned int _size;
unsigned int _cursorIndex;
unsigned int _maxSize;
std::vector<point_type> _offsets;
osg::ref_ptr<Widget> _cursor;
protected:
virtual void _calculateSize(const XYCoord&);
void _calculateCursorOffsets();
public:
Input(const std::string& = "", const std::string& = "", unsigned int = 20);
virtual void parented (Window*);
virtual void positioned ();
virtual bool focus (WindowManager*);
virtual bool unfocus (WindowManager*);
virtual bool keyUp (int, int, WindowManager*);
virtual bool keyDown (int, int, WindowManager*);
void setCursor(Widget*);
void setXOffset(point_type xo) {
_xoff = xo;
}
void setYOffset(point_type yo) {
_yoff = yo;
}
void setXYOffset(point_type xo, point_type yo) {
_xoff = xo;
_yoff = yo;
}
osg::Drawable* getCursor() {
return _cursor.get();
}
const osg::Drawable* getCursor() const {
return _cursor.get();
}
point_type getXOffset() const {
return _xoff;
}
point_type getYOffset() const {
return _yoff;
}
XYCoord getXYOffset() const {
return XYCoord(_xoff, _yoff);
}
};
}
#endif

59
include/osgWidget/Label Normal file
View File

@ -0,0 +1,59 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: Label 59 2008-05-15 20:55:31Z cubicool $
#ifndef OSGWIDGET_LABEL
#define OSGWIDGET_LABEL
#include <osgText/Text>
#include <osgWidget/Widget>
#include <osgWidget/Window>
namespace osgWidget {
class OSGWIDGET_EXPORT Label: public Widget {
unsigned int _textIndex;
protected:
osg::ref_ptr<osgText::Text> _text;
virtual void _calculateSize(const XYCoord&);
public:
META_Object (osgWidget, Label);
META_UIObject (Label);
Label (const std::string& = "", const std::string& = "");
Label (const Label&, const osg::CopyOp&);
virtual void parented (Window*);
virtual void unparented (Window*);
virtual void managed (WindowManager*);
virtual void positioned ();
void update ();
void setLabel (const std::string&);
void setFont (const std::string&);
void setFontSize (unsigned int);
void setFontColor (const Color&);
void setShadow (point_type);
XYCoord getTextSize() const;
std::string getLabel() const {
return _text->getText().createUTF8EncodedString();
}
void setFontColor(point_type r, point_type g, point_type b, point_type a) {
setFontColor(Color(r, g, b, a));
}
// For now you only get a const pointer, because we have a highly specific
// interface with the osgText library.
const osgText::Text* getText() const {
return _text.get();
}
};
}
#endif

31
include/osgWidget/Lua Normal file
View File

@ -0,0 +1,31 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: Lua 2 2008-01-24 16:11:26Z cubicool $
#ifndef OSGWIDGET_LUA
#define OSGWIDGET_LUA
#include <osgWidget/WindowManager>
namespace osgWidget {
// Externally defined; does this work in Windows?
struct LuaEngineData;
// The actual Engine itself. Every attempt is made to export the implemenation into the
// source file, rather than having it here.
class OSGWIDGET_EXPORT LuaEngine: public ScriptEngine {
LuaEngineData* _data;
WindowManager* _wm;
public:
LuaEngine(WindowManager* = 0);
bool initialize ();
bool close ();
bool eval (const std::string&);
bool runFile (const std::string&);
};
}
#endif

28
include/osgWidget/Python Normal file
View File

@ -0,0 +1,28 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: Python 2 2008-01-24 16:11:26Z cubicool $
#ifndef OSGWIDGET_PYTHON
#define OSGWIDGET_PYTHON
#include <osgWidget/WindowManager>
namespace osgWidget {
struct PythonEngineData;
class OSGWIDGET_EXPORT PythonEngine: public ScriptEngine {
PythonEngineData* _data;
WindowManager* _wm;
public:
PythonEngine(WindowManager* = 0);
bool initialize ();
bool close ();
bool eval (const std::string&);
bool runFile (const std::string&);
};
}
#endif

View File

@ -0,0 +1,29 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: ScriptEngine 2 2008-01-24 16:11:26Z cubicool $
#ifndef OSGWIDGET_SCRIPT_ENGINE
#define OSGWIDGET_SCRIPT_ENGINE
#include <osg/Referenced>
namespace osgWidget {
// An interface for our scripting API so that we can have a unified way to talk to both
// Lua and Python; perhaps even more! Furthermore, this will allow us to put the
// entire implementation into a source file...
class ScriptEngine: public osg::Referenced {
protected:
std::string _err;
public:
virtual bool initialize () { return false; }
virtual bool close () { return false; }
virtual bool eval (const std::string&) { return false; }
virtual bool runFile (const std::string&) { return false; }
virtual const std::string& getLastErrorText() const { return _err; }
};
}
#endif

View File

@ -0,0 +1,39 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: StyleInterface 63 2008-06-30 19:18:37Z cubicool $
#ifndef OSGWIDGET_STYLE_INTERFACE
#define OSGWIDGET_STYLE_INTERFACE
namespace osgWidget {
#include <osgWidget/Export>
class OSGWIDGET_EXPORT StyleInterface {
private:
std::string _style;
public:
StyleInterface():
_style("") {
}
StyleInterface(const StyleInterface& si):
_style(si._style) {
}
void setStyle(const std::string& style) {
_style = style;
}
std::string& getStyle() {
return _style;
}
const std::string& getStyle() const {
return _style;
}
};
}
#endif

View File

@ -0,0 +1,175 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: StyleManager 61 2008-06-24 20:24:26Z cubicool $
#ifndef OSGWIDGET_STYLE_MANAGER
#define OSGWIDGET_STYLE_MANAGER
#include <map>
#include <osgDB/FieldReaderIterator>
#include <osgWidget/Box>
#include <osgWidget/Frame>
#include <osgWidget/Input>
namespace osgWidget {
typedef osgDB::FieldReaderIterator& Reader;
class OSGWIDGET_EXPORT Style: public osg::Object {
std::string _style;
bool _match(const char* seq, Reader r) {
if(r.matchSequence(seq)) {
++r;
return true;
}
return false;
}
public:
META_Object(osgWidget, Style);
// Class and contents...
Style (const std::string& = "", const std::string& = "");
Style (const Style&, const osg::CopyOp&);
virtual bool applyStyle (Widget*, Reader);
virtual bool applyStyle (Label*, Reader);
virtual bool applyStyle (Input*, Reader);
virtual bool applyStyle (Window*, Reader);
virtual bool applyStyle (Window::EmbeddedWindow*, Reader);
virtual bool applyStyle (Box*, Reader);
virtual bool applyStyle (Frame::Corner*, Reader);
virtual bool applyStyle (Frame::Border*, Reader);
void setStyle(const std::string& style) {
_style = style;
}
std::string& getStyle() {
return _style;
}
const std::string& getStyle() const {
return _style;
}
static Widget::LAYER strToLayer (const std::string&);
static Widget::VERTICAL_ALIGNMENT strToVAlign (const std::string&);
static Widget::HORIZONTAL_ALIGNMENT strToHAlign (const std::string&);
static Widget::COORDINATE_MODE strToCoordMode (const std::string&);
static bool strToFill (const std::string&);
};
class OSGWIDGET_EXPORT StyleManager: public osg::Object {
public:
typedef std::map<std::string, osg::ref_ptr<Style> > Styles;
typedef Styles::iterator Iterator;
typedef Styles::const_iterator ConstIterator;
private:
Styles _styles;
template<typename T>
bool _applySpecificStyle(T* t, const std::string& style) {
osgDB::FieldReaderIterator r;
std::istringstream input(_styles[style]->getStyle());
r.attach(&input);
bool inc = false;
while(!r.eof()) if(_styles[style]->applyStyle(t, r)) inc = true;
return inc;
}
template<typename T>
bool _coerceAndApply(
osg::Object* obj,
const std::string& style,
const std::string& className
) {
T* t = dynamic_cast<T*>(obj);
if(!t) {
warn()
<< "An attempt was made to coerce Object [" << obj->getName()
<< "] into a " << className << " but failed." << std::endl
;
return 0;
}
return _applySpecificStyle(t, style);
}
bool _applyStyleToObject(osg::Object*, const std::string&);
// 1. Check and see if the explicit FULL path is available.
// 2. Check and see if each component working backward--minus the last--is available.
// 3. Check to see if just the className() is available.
template<typename T>
bool _applyStyles(T* t) {
if(!t) {
warn()
<< "Cannot call StyleManager::applyStyle with a NULL object."
<< std::endl
;
return false;
}
osg::Object* obj = dynamic_cast<osg::Object*>(t);
if(!obj) {
warn()
<< "Cannot coerce object into osg::Object in StyleManager:::applyStyle"
<< std::endl
;
return false;
}
std::string c = obj->className();
// Case 3; there's no explicit Style set, so see if there's one for the class.
if(t->getStyle().empty()) {
// Couldn't find the className, so we exit.
if(_styles.find(c) == _styles.end()) return false;
return _applyStyleToObject(obj, c);
}
// Case 1...
if(_styles.find(t->getStyle()) != _styles.end()) return _applyStyleToObject(
obj,
t->getStyle()
);
return false;
}
public:
META_Object(osgWidget, StyleManager);
StyleManager ();
StyleManager (const StyleManager&, const osg::CopyOp&);
bool addStyle(Style*);
bool applyStyles(Widget* widget) {
return _applyStyles(widget);
}
bool applyStyles(Window* window) {
return _applyStyles(window);
}
};
}
#endif

63
include/osgWidget/Table Normal file
View File

@ -0,0 +1,63 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: Table 48 2008-05-05 14:13:20Z cubicool $
#ifndef OSGWIDGET_TABLE
#define OSGWIDGET_TABLE
#include <osgWidget/Window>
namespace osgWidget {
class OSGWIDGET_EXPORT Table: public Window {
unsigned int _rows;
unsigned int _cols;
unsigned int _lastRowAdd;
unsigned int _lastColAdd;
public:
typedef std::vector<point_type> CellSizes;
protected:
unsigned int _calculateIndex(unsigned int, unsigned int) const;
void _getRows (CellSizes&, Getter) const;
void _getColumns (CellSizes&, Getter) const;
virtual void _resizeImplementation(point_type, point_type);
virtual Sizes _getWidthImplementation () const;
virtual Sizes _getHeightImplementation () const;
public:
META_Object (osgWidget, Table);
META_UIObject (Table);
Table (const std::string& = "", unsigned int = 0, unsigned int = 0);
Table (const Table&, const osg::CopyOp&);
virtual bool addWidget (Widget*);
virtual bool addWidget (Widget*, unsigned int, unsigned int);
void getRowHeights (CellSizes&) const;
void getRowMinHeights (CellSizes&) const;
void getColumnWidths (CellSizes&) const;
void getColumnMinWidths (CellSizes&) const;
void addHeightToRow (unsigned int, point_type);
void addWidthToColumn (unsigned int, point_type);
bool isRowVerticallyFillable (unsigned int) const;
bool isColumnHorizontallyFillable (unsigned int) const;
Widget* getByRowCol(unsigned int row, unsigned int col) {
return getObjects()[_calculateIndex(row, col)].get();
}
const Widget* getByRowCol(unsigned int row, unsigned int col) const {
return getObjects()[_calculateIndex(row, col)].get();
}
};
}
#endif

31
include/osgWidget/Types Normal file
View File

@ -0,0 +1,31 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: Types 33 2008-04-04 19:03:12Z cubicool $
#ifndef OSGWIDGET_TYPES
#define OSGWIDGET_TYPES
#include <numeric>
#include <osg/Geometry>
namespace osgWidget {
typedef osg::Vec2Array TexCoordArray;
typedef osg::Vec3Array PointArray;
typedef osg::Vec4Array ColorArray;
typedef TexCoordArray::value_type TexCoord;
typedef PointArray::value_type Point;
typedef ColorArray::value_type Color;
typedef TexCoord::value_type texcoord_type;
typedef Point::value_type point_type;
typedef Color::value_type color_type;
typedef osg::Vec2 XYCoord;
typedef osg::Vec4 Quad;
typedef osg::Matrix::value_type matrix_type;
}
#endif

View File

@ -0,0 +1,123 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: UIObjectParent 55 2008-05-12 19:14:42Z cubicool $
#ifndef OSGWIDGET_UI_OBJECT_PARENT
#define OSGWIDGET_UI_OBEJCT_PARENT
namespace osgWidget {
#define META_UIObject(name) \
name * cloneAs(\
const std::string& newName, \
const osg::CopyOp& co = osg::CopyOp::DEEP_COPY_ALL \
) const { \
name * obj = dynamic_cast<name *>(this->clone(co)); \
obj->setName(newName); \
return obj; \
}
template <typename T>
class UIObjectParent {
public:
typedef T object_type;
typedef osg::observer_ptr<object_type> ptr_type;
typedef std::vector<ptr_type> Vector;
typedef typename Vector::iterator Iterator;
typedef typename Vector::const_iterator ConstIterator;
protected:
Vector _objects;
public:
Iterator begin() {
return _objects.begin();
}
ConstIterator begin() const {
return _objects.begin();
}
Iterator end() {
return _objects.end();
}
ConstIterator end() const {
return _objects.end();
}
typename Vector::size_type size() const {
return _objects.size();
}
private:
// I had to add this to avoid ambiguity errors with MSVC. Garbage.
object_type* _getByName(const std::string& name) const {
for(ConstIterator i = begin(); i != end(); i++) {
if(i->valid() && i->get()->getName() == name) return i->get();
}
return 0;
}
object_type* _getByIndex(unsigned int index) const {
for(ConstIterator i = begin(); i != end(); i++) {
if(i->valid() && i->get()->getIndex() == index) return i->get();
}
return 0;
}
public:
object_type* getByName(const std::string& name) {
return _getByName(name);
}
const object_type* getByName(const std::string& name) const {
return _getByName(name);
}
object_type* getByIndex(unsigned int index) {
return _getByIndex(index);
}
const object_type* getByIndex(unsigned int index) const {
return _getByIndex(index);
}
unsigned int getNumObjects() const {
return _objects.size();
}
Vector& getObjects() {
return _objects;
}
const Vector& getObjects() const {
return _objects;
}
protected:
bool _remove(object_type* obj) {
Iterator i = std::find(begin(), end(), obj);
if(i == end()) return false;
_objects.erase(i);
return true;
}
bool _removeByName(const std::string& name) {
for(Iterator i = begin(); i != end(); i++) if(i->get()->getName() == name) {
_objects.erase(i);
return true;
}
return false;
}
};
}
#endif

79
include/osgWidget/Util Normal file
View File

@ -0,0 +1,79 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: Util 59 2008-05-15 20:55:31Z cubicool $
#ifndef OSGWIDGET_UTIL
#define OSGWIDGET_UTIL
#include <cctype>
#include <algorithm>
#include <sstream>
#include <osg/Camera>
#include <osgViewer/Viewer>
#include <osgViewer/CompositeViewer>
#include <osgWidget/Export>
#include <osgWidget/Types>
namespace osgWidget {
// These are NOT OSGWIDGET_EXPORT'd; these are internal only!
inline std::ostream& _notify(osg::NotifySeverity ns = osg::INFO) {
std::ostream& n = osg::notify(ns);
return n << "osgWidget: ";
}
inline std::ostream& warn() {
return _notify(osg::WARN);
}
inline std::ostream& info() {
return _notify();
}
inline std::string lowerCase(const std::string& str) {
std::string s = str;
// TODO: Why can't I specify std::tolower?
std::transform(s.begin(), s.end(), s.begin(), ::tolower);
return s;
}
// TODO: Is this totally ghetto or what?
template <typename T>
inline bool hasDecimal(T v) {
return (v - static_cast<T>(static_cast<long>(v))) > 0.0f;
}
class WindowManager;
// These ARE OSGWIDGET_EXPORT'd for your convenience. :)
OSGWIDGET_EXPORT std::string getFilePath (const std::string&);
OSGWIDGET_EXPORT std::string generateRandomName (const std::string&);
OSGWIDGET_EXPORT osg::Matrix createInvertedYOrthoProjectionMatrix (matrix_type, matrix_type);
OSGWIDGET_EXPORT osg::Camera* createOrthoCamera (matrix_type, matrix_type);
OSGWIDGET_EXPORT osg::Camera* createInvertedYOrthoCamera (matrix_type, matrix_type);
// This function sets up our basic example framework, and optionally sets some root
// scene data.
OSGWIDGET_EXPORT int createExample(osgViewer::Viewer&, WindowManager*, osg::Node* = 0);
// This function works like the above routine, except creates an additional "outside"
// view for looking at your 2D scene.
// TODO: Fix this!
OSGWIDGET_EXPORT int createCompositeExample(
osgViewer::CompositeViewer&,
osgViewer::View*,
WindowManager*,
osg::Node* = 0
);
OSGWIDGET_EXPORT bool writeWindowManagerNode(WindowManager*);
}
#endif

23
include/osgWidget/Version Normal file
View File

@ -0,0 +1,23 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: Version 64 2008-06-30 21:32:00Z cubicool $
#ifndef OSGWIDGET_VERSION
#define OSGWIDGET_VERSION
#include <osgWidget/Export>
extern "C" {
OSGWIDGET_EXPORT unsigned int osgWidgetGetMajorVersion ();
OSGWIDGET_EXPORT unsigned int osgWidgetGetMinorVersion ();
OSGWIDGET_EXPORT unsigned int osgWidgetGetPatchVersion ();
OSGWIDGET_EXPORT const char* osgWidgetGetExtraText ();
OSGWIDGET_EXPORT const char* osgWidgetGetVersion ();
OSGWIDGET_EXPORT const char* osgWidgetGetLibraryName ();
OSGWIDGET_EXPORT bool osgWidgetVersionMinimum (unsigned int, unsigned int, unsigned int);
OSGWIDGET_EXPORT bool osgWidgetVersionMaximum (unsigned int, unsigned int, unsigned int);
OSGWIDGET_EXPORT bool osgWidgetVersionRequired (unsigned int, unsigned int, unsigned int);
}
#endif

View File

@ -0,0 +1,78 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: ViewerEventHandlers 31 2008-04-01 19:36:41Z cubicool $
#ifndef OSGWIDGET_VIEWER_EVENT_HANDLERS
#define OSGWIDGET_VIEWER_EVENT_HANDLERS
#include <osgGA/GUIEventAdapter>
#include <osgGA/GUIEventHandler>
#include <osgWidget/WindowManager>
// NOTE! These are all just examples of some default event handlers--they are not
// required. You are more than welcome to provide your own even handlers that
// communicate with a WindowManager using it's public API.
namespace osgWidget {
// This handles the pressing/moving of mouse buttons, etc.
class OSGWIDGET_EXPORT MouseHandler: public osgGA::GUIEventHandler {
osg::ref_ptr<WindowManager> _wm;
bool _handleMousePush (float, float, int);
bool _handleMouseRelease (float, float, int);
bool _handleMouseDoubleClick (float, float, int);
bool _handleMouseDrag (float, float, int);
bool _handleMouseMove (float, float, int);
bool _handleMouseScroll (float, float, int);
typedef bool (MouseHandler::*MouseAction)(float, float, int);
typedef bool (WindowManager::*MouseEvent)(float, float);
MouseAction _isMouseEvent (osgGA::GUIEventAdapter::EventType) const;
bool _doMouseEvent (float, float, MouseEvent);
public:
MouseHandler(WindowManager*);
virtual bool handle(
const osgGA::GUIEventAdapter&,
osgGA::GUIActionAdapter&,
osg::Object*,
osg::NodeVisitor*
);
};
// This handles the forwarding of keypress events.
class OSGWIDGET_EXPORT KeyboardHandler: public osgGA::GUIEventHandler {
osg::ref_ptr<WindowManager> _wm;
public:
KeyboardHandler(WindowManager*);
virtual bool handle(
const osgGA::GUIEventAdapter&,
osgGA::GUIActionAdapter&,
osg::Object*,
osg::NodeVisitor*
);
};
// This class offers a default kind of handling for resizing.
class OSGWIDGET_EXPORT ResizeHandler: public osgGA::GUIEventHandler {
osg::ref_ptr<WindowManager> _wm;
osg::ref_ptr<osg::Camera> _camera;
public:
ResizeHandler(WindowManager*, osg::Camera*);
virtual bool handle(
const osgGA::GUIEventAdapter&,
osgGA::GUIActionAdapter&,
osg::Object*,
osg::NodeVisitor*
);
};
}
#endif

626
include/osgWidget/Widget Normal file
View File

@ -0,0 +1,626 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: Widget 64 2008-06-30 21:32:00Z cubicool $
#ifndef OSGWIDGET_WIDGET
#define OSGWIDGET_WIDGET
#include <osg/Texture2D>
#include <osgWidget/EventInterface>
#include <osgWidget/StyleInterface>
#include <osgWidget/UIObjectParent>
#include <osgWidget/Types>
namespace osgWidget {
class Window;
class WindowManager;
// A Widget is a rectangular region that recieves events about the state of various input
// devices such as the pointer and keyboard. It is aware of it's width, height, and origin but
// nothing else. It is the job of higher-level container objects to organize layouts and
// the like, and to contextualize the meaning of the widgets "origin" (whether it is absolute
// or relative).
class OSGWIDGET_EXPORT Widget: public osg::Geometry, public EventInterface, public StyleInterface {
public:
enum POINT {
LOWER_LEFT = 0,
LOWER_RIGHT = 1,
UPPER_RIGHT = 2,
UPPER_LEFT = 3,
LL = LOWER_LEFT,
LR = LOWER_RIGHT,
UR = UPPER_RIGHT,
UL = UPPER_LEFT,
ALL_POINTS = 4
};
enum LAYER {
LAYER_TOP = 20,
LAYER_HIGH = 15,
LAYER_MIDDLE = 10,
LAYER_LOW = 5,
LAYER_BG = 0
};
enum VERTICAL_ALIGNMENT {
VA_CENTER,
VA_TOP,
VA_BOTTOM
};
enum HORIZONTAL_ALIGNMENT {
HA_CENTER,
HA_LEFT,
HA_RIGHT
};
enum COORDINATE_MODE {
CM_ABSOLUTE,
CM_RELATIVE
};
private:
friend class Window;
// TODO: Because of the current class design, I don't think it's possible to
// have a ref_ptr here. :(
Window* _parent;
unsigned int _index;
unsigned int _layer;
// Padding is the value of pixels of space between whatever the widget is "contianed"
// in and the point at which it starts getting placed.
point_type _padLeft;
point_type _padRight;
point_type _padTop;
point_type _padBottom;
// The alignments are used in conjuction when the widget is NOT set to fill.
VERTICAL_ALIGNMENT _valign;
HORIZONTAL_ALIGNMENT _halign;
// This flag determines how sizing values are interpretted by setDimensions().
COORDINATE_MODE _coordMode;
// These are the relative values, which are not stored directly in our verts
// array but kept around for calculation later.
Quad _relCoords;
// This fill flag determines whether or not the widget will resize itself to fill
// all available space.
bool _canFill;
// Set this to false in an implementation to prevent copying.
bool _canClone;
// This variable is only used by the Window object to determine if it's necessary
// to call managed().
bool _isManaged;
// This variable is like _isManaged; it is used to store whether the Widget has
// been styled yet.
bool _isStyled;
// Set these variables to be the minimum size of a Widget so that it cannot be
// resized any smaller than this.
point_type _minWidth;
point_type _minHeight;
static osg::ref_ptr<PointArray> _norms;
WindowManager* _getWindowManager () const;
osg::Image* _getImage () const;
protected:
point_type _calculateZ(unsigned int) const;
PointArray* _verts() {
return dynamic_cast<PointArray*>(getVertexArray());
}
const PointArray* _verts() const {
return dynamic_cast<const PointArray*>(getVertexArray());
}
ColorArray* _cols() {
return dynamic_cast<ColorArray*>(getColorArray());
}
const ColorArray* _cols() const {
return dynamic_cast<const ColorArray*>(getColorArray());
}
TexCoordArray* _texs() {
return dynamic_cast<TexCoordArray*>(getTexCoordArray(0));
}
const TexCoordArray* _texs() const {
return dynamic_cast<const TexCoordArray*>(getTexCoordArray(0));
}
osg::Texture2D* _texture() {
return dynamic_cast<osg::Texture2D*>(
getStateSet()->getTextureAttribute(0, osg::StateAttribute::TEXTURE)
);
}
const osg::Texture2D* _texture() const {
return dynamic_cast<const osg::Texture2D*>(
getStateSet()->getTextureAttribute(0, osg::StateAttribute::TEXTURE)
);
}
osg::Image* _image() {
return _getImage();
}
const osg::Image* _image() const {
return _getImage();
}
public:
META_Object (osgWidget, Widget);
META_UIObject (Widget);
Widget (const std::string& = "", point_type = 0.0f, point_type = 0.0f);
Widget (const Widget&, const osg::CopyOp&);
virtual ~Widget() {
}
// This method is called when the widget is added to a Window; this is useful
// when the widget needs to do something advanced (like a Label). The parent
// is passed as the first argument, although _parent should already be set.
virtual void parented(Window*) {
}
virtual void unparented(Window*) {
}
// This method is called when the widget's parent Window is added to a
// WindowManager object. The base managed method (WHICH YOU MUST REMEMBER
// TO CALL IN YOUR DERIVED METHODS!) sets the TexMat properly depending
// on what coordinate system you're using.
virtual void managed(WindowManager*);
virtual void unmanaged(WindowManager*) {
}
// This method is called when the widget is resized or reallocated in any
// way. This is useful when the widget manages some internal Drawables that need
// to be modified in some way.
virtual void positioned() {
}
void setDimensions(
point_type = -1.0f,
point_type = -1.0f,
point_type = -1.0f,
point_type = -1.0f,
point_type = -1.0f
);
void setPadding (point_type);
void setColor (color_type, color_type, color_type, color_type, POINT = ALL_POINTS);
void addColor (color_type, color_type, color_type, color_type, POINT = ALL_POINTS);
void setTexCoord (texcoord_type, texcoord_type, POINT = ALL_POINTS);
// These are additional texture coordinate setting methods.
// This method will use a given origin as the LOWER_LEFT point and texture the
// remaining area based on some width and height values.
void setTexCoordRegion(point_type, point_type, point_type, point_type);
// These are convenience methods for setting up wrapping modes.
void setTexCoordWrapHorizontal ();
void setTexCoordWrapVertical ();
bool setImage (osg::Image*, bool=false);
bool setImage (const std::string&, bool=false);
void addX (point_type);
void addY (point_type);
void addWidth (point_type);
void addHeight (point_type);
void addOrigin (point_type, point_type);
void addSize (point_type, point_type);
point_type getWidth () const;
point_type getHeight () const;
point_type getX () const;
point_type getY () const;
point_type getZ () const;
point_type getPadHorizontal () const;
point_type getPadVertical () const;
const Point& getPoint (POINT = ALL_POINTS) const;
const Color& getColor (POINT = ALL_POINTS) const;
const TexCoord& getTexCoord (POINT = ALL_POINTS) const;
POINT convertPoint (POINT) const;
Color getImageColorAtXY (point_type x, point_type y) const;
XYCoord localXY (double, double) const;
bool isPaddingUniform() const;
bool isManaged() const {
return _isManaged;
}
bool isStyled() const {
return _isStyled;
}
void setDimensions(const Quad& q, point_type z = -1.0f) {
setDimensions(q[0], q[1], q[2], q[4], z);
}
void setX(point_type x) {
setDimensions(x);
}
void setY(point_type y) {
setDimensions(-1.0f, y);
}
// This method should be use with extreme caution.
void setZ(point_type z) {
setDimensions(-1.0f, -1.0f, -1.0f, -1.0f, z);
}
void setWidth(point_type w) {
setDimensions(-1.0f, -1.0f, w);
}
void setHeight(point_type h) {
setDimensions(-1.0f, -1.0f, -1.0f, h);
}
void setOrigin(point_type x, point_type y) {
setDimensions(x, y);
}
void setOrigin(const XYCoord& xy) {
setOrigin(xy.x(), xy.y());
}
void setSize(point_type w, point_type h) {
setDimensions(-1.0f, -1.0f, w, h);
}
void setSize(const XYCoord& xy) {
setSize(xy.x(), xy.y());
}
void setColor(const Color& col, POINT p = ALL_POINTS) {
setColor(col.r(), col.g(), col.b(), col.a(), p);
}
void setTexCoord(const XYCoord& xy, POINT p = ALL_POINTS) {
setTexCoord(xy.x(), xy.y(), p);
}
void setTexCoordRegion(const XYCoord& xy, point_type w, point_type h) {
setTexCoordRegion(xy.x(), xy.y(), w, h);
}
void addColor(const Color& col, POINT p = ALL_POINTS) {
addColor(col.r(), col.g(), col.b(), col.a(), p);
}
void addOrigin(const XYCoord& xy) {
addOrigin(xy.x(), xy.y());
}
void addSize(const XYCoord& xy) {
addSize(xy.x(), xy.y());
}
void setMinimumSize(point_type width, point_type height) {
_minWidth = width;
_minHeight = height;
}
void setMinimumSize(const XYCoord& xy) {
setMinimumSize(xy.x(), xy.y());
}
// TODO: Refine this...
void setLayer(LAYER l, unsigned int offset = 0) {
_layer = l + offset;
}
void setPadLeft(point_type p) {
_padLeft = p;
}
void setPadRight(point_type p) {
_padRight = p;
}
void setPadTop(point_type p) {
_padTop = p;
}
void setPadBottom(point_type p) {
_padBottom = p;
}
void setAlignHorizontal(HORIZONTAL_ALIGNMENT h) {
_halign = h;
}
void setAlignVertical(VERTICAL_ALIGNMENT v) {
_valign = v;
}
void setCoordinateMode(COORDINATE_MODE cm) {
_coordMode = cm;
}
void setCanFill(bool f) {
_canFill = f;
}
void setCanClone(bool c) {
_canClone = c;
}
WindowManager* getWindowManager() {
return _getWindowManager();
}
const WindowManager* getWindowManager() const {
return _getWindowManager();
}
Window* getParent() {
return _parent;
}
const Window* getParent() const {
return _parent;
}
unsigned int getIndex() const {
return _index;
}
XYCoord getOrigin() const {
return XYCoord(getX(), getY());
}
Color getImageColorAtXY(const XYCoord& xy) const {
return getImageColorAtXY(xy.x(), xy.y());
}
Color getImageColorAtPointerXY(double x, double y) const {
return getImageColorAtXY(localXY(x, y));
}
Point getPosition() const {
return Point(getX(), getY(), getZ());
}
XYCoord getSize() const {
return XYCoord(getWidth(), getHeight());
}
Quad getDimensions() const {
return Quad(getX(), getY(), getWidth(), getHeight());
}
point_type getPadLeft() const {
return _padLeft;
}
point_type getPadRight() const {
return _padRight;
}
point_type getPadTop() const {
return _padTop;
}
point_type getPadBottom() const {
return _padBottom;
}
HORIZONTAL_ALIGNMENT getAlignHorizontal() const {
return _halign;
}
VERTICAL_ALIGNMENT getAlignVertical() const {
return _valign;
}
COORDINATE_MODE getCoordinateMode() const {
return _coordMode;
}
bool canFill() const {
return _canFill;
}
bool canClone() const {
return _canClone;
}
// This casts the bool _fill variable to be used in iteratively in functions such
// as Window::_accumulate and whatnot.
point_type getFillAsNumeric() const {
return static_cast<point_type>(_canFill);
}
point_type getWidthTotal() const {
return getWidth() + getPadHorizontal();
}
point_type getHeightTotal() const {
return getHeight() + getPadVertical();
}
point_type getMinWidth() const {
return _minWidth;
}
point_type getMinHeight() const {
return _minHeight;
}
point_type getMinWidthTotal() const {
return _minWidth + getPadHorizontal();
}
point_type getMinHeightTotal() const {
return _minHeight + getPadVertical();
}
unsigned int getLayer() const {
return _layer;
}
};
typedef std::list<osg::observer_ptr<Widget> > WidgetList;
// A Widget subclass that prints stuff using osg::notify(). :)
struct NotifyWidget: public Widget {
META_Object(osgWidget, NotifyWidget);
NotifyWidget(const std::string& n = "", point_type w = 0.0f, point_type h = 0.0f):
Widget(n, w, h) {
setEventMask(EVENT_ALL);
}
NotifyWidget(const NotifyWidget& widget, const osg::CopyOp& co):
Widget(widget, co) {
}
bool focus(const WindowManager*) {
osg::notify(osg::NOTICE) << _name << " > focus called" << std::endl;
return false;
}
bool unfocus(const WindowManager*) {
osg::notify(osg::NOTICE) << _name << " > unfocus called" << std::endl;
return false;
}
bool mouseEnter(double, double, const WindowManager*) {
osg::notify(osg::NOTICE) << _name << " > mouseEnter called" << std::endl;
return false;
}
bool mouseOver(double, double, const WindowManager*) {
osg::notify(osg::NOTICE) << _name << " > mouseOver called" << std::endl;
return false;
}
bool mouseLeave(double, double, const WindowManager*) {
osg::notify(osg::NOTICE) << _name << " > mouseLeave called" << std::endl;
return false;
}
bool mouseDrag(double, double, const WindowManager*) {
osg::notify(osg::NOTICE) << _name << " > mouseDrag called" << std::endl;
return false;
}
bool mousePush(double, double, const WindowManager*) {
osg::notify(osg::NOTICE) << _name << " > mousePush called" << std::endl;
return false;
}
bool mouseRelease(double, double, const WindowManager*) {
osg::notify(osg::NOTICE) << _name << " > mouseRelease called" << std::endl;
return false;
}
bool mouseScroll(double, double, const WindowManager*) {
osg::notify(osg::NOTICE) << _name << " > mouseScroll called" << std::endl;
return false;
}
bool keyPress(int, int, const WindowManager*) {
osg::notify(osg::NOTICE) << _name << " > keyPress called" << std::endl;
return false;
}
bool keyRelease(int, int, const WindowManager*) {
osg::notify(osg::NOTICE) << _name << " > keyRelease called" << std::endl;
return false;
}
};
// A Widget that eats all events and returns true.
struct NullWidget: public Widget {
META_Object(osgWidget, NullWidget);
NullWidget(const std::string& n = "", point_type w = 0.0f, point_type h = 0.0f):
Widget(n, w, h) {
setEventMask(EVENT_ALL);
}
NullWidget(const NullWidget& widget, const osg::CopyOp& co):
Widget(widget, co) {
}
bool focus(const WindowManager*) {
return true;
}
bool unfocus(const WindowManager*) {
return true;
}
bool mouseEnter(double, double, const WindowManager*) {
return true;
}
bool mouseOver(double, double, const WindowManager*) {
return true;
}
bool mouseLeave(double, double, const WindowManager*) {
return true;
}
bool mouseDrag(double, double, const WindowManager*) {
return true;
}
bool mousePush(double, double, const WindowManager*) {
return true;
}
bool mouseRelease(double, double, const WindowManager*) {
return true;
}
bool mouseScroll(double, double, const WindowManager*) {
return true;
}
bool keyPress(int, int, const WindowManager*) {
return true;
}
bool keyRelease(int, int, const WindowManager*) {
return true;
}
};
}
#endif

636
include/osgWidget/Window Normal file
View File

@ -0,0 +1,636 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: Window 66 2008-07-14 21:54:09Z cubicool $
#ifndef OSGWIDGET_WINDOW
#define OSGWIDGET_WINDOW
#include <osg/Scissor>
#include <osg/MatrixTransform>
#include <osg/Geode>
#include <osg/ClipNode>
#include <osgWidget/Types>
#include <osgWidget/Util>
#include <osgWidget/Widget>
namespace osgWidget {
// These are helper callbacks you can attach to Windows that will make them moveable,
// rotatable, and scalable respectively.
bool callbackWindowMove (Event&);
bool callbackWindowRotate (Event&);
bool callbackWindowScale (Event&);
// These are helper callbacks you can attach to Windows to that will make various
// keyboard events behave as you might imagine.
bool callbackWindowTabFocus(Event&);
class OSGWIDGET_EXPORT Window:
public osg::MatrixTransform,
public UIObjectParent<Widget>,
public EventInterface,
public StyleInterface
{
public:
typedef std::list<osg::observer_ptr<Window> > WindowList;
struct Sizes {
point_type cur;
point_type min;
Sizes(point_type c = -1.0f, point_type m = -1.0f):
cur(c),
min(m) {
}
};
// TODO: This is a class that puts (embeds) the Window inside of a Widget
// interface, to help assemble Windows with Windows, and what have you.
class OSGWIDGET_EXPORT EmbeddedWindow: public Widget {
osg::ref_ptr<Window> _window;
public:
META_Object (osgWidget::Window, EmbeddedWindow);
META_UIObject (EmbeddedWindow);
EmbeddedWindow (const std::string& = "", point_type = 0.0f, point_type = 0.0f);
EmbeddedWindow (const EmbeddedWindow&, const osg::CopyOp&);
virtual void parented (Window*);
virtual void unparented (Window*);
virtual void managed (WindowManager*);
virtual void unmanaged (WindowManager*);
virtual void positioned ();
bool setWindow(Window*);
Window* getWindow() {
return _window.get();
}
const Window* getWindow() const {
return _window.get();
}
};
// These correspond to special regions honored by the WindowManager. Most Windows
// will want to be NONE, unless they need to exist in the foreground or background
// for some reason.
enum STRATA {
STRATA_NONE,
STRATA_BACKGROUND,
STRATA_FOREGROUND
};
// If you only want to display a portion of a Window (such as when it is embedded),
// you will need to set the VISIBILITY_MODE to WM_PARTIAL. Otherwise, the entire
// Window is visible by default. The final enum, VM_ENTIRE, says that no Scissoring
// should take place at all, and is useful in cases where you want to properly
// scale or rotate Windows.
enum VISIBILITY_MODE {
VM_FULL,
VM_PARTIAL,
VM_ENTIRE
};
// Anchors are very similar in that they allow us to pre-apply transformations in the
// call to Window::update() that allow us to position a Window somewhere relative
// to the WindowManger's viewable area. However, unlike the ALIGNMENT enums, these
// are totally optional (whereas a Widget must always have some ALIGNMENT value set.
enum VERTICAL_ANCHOR {
VA_NONE,
VA_CENTER,
VA_TOP,
VA_BOTTOM
};
enum HORIZONTAL_ANCHOR {
HA_NONE,
HA_CENTER,
HA_LEFT,
HA_RIGHT
};
protected:
typedef point_type (Widget::*Getter)() const;
typedef std::less<point_type> Less;
typedef std::greater<point_type> Greater;
typedef std::plus<point_type> Plus;
private:
friend class WindowManager;
// The (optional) Window that this Window is parented inside.
Window* _parent;
// The WindowManger to which this window is attached.
WindowManager* _wm;
// The positional index this Node holds within it's parent WindowManager.
unsigned int _index;
// The X and Y values of the Window (origin).
matrix_type _x;
matrix_type _y;
// A pair of values representing the currently calculated Z value and the
// depth range for all children to be used during the call to update().
matrix_type _z;
matrix_type _zRange;
// This is a special value that can be used to "force" a Window not to be
// focusable and instead always exist in the foreground or background.
STRATA _strata;
// A flag determining whether our visible area is the full Window or rather
// a portion of the Window.
VISIBILITY_MODE _vis;
// A rotation value in degrees.
matrix_type _r;
// This will also need to adjust geom internally so that picking is correct.
matrix_type _s;
matrix_type _scaleDenom;
Sizes _width;
Sizes _height;
VERTICAL_ANCHOR _vAnchor;
HORIZONTAL_ANCHOR _hAnchor;
// Not all windows have widgets that can focus, but if they do this should
// be a pointer to it.
osg::observer_ptr<Widget> _focused;
// The "visible" area that will define both the glScissor bounds AND will
// be used to make sure our pick is valid. The values herein correspond to
// X, Y, W, and H--in that order.
Quad _visibleArea;
// This helper method is used by _compare<>() and _accumulate<>(), so ignore this
// function and go see the docs for those instead. This thing is huge and unwieldy
// and not to be triffled with! :)
template<typename T>
point_type _forEachAssignOrApply(
Getter get,
int begin,
int end,
int add,
bool assign
) const {
point_type val = 0.0f;
unsigned int c = begin;
ConstIterator e = end > 0 ? _objects.begin() + end : _objects.end() + end;
// I WARNED YOU! If you try and understand what this does your head will
// explode! But let me say a few things: in MSVC you can't add to an iterator
// such that the add will cause it to increment past the end of the container.
// This appears to be safe in GCC, where it will just return the last
// item therein, but causes an assertion error in other compilers. I'm not
// sure if there is a cleaner remedy for this, so what we do for now is keep a
// count variable called "c" that makes sure our iterator's opterator+()
// method is safe to call.
for(
ConstIterator i = _objects.begin() + begin;
i < e;
c += add
) {
point_type v = 0.0f;
if(i->valid()) v = (i->get()->*get)();
// If you want to assign to val, and NOT add a sequence of them...
if(assign) {
if(T()(v, val)) val = v;
}
// If you want to accumulate a value INTO val...
else val = T()(v, val);
// Make sure our iterator is safe to increment. Otherwise, set it to
// whatever end is.
// TODO: This isn't 100% accurate, as it does not YET take into account
// our requested end in any way other than implicitly. It should, however,
// work okay for now.
if((c + add) < _objects.size()) i += add;
else i = e;
}
return val;
}
void _setWidthAndHeightUnknownSizeError (const std::string&, point_type);
void _setWidthAndHeightNotPAError (const std::string&, point_type);
void _setWidthAndHeight ();
void _removeFromGeode (Widget*);
Widget* _getBackground() const;
Window* _getTopmostParent() const;
protected:
// This method will return the T'th value returned by applying the Getter member function
// pointer to each iterator in the range of iterators defined by offset and add. In
// plain language, this helper method will apply some standard Widget::get* function
// to a range of objects in the _objects Vector, and will return the T'th of that.
// The template T can be any functor accepting two point_type values that return
// a bool. For example, this is commonly used with std::less to find the smallest
// width in a range of Widgets.
template<typename T>
point_type _compare(
Getter get,
int begin = 0,
int end = 0,
int add = 1
) const {
return _forEachAssignOrApply<T>(get, begin, end, add, true);
}
// This method will return the T'th value accumulated by applying the Getter member
// function to each iterator in the range of iterators defined by offset and add (similar
// to above). For example, this method can be used to apply std::plus to every
// width in a range of Widgets, and return the total.
template<typename T>
point_type _accumulate(
Getter get,
int begin = 0,
int end = 0,
int add = 1
) const {
return _forEachAssignOrApply<T>(get, begin, end, add, false);
}
osg::Geode* _geode() {
return dynamic_cast<osg::Geode*>(getChild(0));
}
const osg::Geode* _geode() const {
return dynamic_cast<const osg::Geode*>(getChild(0));
}
Widget* _bg() {
return _getBackground();
}
const Widget* _bg() const {
return _getBackground();
}
osg::Scissor* _scissor() {
return dynamic_cast<osg::Scissor*>(
getStateSet()->getAttribute(osg::StateAttribute::SCISSOR)
);
}
bool _setWidget (Widget*, int = -1);
bool _setVisible (bool);
void _setFocused (Widget*);
void _setStyled (Widget*);
void _setParented (Widget*, bool=false);
void _setManaged (Widget*, bool=false);
void _positionWidget(Widget*, point_type, point_type);
// These return the smallest and largest width and height values for the given
// range of Widgets.
point_type _getMinWidgetWidth (int = 0, int = 0, int = 1) const;
point_type _getMinWidgetHeight (int = 0, int = 0, int = 1) const;
point_type _getMaxWidgetWidth (int = 0, int = 0, int = 1) const;
point_type _getMaxWidgetHeight (int = 0, int = 0, int = 1) const;
// These return the smallest and largest minWidth and minHeight values for
// the given range of Widgets.
point_type _getMinWidgetMinWidth (int = 0, int = 0, int = 1) const;
point_type _getMinWidgetMinHeight (int = 0, int = 0, int = 1) const;
point_type _getMaxWidgetMinWidth (int = 0, int = 0, int = 1) const;
point_type _getMaxWidgetMinHeight (int = 0, int = 0, int = 1) const;
// These return the smallest and largest width and height total (width + pad)
// values for the given range of Widgets.
point_type _getMinWidgetWidthTotal (int = 0, int = 0, int = 1) const;
point_type _getMinWidgetHeightTotal (int = 0, int = 0, int = 1) const;
point_type _getMaxWidgetWidthTotal (int = 0, int = 0, int = 1) const;
point_type _getMaxWidgetHeightTotal (int = 0, int = 0, int = 1) const;
// These return the smallest and largest minWidth and minHeight total
// (width + pad) values for the given range of Widgets.
point_type _getMinWidgetMinWidthTotal (int = 0, int = 0, int = 1) const;
point_type _getMinWidgetMinHeightTotal (int = 0, int = 0, int = 1) const;
point_type _getMaxWidgetMinWidthTotal (int = 0, int = 0, int = 1) const;
point_type _getMaxWidgetMinHeightTotal (int = 0, int = 0, int = 1) const;
// These return the smallest and largest horizontal and vertical padding
// values for the given range of Widgets.
point_type _getMinWidgetPadHorizontal (int = 0, int = 0, int = 1) const;
point_type _getMinWidgetPadVertical (int = 0, int = 0, int = 1) const;
point_type _getMaxWidgetPadHorizontal (int = 0, int = 0, int = 1) const;
point_type _getMaxWidgetPadVertical (int = 0, int = 0, int = 1) const;
point_type _getNumFill(int = 0, int = 0, int = 1) const;
// This method is passed the additional values by which width and height should be
// modified as calculed by the parent method, Window::resize. Keep in mind that these
// values can be negative (indicating a potential "shrink" request) or positive (which
// would indicate a "grow" reqeust).
virtual void _resizeImplementation(point_type, point_type) = 0;
// These are made into implementation functions since getting the width or height
// of a window can potentially be an expensive operation, and we'll want to cache
// results if possible (which is handled transparently by the actualy Window::resize
// method). They return a Sizes struct which contains two members: cur (for current)
// and min (minimum). It's important that the Window know it's minimum possible
// size so that it can ignore invaled requests to resize.
//
// Default versions using BoundingBox calculations are provided, but some Windows
// override this (Table, Box).
virtual Sizes _getWidthImplementation () const;
virtual Sizes _getHeightImplementation () const;
public:
META_UIObject(Window);
Window (const std::string& = "");
Window (const Window&, const osg::CopyOp&);
bool resize (point_type = 0.0f, point_type = 0.0f);
bool resizeAdd (point_type = 0.0f, point_type = 0.0f);
bool resizePercent (point_type = 0.0f, point_type = 0.0f);
virtual void update ();
virtual void managed (WindowManager*);
virtual void unmanaged (WindowManager*);
virtual bool addWidget (Widget*);
virtual bool insertWidget (Widget*, unsigned int);
virtual bool removeWidget (Widget*);
virtual bool replaceWidget (Widget*, Widget*);
// This method wraps our Geode's addDrawable() method and returns the index of
// the newly-added Drawable.
unsigned int addDrawableAndGetIndex(osg::Drawable*);
bool isVisible () const;
bool isXYWithinVisible (float, float) const;
void setVisibleArea (int = 0, int = 0, int = 0, int = 0);
void addVisibleArea (int = 0, int = 0, int = 0, int = 0);
bool setFocused (const Widget*);
bool setFocused (const std::string&);
bool setFirstFocusable ();
bool setNextFocusable ();
bool getFocusList (WidgetList&) const;
bool getEmbeddedList (WindowList&) const;
void getParentList (WindowList&) const;
XYCoord localXY (double, double) const;
XYCoord getAbsoluteOrigin () const;
// This method wraps the current Window in a EmbeddedWindow object and returns it.
EmbeddedWindow* embed();
Widget* getFocused() {
return _focused.get();
}
const Widget* getFocused() const {
return _focused.get();
}
bool show() {
return _setVisible(true);
}
bool hide() {
return _setVisible(false);
}
bool isPointerXYWithinVisible(float x, float y) const {
XYCoord xy = localXY(x, y);
return isXYWithinVisible(xy.x(), xy.y());
}
osg::Geode* getGeode() {
return _geode();
}
const osg::Geode* getGeode() const {
return _geode();
}
Widget* getBackground() {
return _bg();
}
const Widget* getBackground() const {
return _bg();
}
WindowManager* getWindowManager() {
return _wm;
}
const WindowManager* getWindowManager() const {
return _wm;
}
Window* getParent() {
return _parent;
}
const Window* getParent() const {
return _parent;
}
Window* getTopmostParent() {
return _getTopmostParent();
}
const Window* getTopmostParent() const {
return _getTopmostParent();
}
unsigned int getIndex() const {
return _index;
}
matrix_type getX() const {
return _x;
}
matrix_type getY() const {
return _y;
}
matrix_type getZ() const {
return _z;
}
point_type getWidth() const {
return _width.cur;
}
point_type getHeight() const {
return _height.cur;
}
point_type getMinWidth() const {
return _width.min;
}
point_type getMinHeight() const {
return _height.min;
}
VERTICAL_ANCHOR getAnchorVertical() const {
return _vAnchor;
}
HORIZONTAL_ANCHOR getAnchorHorizontal() const {
return _hAnchor;
}
XYCoord getOrigin() const {
return XYCoord(_x, _y);
}
XYCoord getSize() const {
return XYCoord(_width.cur, _height.cur);
}
XYCoord getMinSize() const {
return XYCoord(_width.min, _height.min);
}
matrix_type getZRange() const {
return _zRange;
}
STRATA getStrata() const {
return _strata;
}
const Quad& getVisibleArea() const {
return _visibleArea;
}
VISIBILITY_MODE getVisibilityMode() const {
return _vis;
}
Point getPosition() const {
return Point(_x, _y, _z);
}
matrix_type getRotate() const {
return _r;
}
matrix_type getScale() const {
return _s;
}
matrix_type getScaleDenominator() const {
return _scaleDenom;
}
void setX(matrix_type x) {
_x = x;
}
void setY(matrix_type y) {
_y = y;
}
void setPosition(matrix_type x, matrix_type y, matrix_type z) {
_x = x;
_y = y;
_z = z;
}
void setPosition(const Point& p) {
setPosition(p.x(), p.y(), p.z());
}
void setOrigin(matrix_type x, matrix_type y) {
_x = x;
_y = y;
}
void setRotate(matrix_type r) {
_r = r;
}
void setScale(matrix_type s) {
_s = s;
}
void setScaleDenominator(matrix_type sd) {
_scaleDenom = sd;
}
void setAnchorVertical(VERTICAL_ANCHOR va) {
_vAnchor = va;
}
void setAnchorHorizontal(HORIZONTAL_ANCHOR ha) {
_hAnchor = ha;
}
void setStrata(STRATA s) {
_strata = s;
}
void setVisibilityMode(VISIBILITY_MODE v) {
_vis = v;
}
void addX(matrix_type x) {
_x += x;
}
void addY(matrix_type y) {
_y += y;
}
void addZ(matrix_type z) {
_z += z;
}
void addRotate(matrix_type r) {
_r += r;
}
void addScale(matrix_type s) {
_s += s / (_scaleDenom != 0.0f ? _scaleDenom : 1.0f);
}
void addOrigin(matrix_type x, matrix_type y) {
_x += x;
_y += y;
}
void attachMoveCallback() {
addCallback(Callback(&callbackWindowMove, EVENT_MOUSE_DRAG));
}
void attachRotateCallback() {
addCallback(Callback(&callbackWindowRotate, EVENT_MOUSE_DRAG));
}
void attachScaleCallback() {
addCallback(Callback(&callbackWindowScale, EVENT_MOUSE_DRAG));
}
void attachTabFocusCallback() {
addCallback(Callback(&callbackWindowTabFocus, EVENT_KEY_DOWN));
}
};
typedef Window::WindowList WindowList;
}
#endif

View File

@ -0,0 +1,358 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: WindowManager 66 2008-07-14 21:54:09Z cubicool $
#ifndef OSGWIDGET_WINDOW_MANAGER
#define OSGWIDGET_WINDOW_MANAGER
#include <osg/Switch>
#include <osg/Uniform>
#include <osg/Drawable>
#include <osgGA/GUIEventAdapter>
#include <osgUtil/LineSegmentIntersector>
#include <osgViewer/View>
#include <osgWidget/ScriptEngine>
#include <osgWidget/StyleManager>
#include <osgWidget/Window>
namespace osgWidget {
// TODO: It should be possible to use something other than osgWidget/ViewerEventHandlers
// to handle all of these events. In fact, I need to create an SDL example showing this.
// A private typedef that we use for pickAtXY() below.
typedef osgUtil::LineSegmentIntersector::Intersections Intersections;
// A WindowManager performs pointer interaction with the topmost (highest Z) Widget,
// and performs keyboard input on the currently focused Window->Widget.
class OSGWIDGET_EXPORT WindowManager: public osg::Switch, public UIObjectParent<Window> {
public:
enum WM_FLAGS {
WM_USE_LUA = 0x00000001,
WM_USE_PYTHON = 0x00000002,
WM_PICK_DEBUG = 0x00000004,
WM_NO_INVERT_Y = 0x00000008,
WM_NO_BETA_WARN = 0x00000010
};
enum POINTER_DIRECTION {
PD_NONE = 0x00000000,
PD_LEFT = 0x00000001,
PD_RIGHT = 0x00000002,
PD_UP = 0x00000004,
PD_DOWN = 0x00000008
};
enum POINTER_FOCUS_MODE {
PFM_FOCUS = 0x00000000,
PFM_UNFOCUS = 0x00000001,
PFM_SLOPPY = 0x00000002
};
private:
// A functor used to sort the Windows by their Z component in descending order.
struct WindowZCompare: public std::binary_function<ptr_type, ptr_type, bool> {
bool operator()(const ptr_type& x, const ptr_type& y) {
return x.get()->getZ() > y.get()->getZ();
}
};
point_type _width;
point_type _height;
point_type _zNear;
point_type _zFar;
matrix_type _numForeground;
matrix_type _numBackground;
unsigned int _flags;
unsigned int _nodeMask;
osgViewer::View* _view;
float _lastX;
float _lastY;
EventInterface* _lastEvent;
EventInterface* _lastPush;
POINTER_DIRECTION _lastVertical;
POINTER_DIRECTION _lastHorizontal;
POINTER_FOCUS_MODE _focusMode;
bool _leftDown;
bool _middleDown;
bool _rightDown;
osgGA::GUIEventAdapter::ScrollingMotion _scrolling;
osg::ref_ptr<ScriptEngine> _lua;
osg::ref_ptr<ScriptEngine> _python;
osg::ref_ptr<StyleManager> _styleManager;
osg::observer_ptr<Widget> _widget;
osg::observer_ptr<Window> _focused;
osg::observer_ptr<Window> _pickWindow;
void childInserted (unsigned int);
void childRemoved (unsigned int, unsigned int);
bool _handleMousePushed (float, float, bool&);
bool _handleMouseReleased (float, float, bool&);
bool _haneldMouseScrolled (float, float, bool = false);
void _getPointerXYDiff (float&, float&);
void _updatePickWindow (const WidgetList*, point_type, point_type);
public:
META_Object(osgWidget, WindowManager);
WindowManager(
osgViewer::View* = 0,
point_type = 0.0f,
point_type = 0.0f,
unsigned int = 0,
unsigned int = 0
);
WindowManager(const WindowManager&, const osg::CopyOp&);
virtual ~WindowManager();
// A static method that will set both the _widget and _window data of an Event
// reference from a passed-in Interface.
static void setEventFromInterface(Event&, EventInterface*);
// A static template method that will iterate over a container and return a
// properly formed EventInterface*.
template<typename T>
static EventInterface* getFirstEventInterface(T&, Event&);
bool pickAtXY (float, float, WidgetList&);
bool setFocused (Window*);
void setPointerXY (float, float);
void setStyleManager (StyleManager*);
void resizeAllWindows (bool = true);
// Methods all called by the ViewerEventHandlers::MouseHandler object, or
// by some customer caller of your own. Examples of this to come...
bool pointerMove (float, float);
bool pointerDrag (float, float);
bool mouseScroll (float, float);
osg::Camera* createParentOrthoCamera();
unsigned int getNodeMask() const {
return _nodeMask;
}
point_type getWidth() const {
return _width;
}
point_type getHeight() const {
return _height;
}
bool isUsingLua() const {
return (_flags & WM_USE_LUA) != 0;
}
bool isUsingPython() const {
return (_flags & WM_USE_PYTHON) != 0;
}
bool isInvertedY() const {
return (_flags & WM_NO_INVERT_Y) == 0;
}
int getMouseKeysDown() const {
int flag = 0;
flag |= _leftDown ? osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON : 0;
flag |= _middleDown ? osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON: 0;
flag |= _rightDown ? osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON : 0;
return flag;
}
ScriptEngine* getLuaEngine() {
return _lua.get();
}
const ScriptEngine* getLuaEngine() const {
return _lua.get();
}
ScriptEngine* getPythonEngine() {
return _python.get();
}
const ScriptEngine* getPythonEngine() const {
return _python.get();
}
StyleManager* getStyleManager() {
return _styleManager.get();
}
const StyleManager* getStyleManager() const {
return _styleManager.get();
}
POINTER_DIRECTION getPointerVerticalDirection() const {
return _lastVertical;
}
POINTER_DIRECTION getPointerHorizontalDirection() const {
return _lastHorizontal;
}
POINTER_FOCUS_MODE getPointerFocusMode() const {
return _focusMode;
}
int getPointerDirectionVector() const {
return _lastVertical | _lastHorizontal;
}
bool isPointerMovingUp() const {
return _lastVertical == PD_UP;
}
bool isPointerMovingDown() const {
return _lastVertical == PD_DOWN;
}
bool isPointerMovingLeft() const {
return _lastHorizontal == PD_LEFT;
}
bool isPointerMovingRight() const {
return _lastHorizontal == PD_RIGHT;
}
bool isPointerMovingVertically() const {
return _lastVertical != PD_NONE;
}
bool isPointerMovingHorizontally() const {
return _lastHorizontal != PD_NONE;
}
bool isLeftMouseButtonDown() const {
return _leftDown;
}
bool isMiddleMouseButtonDown() const {
return _middleDown;
}
bool isRightMouseButtonDown() const {
return _rightDown;
}
bool isMouseScrollingUp() const {
return _scrolling == osgGA::GUIEventAdapter::SCROLL_UP;
}
bool isMouseScrollingDown() const {
return _scrolling == osgGA::GUIEventAdapter::SCROLL_DOWN;
}
bool setFocusedByName(const std::string& name) {
return setFocused(getByName(name));
}
void setScrollingMotion(osgGA::GUIEventAdapter::ScrollingMotion sm) {
_scrolling = sm;
}
void setPointerFocusMode(POINTER_FOCUS_MODE pfm) {
_focusMode = pfm;
}
void setWidth(point_type w) {
_width = w;
}
void setHeight(point_type h) {
_height = h;
}
void setSize(point_type w, point_type h) {
_width = w;
_height = h;
}
// Wrappers around the real calls. These only pertains to mouse buttons,
// particularly 3-button mice, although there are other more generic
// "pointer" API methods.
bool mousePushedLeft(float x, float y) {
return _handleMousePushed(x, y, _leftDown);
}
bool mousePushedMiddle(float x, float y) {
return _handleMousePushed(x, y, _middleDown);
}
bool mousePushedRight(float x, float y) {
return _handleMousePushed(x, y, _rightDown);
}
bool mouseReleasedLeft(float x, float y) {
return _handleMouseReleased(x, y, _leftDown);
}
bool mouseReleasedMiddle(float x, float y) {
return _handleMouseReleased(x, y, _middleDown);
}
bool mouseReleasedRight(float x, float y) {
return _handleMouseReleased(x, y, _rightDown);
}
// Keyboards wrappers, as above; takes the key and key's mask code, which
// can be compared to osgGA::GUIEventAdapter::{KeySymbol,KeyModMask}.
bool keyDown (int, int);
bool keyUp (int, int);
};
// We use a template here because the container could be a list or a vector; or something
// else that supports iteration!
template<typename T>
EventInterface* WindowManager::getFirstEventInterface(T& container, Event& ev) {
if(!container.size()) return 0;
// See if we can find a Widget that responds to this event...
for(typename T::iterator i = container.begin(); i != container.end(); i++) {
Widget* widget = i->get();
// If so, set the _widget/_window members and return it.
if(widget->getEventMask() & ev.type) {
ev._window = widget->getParent();
ev._widget = widget;
return widget;
}
}
// If we can't find a Widget that will accept this event, try and recurse all
// of the parent Windows and find one that can.
WindowList windowList;
Window* parent = container.back()->getParent();
if(parent) {
parent->getParentList(windowList);
// A WindowList from getParentList includes the Window the method was called
// on, and the entire tree of parentage.
for(WindowList::iterator i = windowList.begin(); i != windowList.end(); i++) {
Window* window = i->get();
if(window->getEventMask() & ev.type) {
ev._window = window;
return window;
}
}
}
return 0;
}
}
#endif

View File

@ -1,21 +1,31 @@
#the old construct SUBDIRS( was substituded by ADD_SUBDIRECTORY that is to be preferred according on CMake docs.
FOREACH( mylibfolder
OpenThreads
osg
osgDB
osgUtil
osgGA
osgText
osgManipulator
osgSim
osgFX
osgParticle
osgShadow
osgTerrain
osgViewer
)
OpenThreads
osg
osgDB
osgUtil
osgGA
osgText
osgManipulator
osgSim
osgFX
osgParticle
osgShadow
osgTerrain
osgViewer
)
ADD_SUBDIRECTORY(${mylibfolder})
ENDFOREACH( mylibfolder )
ENDFOREACH( mylibfolder )
OPTION(BUILD_OSGWIDGET "Enable to build osgWidget" ON)
IF (BUILD_OSGWIDGET)
ADD_SUBDIRECTORY(osgWidget)
ENDIF(BUILD_OSGWIDGET)
OPTION(BUILD_OSG_PLUGINS "Enable to build OSG Plugins" ON)
IF (BUILD_OSG_PLUGINS)
ADD_SUBDIRECTORY(osgPlugins)

View File

@ -166,6 +166,10 @@ IF(RSVG_FOUND AND CAIRO_FOUND)
ADD_SUBDIRECTORY(svg)
ENDIF(RSVG_FOUND AND CAIRO_FOUND)
IF (BUILD_OSGWIDGET)
ADD_SUBDIRECTORY(osgWidget)
ENDIF(BUILD_OSGWIDGET)
##########to get all the variables of Cmake
#GET_CMAKE_PROPERTY(MYVARS VARIABLES)

View File

@ -0,0 +1,113 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: Box.cpp 50 2008-05-06 05:06:36Z cubicool $
#include <osgDB/Registry>
#include <osgDB/Input>
#include <osgDB/Output>
#include <osgDB/FileUtils>
#include <osgWidget/Box>
bool osgWidget_Box_readData(osg::Object& obj, osgDB::Input& fr) {
/*
osgWidget::Box& box = static_cast<osgWidgegt::Box&>(obj);
if(fr[0].matchWord("skeleton") and fr[1].isString()) iter = loadFile(
"skeleton",
&osgCal::osgWidget_Box::loadSkeleton,
model,
fr
);
if(fr[0].matchWord("animation") and fr[1].isString()) iter = loadFile(
"animation",
&osgCal::osgWidget_Box::loadAnimation,
model,
fr
);
if(fr[0].matchWord("mesh") and fr[1].isString()) iter = loadFile(
"mesh",
&osgCal::osgWidget_Box::loadMesh,
model,
fr
);
if(fr[0].matchWord("material") and fr[1].isString()) iter = loadFile(
"material",
&osgCal::osgWidget_Box::loadMaterial,
model,
fr
);
*/
osgWidget::warn() << "Box read" << std::endl;
return false;
}
bool osgWidget_Box_writeData(const osg::Object& obj, osgDB::Output& fw) {
const osgWidget::Box& model = static_cast<const osgWidget::Box&>(obj);
fw.indent() << fw.wrapString("Box stuff...") << std::endl;
return true;
}
/*
bool Model_readData(osg::Object& obj, osgDB::Input& fr) {
bool iter = false;
osgCal::Model& model = static_cast<osgCal::Model&>(obj);
osgCal::osgWidget_Box* core = static_cast<osgCal::osgWidget_Box*>(
fr.readObjectOfType(osgCal::osgWidget_Box("dummy"))
);
if(core) {
model.create(core);
iter = true;
}
if(fr.matchSequence("StartAnimation")) {
if(fr[1].isString()) {
int animation = core->getAnimationId(fr[1].getStr());
if(animation >= 0) model.startLoop(animation, 1.0f, 0.0f);
else osg::notify(osg::WARN)
<< "Couldn't start animation: " << fr[1].getStr()
<< std::endl
;
iter = true;
fr += 2;
}
}
return iter;
}
bool Model_writeData(const osg::Object& obj, osgDB::Output& fw) {
const osgCal::Model& model = static_cast<const osgCal::Model&>(obj);
fw.writeObject(*model.getosgWidget_Box());
return true;
}
osgDB::RegisterDotOsgWrapperProxy g_ModelProxy(
new osgCal::Model,
"Model",
"Object Node Model",
&Model_readData,
&Model_writeData
);
*/
osgDB::RegisterDotOsgWrapperProxy g_osgWidget_BoxProxy(
new osgWidget::Box("unset"),
"osgWidget::Box",
"Object Node Group Transform MatrixTransform osgWidget::Box",
&osgWidget_Box_readData,
&osgWidget_Box_writeData
);

View File

@ -0,0 +1,19 @@
#this file is automatically generated
SET(TARGET_SRC
Box.cpp
EmbeddedWindow.cpp
Frame.cpp
Input.cpp
Label.cpp
Table.cpp
Widget.cpp
WindowManager.cpp
)
SET(TARGET_ADDED_LIBRARIES osgWidget )
#### end var setup ###
SETUP_PLUGIN(osgwisget)

View File

@ -0,0 +1,32 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: EmbeddedWindow.cpp 50 2008-05-06 05:06:36Z cubicool $
#include <osgDB/Registry>
#include <osgDB/Input>
#include <osgDB/Output>
#include <osgDB/FileUtils>
#include <osgWidget/Window>
bool osgWidget_EmbeddedWindow_readData(osg::Object& obj, osgDB::Input& fr) {
osgWidget::warn() << "EmbeddedWindow read" << std::endl;
return false;
}
bool osgWidget_EmbeddedWindow_writeData(const osg::Object& obj, osgDB::Output& fw) {
const osgWidget::Window::EmbeddedWindow& model =
static_cast<const osgWidget::Window::EmbeddedWindow&>(obj)
;
fw.indent() << fw.wrapString("EmbeddedWindow stuff...") << std::endl;
return true;
}
osgDB::RegisterDotOsgWrapperProxy g_osgWidget_EmbeddedWindowProxy(
new osgWidget::Window::EmbeddedWindow("unset"),
"osgWidget::Window::EmbeddedWindow",
"Object Drawable Geometry osgWidget::Widget osgWidget::Window::EmbeddedWindow",
&osgWidget_EmbeddedWindow_readData,
&osgWidget_EmbeddedWindow_writeData
);

View File

@ -0,0 +1,30 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: Frame.cpp 50 2008-05-06 05:06:36Z cubicool $
#include <osgDB/Registry>
#include <osgDB/Input>
#include <osgDB/Output>
#include <osgDB/FileUtils>
#include <osgWidget/Frame>
bool osgWidget_Frame_readData(osg::Object& obj, osgDB::Input& fr) {
osgWidget::warn() << "Frame read" << std::endl;
return false;
}
bool osgWidget_Frame_writeData(const osg::Object& obj, osgDB::Output& fw) {
const osgWidget::Frame& model = static_cast<const osgWidget::Frame&>(obj);
fw.indent() << fw.wrapString("Frame stuff...") << std::endl;
return true;
}
osgDB::RegisterDotOsgWrapperProxy g_osgWidget_FrameProxy(
new osgWidget::Frame("unset"),
"osgWidget::Frame",
"Object Node Group Transform MatrixTransform osgWidget::Table osgWidget::Frame",
&osgWidget_Frame_readData,
&osgWidget_Frame_writeData
);

View File

@ -0,0 +1,30 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: Input.cpp 50 2008-05-06 05:06:36Z cubicool $
#include <osgDB/Registry>
#include <osgDB/Input>
#include <osgDB/Output>
#include <osgDB/FileUtils>
#include <osgWidget/Input>
bool osgWidget_Input_readData(osg::Object& obj, osgDB::Input& fr) {
osgWidget::warn() << "Input read" << std::endl;
return false;
}
bool osgWidget_Input_writeData(const osg::Object& obj, osgDB::Output& fw) {
const osgWidget::Input& model = static_cast<const osgWidget::Input&>(obj);
fw.indent() << fw.wrapString("Input stuff...") << std::endl;
return true;
}
osgDB::RegisterDotOsgWrapperProxy g_osgWidget_InputProxy(
new osgWidget::Input("unset"),
"osgWidget::Input",
"Object Drawable Geometry osgWidget::Widget osgWidget::Input",
&osgWidget_Input_readData,
&osgWidget_Input_writeData
);

View File

@ -0,0 +1,30 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: Label.cpp 50 2008-05-06 05:06:36Z cubicool $
#include <osgDB/Registry>
#include <osgDB/Input>
#include <osgDB/Output>
#include <osgDB/FileUtils>
#include <osgWidget/Label>
bool osgWidget_Label_readData(osg::Object& obj, osgDB::Input& fr) {
osgWidget::warn() << "Label read" << std::endl;
return false;
}
bool osgWidget_Label_writeData(const osg::Object& obj, osgDB::Output& fw) {
const osgWidget::Label& model = static_cast<const osgWidget::Label&>(obj);
fw.indent() << fw.wrapString("Label stuff...") << std::endl;
return true;
}
osgDB::RegisterDotOsgWrapperProxy g_osgWidget_LabelProxy(
new osgWidget::Label("unset"),
"osgWidget::Label",
"Object Drawable Geometry osgWidget::Widget osgWidget::Label",
&osgWidget_Label_readData,
&osgWidget_Label_writeData
);

View File

@ -0,0 +1,30 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: Table.cpp 50 2008-05-06 05:06:36Z cubicool $
#include <osgDB/Registry>
#include <osgDB/Input>
#include <osgDB/Output>
#include <osgDB/FileUtils>
#include <osgWidget/Table>
bool osgWidget_Table_readData(osg::Object& obj, osgDB::Input& fr) {
osgWidget::warn() << "Table read" << std::endl;
return false;
}
bool osgWidget_Table_writeData(const osg::Object& obj, osgDB::Output& fw) {
const osgWidget::Table& model = static_cast<const osgWidget::Table&>(obj);
fw.indent() << fw.wrapString("Table stuff...") << std::endl;
return true;
}
osgDB::RegisterDotOsgWrapperProxy g_osgWidget_TableProxy(
new osgWidget::Table("unset"),
"osgWidget::Table",
"Object Node Group Transform MatrixTransform osgWidget::Table",
&osgWidget_Table_readData,
&osgWidget_Table_writeData
);

View File

@ -0,0 +1,75 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: Widget.cpp 50 2008-05-06 05:06:36Z cubicool $
#include <osgDB/Registry>
#include <osgDB/Input>
#include <osgDB/Output>
#include <osgDB/FileUtils>
#include <osgWidget/Util>
#include <osgWidget/Widget>
bool osgWidget_Widget_readData(osg::Object& obj, osgDB::Input& fr) {
osgWidget::warn() << "Widget read" << std::endl;
return false;
}
bool osgWidget_Widget_writeData(const osg::Object& obj, osgDB::Output& fw) {
const osgWidget::Widget& model = static_cast<const osgWidget::Widget&>(obj);
fw.indent() << fw.wrapString("Widget stuff...") << std::endl;
return true;
}
bool osgWidget_NotifyWidget_readData(osg::Object& obj, osgDB::Input& fr) {
osgWidget::warn() << "NotifyWidget read" << std::endl;
return false;
}
bool osgWidget_NotifyWidget_writeData(const osg::Object& obj, osgDB::Output& fw) {
const osgWidget::NotifyWidget& model = static_cast<const osgWidget::NotifyWidget&>(obj);
fw.indent() << fw.wrapString("NotifyWidget stuff...") << std::endl;
return true;
}
bool osgWidget_NullWidget_readData(osg::Object& obj, osgDB::Input& fr) {
osgWidget::warn() << "NullWidget read" << std::endl;
return false;
}
bool osgWidget_NullWidget_writeData(const osg::Object& obj, osgDB::Output& fw) {
const osgWidget::NullWidget& model = static_cast<const osgWidget::NullWidget&>(obj);
fw.indent() << fw.wrapString("NullWidget stuff...") << std::endl;
return true;
}
osgDB::RegisterDotOsgWrapperProxy g_osgWidget_WidgetProxy(
new osgWidget::Widget("unset"),
"osgWidget::Widget",
"Object Drawable Geometry osgWidget::Widget",
&osgWidget_Widget_readData,
&osgWidget_Widget_writeData
);
osgDB::RegisterDotOsgWrapperProxy g_osgWidget_NotifyWidgetProxy(
new osgWidget::NotifyWidget("unset"),
"osgWidget::NotifyWidget",
"Object Drawable Geometry osgWidget::Widget osgWidget::NotifyWidget",
&osgWidget_NotifyWidget_readData,
&osgWidget_NotifyWidget_writeData
);
osgDB::RegisterDotOsgWrapperProxy g_osgWidget_NullWidgetProxy(
new osgWidget::Widget("unset"),
"osgWidget::NullWidget",
"Object Drawable Geometry osgWidget::Widget osgWidget::NullWidget",
&osgWidget_NullWidget_readData,
&osgWidget_NullWidget_writeData
);

View File

@ -0,0 +1,30 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: WindowManager.cpp 50 2008-05-06 05:06:36Z cubicool $
#include <osgDB/Registry>
#include <osgDB/Input>
#include <osgDB/Output>
#include <osgDB/FileUtils>
#include <osgWidget/WindowManager>
bool osgWidget_WindowManager_readData(osg::Object& obj, osgDB::Input& fr) {
osgWidget::warn() << "WindowManager read" << std::endl;
return false;
}
bool osgWidget_WindowManager_writeData(const osg::Object& obj, osgDB::Output& fw) {
const osgWidget::WindowManager& model = static_cast<const osgWidget::WindowManager&>(obj);
fw.indent() << fw.wrapString("WindowManager stuff...") << std::endl;
return true;
}
osgDB::RegisterDotOsgWrapperProxy g_osgWidget_WindowManagerProxy(
new osgWidget::WindowManager(),
"osgWidget::WindowManager",
"Object Node Group Switch osgWidget::WindowManager",
&osgWidget_WindowManager_readData,
&osgWidget_WindowManager_writeData
);

194
src/osgWidget/Box.cpp Normal file
View File

@ -0,0 +1,194 @@
// -*-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):
Window (name),
_boxType (bt),
_uniform (uniform),
_lastAdd (0) {
}
Box::Box(const Box& box, const osg::CopyOp& co):
Window (box, co),
_boxType (box._boxType),
_uniform (box._uniform),
_lastAdd (box._lastAdd) {
}
// TODO: Here's something to consider! If we resize the box by 1 every time, only the
// first resizable Widget will continue to get larger. This is really silly.
void Box::_resizeImplementation(point_type w, point_type h) {
// Get the number of Widgets that agree to fill. Also perfom some casting to integers
// in case we're being request to resize with pixel perfection.
point_type numFill = _getNumFill();
int iw = static_cast<int>(w);
int ih = static_cast<int>(h);
int inumFill = static_cast<int>(numFill);
int wrem = 0;
int hrem = 0;
// If we have some widgets that fill, use these variables to keep a running count
// of what needs to be added.
if(inumFill) {
wrem = iw % inumFill;
hrem = ih % inumFill;
}
// If we have any widgets that agree to fill and there has been an honest resize
// request, handle it here. The first case handles resizes where we have AT LEAST
// as many pixels to fill as we have objects.
if(numFill > 0.0f && (w != 0.0f || h != 0.0f)) {
unsigned int cur = 0;
for(Iterator i = begin(); i != end(); i++) if(i->valid() && i->get()->canFill()) {
point_type addWidth = 0.0f;
point_type addHeight = 0.0f;
// If our last added-to Widget was the last one, reset it to 0.
if(_lastAdd >= size()) _lastAdd = 0;
// We EVENLY give any remaining space to all fillable Widgets. In the
// future we may want to be able to specify a fill "percent", which
// would be some portion of the total available space.
if(_boxType == HORIZONTAL) {
if(w) {
addWidth += static_cast<point_type>(iw / inumFill);
if(cur >= _lastAdd && wrem) {
_lastAdd++;
addWidth++;
wrem--;
}
}
if(h) addHeight += h;
}
else {
if(w) addWidth += w;
if(h) {
addHeight += static_cast<point_type>(ih / inumFill);
if(cur >= _lastAdd && hrem) {
_lastAdd++;
addHeight++;
hrem--;
}
}
}
if(addWidth != 0.0f) i->get()->addWidth(addWidth);
if(addHeight != 0.0f) i->get()->addHeight(addHeight);
cur++;
}
}
// Get the width and height of our largest widgets; these values take
// into account the padding, and will be affected by any resizing that occured above.
point_type maxWidth = _getMaxWidgetWidthTotal();
point_type maxHeight = _getMaxWidgetHeightTotal();
// Create counters for the various offsets as we position Widgets.
point_type xoff = 0.0f;
point_type yoff = 0.0f;
point_type xadd = 0.0f;
point_type yadd = 0.0f;
for(Iterator i = begin(); i != end(); i++) {
Widget* widget = i->get();
// This positioning works by setting each Widget's unmodified origin and then
// letting Window::_positionWidget calculate the padding/fill.
if(_boxType == HORIZONTAL) {
// First, lets set it to the proper x offset, ignoring any padding.
widget->setOrigin(xoff, 0.0f);
// Immediately reset our xoff for the next iteration.
if(_uniform) {
_positionWidget(widget, maxWidth, maxHeight);
xadd = maxWidth;
}
else {
_positionWidget(widget, widget->getWidthTotal(), maxHeight);
xadd = widget->getWidthTotal();
}
}
else {
widget->setOrigin(0.0f, yoff);
if(_uniform) {
_positionWidget(widget, maxWidth, maxHeight);
yadd = maxHeight;
}
else {
_positionWidget(widget, maxWidth, widget->getHeightTotal());
yadd = widget->getHeightTotal();
}
}
xoff += xadd;
yoff += yadd;
}
}
Window::Sizes Box::_getWidthImplementation() const {
// The width of a horizontal box is all of the widgets added together.
if(_boxType == HORIZONTAL) {
// If we're a uniformly sized box, our width is our largest width plus our
// largest padding, multiplied times the number of widgets. Our minimum width
// is the size of the largest minWidth times the number of widgets.
if(_uniform) return Sizes(
_getMaxWidgetWidthTotal() * size(),
_getMaxWidgetMinWidthTotal() * size()
);
// Othweriwse, our width is all of the widths added together, and our minWidth
// is all of the minWidths added together.
else return Sizes(
_accumulate<Plus>(&Widget::getWidthTotal),
_accumulate<Plus>(&Widget::getMinWidthTotal)
);
}
// If we're a vertical Box, our width is the width of the larget Widget in the group.
// Our minWidth is the largest minWidth of the Widgets in the group.
else return Sizes(
_getMaxWidgetWidthTotal(),
_getMaxWidgetMinWidthTotal()
);
}
Window::Sizes Box::_getHeightImplementation() const {
if(_boxType == VERTICAL) {
if(_uniform) return Sizes(
_getMaxWidgetHeightTotal() * size(),
_getMaxWidgetMinHeightTotal() * size()
);
else return Sizes(
_accumulate<Plus>(&Widget::getHeightTotal),
_accumulate<Plus>(&Widget::getMinHeightTotal)
);
}
else return Sizes(
_getMaxWidgetHeightTotal(),
_getMaxWidgetMinHeightTotal()
);
}
}

View File

@ -0,0 +1,66 @@
IF (DYNAMIC_OPENSCENEGRAPH)
ADD_DEFINITIONS(-DOSGWIDGET_LIBRARY)
ELSE (DYNAMIC_OPENSCENEGRAPH)
ADD_DEFINITIONS(-DOSG_LIBRARY_STATIC)
ENDIF(DYNAMIC_OPENSCENEGRAPH)
SET(LIB_NAME osgWidget)
SET(HEADER_PATH ${OpenSceneGraph_SOURCE_DIR}/include/${LIB_NAME})
SET(LIB_PUBLIC_HEADERS
${HEADER_PATH}/Export
${HEADER_PATH}/Box
${HEADER_PATH}/Canvas
${HEADER_PATH}/EventInterface
${HEADER_PATH}/Frame
${HEADER_PATH}/Input
${HEADER_PATH}/Label
${HEADER_PATH}/Lua
${HEADER_PATH}/Python
${HEADER_PATH}/ScriptEngine
${HEADER_PATH}/StyleInterface
${HEADER_PATH}/StyleManager
${HEADER_PATH}/Table
${HEADER_PATH}/Types
${HEADER_PATH}/UIObjectParent
${HEADER_PATH}/Util
${HEADER_PATH}/Version
${HEADER_PATH}/ViewerEventHandlers
${HEADER_PATH}/Widget
${HEADER_PATH}/Window
${HEADER_PATH}/WindowManager
)
# FIXME: For OS X, need flag for Framework or dylib
ADD_LIBRARY(${LIB_NAME}
${OPENSCENEGRAPH_USER_DEFINED_DYNAMIC_OR_STATIC}
${LIB_PUBLIC_HEADERS}
Box.cpp
Canvas.cpp
CMakeLists.txt
Frame.cpp
Input.cpp
Label.cpp
Lua.cpp
Python.cpp
StyleManager.cpp
Table.cpp
Util.cpp
Version.cpp
ViewerEventHandlers.cpp
Widget.cpp
Window.cpp
WindowManager.cpp
)
SET(TARGET_LIBRARIES_VARS FREETYPE_LIBRARY )
LINK_INTERNAL(${LIB_NAME}
osgText
osgViewer
osgDB
osg
OpenThreads
)
LINK_CORELIB_DEFAULT(${LIB_NAME})
INCLUDE(ModuleInstall OPTIONAL)

32
src/osgWidget/Canvas.cpp Normal file
View File

@ -0,0 +1,32 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: Canvas.cpp 66 2008-07-14 21:54:09Z cubicool $
#include <osgWidget/Canvas>
namespace osgWidget {
Canvas::Canvas(const std::string& name):
Window(name) {
}
Canvas::Canvas(const Canvas& canvas, const osg::CopyOp& co):
Window(canvas, co) {
}
void Canvas::_resizeImplementation(point_type w, point_type h) {
// A Canvas has no layout, so it doesn't really know how to honor a resize
// request. :) The best I could do here is store the differences and add them
// later to the calls to getWidth/getHeight.
}
bool Canvas::addWidget(Widget* widget, point_type x, point_type y) {
if(Window::addWidget(widget)) {
widget->setOrigin(x, y);
return true;
}
return false;
}
}

251
src/osgWidget/Frame.cpp Normal file
View File

@ -0,0 +1,251 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: Frame.cpp 59 2008-05-15 20:55:31Z cubicool $
#include <osgDB/ReadFile>
#include <osgWidget/WindowManager>
#include <osgWidget/Frame>
namespace osgWidget {
std::string Frame::cornerToString(CORNER c) {
if(c == CORNER_LOWER_LEFT) return "CornerLowerLeft";
else if(c == CORNER_LOWER_RIGHT) return "CornerLowerRight";
else if(c == CORNER_UPPER_RIGHT) return "CornerUpperRight";
else return "CornerUpperLeft";
}
std::string Frame::borderToString(BORDER b) {
if(b == BORDER_LEFT) return "BorderLeft";
else if(b == BORDER_RIGHT) return "BorderRight";
else if(b == BORDER_TOP) return "BorderTop";
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(const Corner& corner, const osg::CopyOp& co):
Widget (corner, co),
_corner (corner._corner) {
}
bool Frame::Corner::mouseDrag(double x, double y, WindowManager* wm) {
Window* parent = getParent();
if(!parent) return false;
if(wm->isInvertedY()) {
if(_corner == CORNER_UPPER_LEFT) {
if(parent->resizeAdd(-x, -y)) parent->addOrigin(x, y);
}
else if(_corner == CORNER_UPPER_RIGHT) {
if(parent->resizeAdd(x, -y)) parent->addY(y);
}
else if(_corner == CORNER_LOWER_RIGHT) parent->resizeAdd(x, y);
else {
if(parent->resizeAdd(-x, y)) parent->addX(x);
}
}
// 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);
}
}
parent->update();
return true;
}
Frame::Border::Border(BORDER border, point_type width, point_type height):
Widget (borderToString(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) {
}
bool Frame::Border::mouseDrag(double x, double y, WindowManager* wm) {
Window* parent = getParent();
if(!parent) 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(_border == BORDER_TOP) parent->addOrigin(x, y);
else {
// The only BORDER that inverted-Y affects is this...
if(wm->isInvertedY()) parent->resizeAdd(0.0f, y);
else {
if(parent->resizeAdd(0.0f, -y)) parent->addY(y);
}
}
parent->update();
return true;
}
Frame::Frame(const std::string& name):
Table(name, 3, 3) {
}
Frame::Frame(const Frame& frame, const osg::CopyOp& co):
Table(frame, co) {
}
Widget* Frame::_getCorner(CORNER c) const {
return const_cast<Widget*>(getByName(cornerToString(c)));
}
Widget* Frame::_getBorder(BORDER b) const {
return const_cast<Widget*>(getByName(borderToString(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) {
if(!window) return false;
EmbeddedWindow* ew = getEmbeddedWindow();
// If it's the first time setting the Window...
// if(!ew || !ew->getWindow()) return addWidget(window->embed(), 1, 1);
if(!ew) return addWidget(window->embed(), 1, 1);
else return ew->setWindow(window);
}
Frame* Frame::createSimpleFrame(
const std::string& name,
point_type cw,
point_type ch,
point_type w,
point_type h,
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);
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);
EmbeddedWindow* ew = new EmbeddedWindow(name, w, h);
ew->setCanFill(true);
frame->addWidget(ew, 1, 1);
return frame;
}
Frame* Frame::createSimpleFrameWithSingleTexture(
const std::string& name,
const std::string& texture,
point_type tw,
point_type th,
point_type cw,
point_type ch,
point_type w,
point_type h,
Frame* exFrame
) {
Frame* frame = 0;
// The same as above...
if(!exFrame) frame = createSimpleFrame(name, cw, ch, w, h);
else frame = createSimpleFrame(name, cw, ch, w, h, exFrame);
for(unsigned int i = 0; i < 9; i++) frame->getObjects()[i]->setImage(texture);
frame->getByRowCol(0, 0)->setTexCoordRegion(0.0f, th - ch, cw, ch);
frame->getByRowCol(0, 1)->setTexCoordRegion(cw, th - ch, tw - (cw * 2.0f), ch);
frame->getByRowCol(0, 2)->setTexCoordRegion(tw - cw, th - ch, cw, ch);
frame->getByRowCol(1, 0)->setTexCoordRegion(0.0f, ch, cw, th - (ch * 2.0f));
frame->getByRowCol(1, 2)->setTexCoordRegion(tw - cw, ch, cw, th - (ch * 2.0f));
frame->getByRowCol(2, 0)->setTexCoordRegion(0.0f, 0.0f, cw, ch);
frame->getByRowCol(2, 1)->setTexCoordRegion(cw, 0.0f, tw - (cw * 2.0f), ch);
frame->getByRowCol(2, 2)->setTexCoordRegion(tw - cw, 0.0f, cw, ch);
frame->getEmbeddedWindow()->setTexCoordRegion(cw, ch, tw - (cw * 2.0f), th - (ch * 2.0f));
return frame;
}
}

176
src/osgWidget/Input.cpp Normal file
View File

@ -0,0 +1,176 @@
// -*-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>
#include <osgWidget/Input>
namespace osgWidget {
Input::Input(const std::string& name, const std::string& label, unsigned int size):
Label (name, label),
_xoff (0.0f),
_yoff (0.0f),
_index (0),
_size (0),
_cursorIndex (0),
_maxSize (size),
_cursor (new Widget("cursor")) {
_text->setAlignment(osgText::Text::LEFT_BOTTOM_BASE_LINE);
_text->setKerningType(osgText::KERNING_NONE);
// Make the cursor un-copyable.
_cursor->setCanClone(false);
_cursor->setDataVariance(osg::Object::DYNAMIC);
_cursor->setColor(0.0f, 0.0f, 0.0f, 0.0f);
setEventMask(
// For showing/hiding the "cursor."
EVENT_MASK_FOCUS |
// For keypresses, obviously.
EVENT_MASK_KEY |
// For "click" focusing.
EVENT_MOUSE_PUSH
);
_offsets.resize(size, 0.0f);
_text->getText().resize(size, ' ');
_text->update();
}
void Input::_calculateSize(const XYCoord& size) {
// An Input cannot currently set it's own size RELIABLY until the osgText implementation
// is dratiscally improved. I'm getting wildly crazy results. :(
// point_type height = size.y() > _cursor->getHeight() ? size.y() : _cursor->getHeight();
point_type width = size.x() + _cursor->getWidth();
point_type height = _cursor->getHeight();
if(width > getWidth()) setWidth(osg::round(width));
if(height > getHeight()) setHeight(osg::round(height));
}
void Input::_calculateCursorOffsets() {
// Determine the "offset"
const osgText::Text::TextureGlyphQuadMap& tgqm = _text->getTextureGlyphQuadMap();
const osgText::Text::TextureGlyphQuadMap::const_iterator tgqmi = tgqm.begin();
const osgText::Text::GlyphQuads& gq = tgqmi->second;
point_type accum = 0.0f;
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)];
accum += osg::round(lr.x() - ll.x());
_offsets[i] = accum;
os << _offsets[i] << " (" << static_cast<char>(_text->getText()[i]) << ") ";
}
os << "]" << std::endl;
}
bool Input::focus(WindowManager*) {
_cursor->setColor(1.0f, 1.0f, 1.0f, 0.5f);
return true;
}
bool Input::unfocus(WindowManager*) {
_cursor->setColor(0.0f, 0.0f, 0.0f, 0.0f);
return true;
}
void Input::parented(Window* parent) {
Label::parented(parent);
_cursor->setSize(2.0f, _text->getCharacterHeight());
if(_cursorIndex) parent->getGeode()->setDrawable(_cursorIndex, _cursor.get());
else _cursorIndex = parent->addDrawableAndGetIndex(_cursor.get());
}
void Input::positioned() {
point_type ln = static_cast<point_type>(_text->getLineCount());
ln = ln == 0.0f ? 1.0f : ln;
point_type th =
(_text->getCharacterHeight() * ln) +
(_text->getLineSpacing() * (ln - 1.0f))
;
point_type x = getX() + _xoff;
point_type y = getY() + th + _yoff;
// XYCoord size = getTextSize();
_text->setPosition(osg::Vec3(x, y, _calculateZ(LAYER_MIDDLE)));
point_type xoffset = _index > 0 ? _offsets[_index - 1] : 0.0f;
_cursor->setOrigin(x + xoffset + 1.0f, y - _cursor->getHeight() + 1.0f);
_cursor->setZ(_calculateZ(LAYER_MIDDLE));
}
bool Input::keyUp(int key, int mask, WindowManager*) {
return false;
}
bool Input::keyDown(int key, int mask, WindowManager*) {
/*
osgText::String& s = _text->getText();
if(key == osgGA::GUIEventAdapter::KEY_BackSpace) {
if(_index >= 1) {
// s.erase(s.begin() + (_index - 1));
s[_index - 1] = ' ';
_text->update();
_calculateCursorOffsets();
_index--;
}
}
else {
if(key > 255 || _index >= _maxSize) return false;
// else if(_index < s.size()) s.insert(s.begin() + _index, key);
// else if(_index == s.size()) s.push_back(key);
s[_index] = key;
_text->update();
_calculateCursorOffsets();
_index++;
}
// _text->update();
_calculateSize(getTextSize());
getParent()->resize();
*/
warn() << "Input is disabled until someone can help me understand how to use osgText; sorry..." << std::endl;
return false;
}
}

140
src/osgWidget/Label.cpp Normal file
View File

@ -0,0 +1,140 @@
// -*-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>
#include <osgWidget/Label>
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->setAlignment(osgText::Text::LEFT_BOTTOM);
_text->setDataVariance(osg::Object::DYNAMIC);
// TODO: Make a patch for this!
// If you're wondering why we don't use this let me explain...
//
// _text->setAlignment(osgText::Text::CENTER_CENTER);
//
// When you set the position of an osgText::Text object which has a CENTER_CENTER
// alignment, the internal implementation of osgText may give it values that have
// a "decimal" portion, which is NO GOOD on orthographic 2D displays where we
// want "pixel perfect" ratios. Thus, until I can remedy this internally with
// osgText::Text, I will need to calculate the center myself.
setColor(0.0f, 0.0f, 0.0f, 0.0f);
}
Label::Label(const Label& label, const osg::CopyOp& co):
Widget (label, co),
_textIndex (label._textIndex) {
_text = new osgText::Text(*label._text, co);
}
void Label::_calculateSize(const XYCoord& size) {
if(size.x() && size.y()) setMinimumSize(size.x(), size.y());
if(getWidth() < size.x()) setWidth(size.x());
if(getHeight() < size.y()) setHeight(size.y());
}
// 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());
// Otherwise, add it as new.
else _textIndex = parent->addDrawableAndGetIndex(_text.get());
}
void Label::unparented(Window* parent) {
if(_textIndex) parent->getGeode()->removeDrawable(_text.get());
_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;
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;
warn() << "Label XY coords : " << getX() << " x " << getY() << std::endl;
warn() << "Label BB in size : " << size.x() << " x " << size.y() << std::endl;
warn() << "Label xy position : " << x << " y " << y << std::endl;
warn() << "------------------------------------" << std::endl;
*/
_text->setPosition(osg::Vec3(x, y, _calculateZ(getLayer() + 1)));
}
void Label::setLabel(const std::string& label) {
_text->setText(label);
_calculateSize(getTextSize());
}
void Label::setFont(const std::string& font) {
_text->setFont(font);
_calculateSize(getTextSize());
}
void Label::setFontSize(unsigned int size) {
_text->setCharacterSize(size);
_text->setFontResolution(size, size);
_calculateSize(getTextSize());
}
void Label::setFontColor(const Color& c) {
_text->setColor(c);
}
void Label::setShadow(point_type offset) {
_text->setBackdropType(osgText::Text::DROP_SHADOW_BOTTOM_RIGHT);
_text->setBackdropImplementation(osgText::Text::NO_DEPTH_BUFFER);
_text->setBackdropOffset(offset);
_calculateSize(getTextSize());
}
XYCoord Label::getTextSize() const {
osg::BoundingBox bb = _text->getBound();
return XYCoord(
osg::round(bb.xMax() - bb.xMin()),
osg::round(bb.yMax() - bb.yMin())
);
}
}

171
src/osgWidget/Lua.cpp Normal file
View File

@ -0,0 +1,171 @@
// -*-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>
#include <osgWidget/Box>
#include <osgWidget/WindowManager>
// If you want to build with LUA, include it--otherwise, typedef some of the data types
// so that we don't pollute our code too much with conditional includes.
#ifdef OSGWIDGET_USELUA
extern "C" {
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
}
#endif
namespace osgWidget {
// This namespace will include all of our Lua library functions. Otherwise, it'll be
// an empty namespace. This is 100% for code clarity, as this namespace is internal and
// not visible to the outside C/C++ world.
namespace lua {
#ifdef OSGWIDGET_USELUA
// Strings representing our global REGISTRY values.
const char* G_WM = "osgWidget_G_WindowManager";
WindowManager* getWindowManager(lua_State* L) {
lua_pushstring(L, G_WM);
lua_gettable(L, LUA_REGISTRYINDEX);
return reinterpret_cast<WindowManager*>(lua_touserdata(L, -1));
}
int newWindow(lua_State* L) {
osg::ref_ptr<Window> w = new Box("testLUA", Box::HORIZONTAL);
lua_pushstring(L, w->getName().c_str());
return 1;
}
int newWidget(lua_State* L) {
osg::ref_ptr<Widget> w = new Widget("testLUA", 0.0f, 0.0f);
lua_pushstring(L, w->getName().c_str());
return 1;
}
int getWindow(lua_State* L) {
WindowManager* wm = getWindowManager(L);
lua_pushlightuserdata(L, wm);
return 1;
}
#endif
}
// A helper function for all those cases where we need to inform the user that there isn't
// a LUA engine available.
bool noLuaFail(const std::string& err) {
warn() << err << "; Lua not compiled in library." << std::endl;
return false;
}
// Our "private", internal data.
struct LuaEngineData {
#ifdef OSGWIDGET_USELUA
LuaEngineData():
lua(0) {
}
lua_State* lua;
#endif
};
LuaEngine::LuaEngine(WindowManager* wm):
_wm(wm) {
#ifdef OSGWIDGET_USELUA
_data = new LuaEngineData();
#else
_data = 0;
#endif
}
bool LuaEngine::initialize() {
#ifdef OSGWIDGET_USELUA
_data->lua = lua_open();
luaL_openlibs(_data->lua);
static const struct luaL_reg library[] = {
{"newWindow", lua::newWindow},
{"newWidget", lua::newWidget},
{"getWindow", lua::getWindow},
{0, 0}
};
luaL_openlib(_data->lua, "osgwidget", library, 0);
// An alternative to using the Registry here would be to pass the WindowManager
// as a userdata "closure" (pvalue). Please see the following doc on more info:
// http://www.lua.org/pil/27.3.3.html
lua_pushstring(_data->lua, lua::G_WM);
lua_pushlightuserdata(_data->lua, _wm);
lua_settable(_data->lua, LUA_REGISTRYINDEX);
return true;
#else
return noLuaFail("Can't initialize the LuaEngine");
#endif
}
bool LuaEngine::close() {
#ifdef OSGWIDGET_USELUA
lua_close(_data->lua);
delete _data;
return true;
#else
return noLuaFail("Can't close the LuaEngine");
#endif
}
bool LuaEngine::eval(const std::string& code) {
#ifdef OSGWIDGET_USELUA
if(luaL_dostring(_data->lua, code.c_str())) {
warn() << "LuaEngine::eval - " << lua_tostring(_data->lua, -1) << std::endl;
return false;
}
return true;
#else
return noLuaFail("Can't evaluate code in LuaEngine");
#endif
}
bool LuaEngine::runFile(const std::string& filePath) {
#ifdef OSGWIDGET_USELUA
if(!osgDB::fileExists(filePath)) {
warn() << "Couldn't find file \"" << filePath << "\" for LuaEngine." << std::endl;
return false;
}
if(luaL_dofile(_data->lua, filePath.c_str())) {
warn() << "LuaEngine::runFile - " << lua_tostring(_data->lua, -1) << std::endl;
return false;
}
return true;
#else
return noLuaFail("Can't run file in LuaEngine");
#endif
}
}

215
src/osgWidget/Python.cpp Normal file
View File

@ -0,0 +1,215 @@
// -*-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
#include <Python.h>
#endif
#include <osgDB/FileUtils>
#include <osgWidget/Python>
#include <osgWidget/Box>
#include <osgWidget/WindowManager>
namespace osgWidget {
// Our Python library.
namespace py {
#ifdef OSGWIDGET_USEPYTHON
// TODO: Until I can find a way to move data around inside of the context, this will
// have to do. I don't really like it, but I've got no choice.
static PyObject* G_ERR = 0;
PyObject* newWindow(PyObject* self, PyObject* args) {
PyObject* buffer = 0;
const char* name = 0;
int width = 0;
int height = 0;
/*
if(PyArg_ParseTuple(args, "sO!ii", &name, &PyBuffer_Type, &buffer, &width, &height)) {
const void* buf = 0;
int len = 0;
if(!PyObject_AsReadBuffer(buffer, &buf, &len)) {
// if(Database::instance().add(name, buf, width, height))
return Py_BuildValue("i", len);
// else PyErr_SetString(G_ERR, "Couldn't add image to database.");
}
else PyErr_SetString(G_ERR, "Couldn't read buffer data.");
return 0;
}
*/
PyErr_SetString(G_ERR, "still testing...");
return 0;
}
static PyMethodDef methods[] = {
{
"newWindow", newWindow, METH_VARARGS,
"docstring"
},
{ 0, 0, 0, 0 }
};
#endif
}
// A helper function for all those cases where we need to inform the user that there isn't
// a LUA engine available.
bool noPythonFail(const std::string& err) {
warn() << err << "; Python not compiled in library." << std::endl;
return false;
}
// Our "private", internal data.
struct PythonEngineData {
#ifdef OSGWIDGET_USEPYTHON
PythonEngineData():
mod (0),
err (0),
main (0) {
}
bool valid() const {
return mod && err && main;
}
PyObject* mod;
PyObject* err;
PyObject* main;
#endif
};
PythonEngine::PythonEngine(WindowManager* wm):
_wm(wm) {
#ifdef OSGWIDGET_USEPYTHON
_data = new PythonEngineData();
#else
_data = 0;
#endif
}
bool PythonEngine::initialize() {
#ifdef OSGWIDGET_USEPYTHON
Py_InitializeEx(0);
if(!_data->valid()) {
_data->mod = Py_InitModule3("osgwidget", py::methods, "main docstring");
_data->err = PyErr_NewException((char*)("osgwidget.error"), 0, 0);
_data->main = PyModule_GetDict(PyImport_AddModule("__main__"));
Py_INCREF(_data->err);
// TODO: ...sigh...
py::G_ERR = _data->err;
PyModule_AddObject(_data->mod, "error", _data->err);
}
return true;
#else
return noPythonFail("Can't initialize the PythonEngine");
#endif
}
bool PythonEngine::close() {
#ifdef OSGWIDGET_USEPYTHON
if(_data->valid()) {
Py_DECREF(_data->err);
Py_Finalize();
}
delete _data;
return true;
#else
return noPythonFail("Can't close the PythonEngine");
#endif
}
bool PythonEngine::eval(const std::string& code) {
#ifdef OSGWIDGET_USEPYTHON
PyObject* r = PyRun_String(code.c_str(), Py_file_input, _data->main, _data->main);
if(!r) {
r = PyErr_Occurred();
if(r) {
PyErr_Print();
PyErr_Clear();
}
return false;
}
return true;
#else
return noPythonFail("Can't evaluate code in PythonEngine");
#endif
}
bool PythonEngine::runFile(const std::string& filePath) {
#ifdef OSGWIDGET_USEPYTHON
if(!osgDB::fileExists(filePath)) {
warn()
<< "Couldn't find file \"" << filePath << "\" for PythonEngine."
<< std::endl
;
return false;
}
FILE* f = fopen(filePath.c_str(), "r");
PyObject* r = PyRun_File(f, filePath.c_str(), Py_file_input, _data->main, _data->main);
fclose(f);
if(!r) {
r = PyErr_Occurred();
if(r) {
// The following snippet lets us get the return code. That is: if the
// script is stopped with sys.exit() or similar. We could use this
// return code to do something sensible... later.
if(PyErr_ExceptionMatches(PyExc_SystemExit)) {
PyObject* ty = 0;
PyObject* er = 0;
PyObject* tr = 0;
PyErr_Fetch(&ty, &er, &tr);
Py_DECREF(ty);
Py_DECREF(er);
Py_DECREF(er);
}
else {
PyErr_Print();
PyErr_Clear();
}
}
return false;
}
return true;
#else
return noPythonFail("Can't evaluate code in PythonEngine");
#endif
}
}

View File

@ -0,0 +1,376 @@
// -*-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>
#include <osgWidget/StyleManager>
namespace osgWidget {
Style::Style(const std::string& name, const std::string& style):
_style(style) {
setName(name);
}
Style::Style(const Style& style, const osg::CopyOp& co):
osg::Object (style, co),
_style (style._style) {
}
bool Style::applyStyle(Widget* widget, Reader r) {
std::string str;
osg::Vec2 vec2;
osg::Vec3 vec3;
osg::Vec4 vec4;
float f;
if(_match("pos %i %i", r) || _match("pos %f %f", r)) {
r.readSequence(vec2);
widget->setOrigin(vec2);
}
else if(_match("pos-x %i", r) || _match("pos-x %f", r)) {
r.readSequence(f);
widget->setX(f);
}
else if(_match("pos-y %i", r) || _match("pos-y %f", r)) {
r.readSequence(f);
widget->setY(f);
}
else if(_match("size %i %i", r) || _match("size %f %f", r)) {
r.readSequence(vec2);
widget->setSize(vec2);
}
else if(_match("width %i", r) || _match("width %f", r)) {
r.readSequence(f);
widget->setWidth(f);
}
else if(_match("height %i", r) || _match("height %f", r)) {
r.readSequence(f);
widget->setHeight(f);
}
// Color using 4x 0-255 integers.
else if(_match("color %i %i %i %i", r)) {
r.readSequence(vec4);
widget->setColor(vec4 / 255.0f);
}
// Color using 3x 0-255 integers with a default alpha of 255.
else if(_match("color %i %i %i", r)) {
r.readSequence(vec3);
widget->setColor(osg::Vec4(vec3[0], vec3[1], vec3[2], 255.0f) / 255.0f);
}
// Color using 4x 0.0f-1.0f floats.
else if(_match("color %f %f %f %f", r)) {
r.readSequence(vec4);
widget->setColor(vec4);
}
// Color using 3x 0.0f-1.0f floats with a default alpha of 1.0f.
else if(_match("color %f %f %f", r)) {
r.readSequence(vec3);
widget->setColor(osg::Vec4(vec3[0], vec3[1], vec3[2], 1.0f));
}
// Set padding uniformly.
else if(_match("padding %i", r)) {
r.readSequence(f);
widget->setPadding(f);
}
// Set left padding.
else if(_match("padding-left %i", r)) {
r.readSequence(f);
widget->setPadLeft(f);
}
// Set right padding.
else if(_match("padding-right %i", r)) {
r.readSequence(f);
widget->setPadRight(f);
}
// Set top padding.
else if(_match("padding-top %i", r)) {
r.readSequence(f);
widget->setPadTop(f);
}
// Set bottom padding.
else if(_match("padding-bottom %i", r)) {
r.readSequence(f);
widget->setPadBottom(f);
}
else if(_match("layer %w", r)) {
r.readSequence(str);
widget->setLayer(strToLayer(str));
}
else if(_match("valign %w", r)) {
r.readSequence(str);
widget->setAlignVertical(strToVAlign(str));
}
else if(_match("halign %w", r)) {
r.readSequence(str);
widget->setAlignHorizontal(strToHAlign(str));
}
else if(_match("coordmode %w", r)) {
r.readSequence(str);
widget->setCoordinateMode(strToCoordMode(str));
}
else if(_match("fill %w", r)) {
r.readSequence(str);
widget->setCanFill(strToFill(str));
}
else if(_match("image %s", r)) {
r.readSequence(str);
widget->setImage(str, true);
}
// Otherwise, increment the stream pointer.
else return false;
return true;
}
bool Style::applyStyle(Label* label, Reader r) {
return false;
}
bool Style::applyStyle(Input* input, Reader r) {
return false;
}
bool Style::applyStyle(Window* window, Reader r) {
osg::Vec2 vec2;
float f;
if(_match("pos %i %i", r) || _match("pos %f %f", r)) {
r.readSequence(vec2);
window->setOrigin(vec2.x(), vec2.y());
}
else if(_match("pos-x %i", r) || _match("pos-x %f", r)) {
r.readSequence(f);
window->setX(f);
}
else if(_match("pos-y %i", r) || _match("pos-y %f", r)) {
r.readSequence(f);
window->setY(f);
}
else if(_match("size %i %i", r) || _match("size %f %f", r)) {
r.readSequence(vec2);
window->resize(vec2.x(), vec2.y());
}
else if(_match("width %i", r) || _match("width %f", r)) {
r.readSequence(f);
window->resize(f);
}
else if(_match("height %i", r) || _match("height %f", r)) {
r.readSequence(f);
window->resize(0.0f, f);
}
else return false;
return true;
}
bool Style::applyStyle(Window::EmbeddedWindow*, Reader r) {
return false;
}
bool Style::applyStyle(Box* box, Reader r) {
if(applyStyle(static_cast<Window*>(box), r)) return true;
return false;
}
bool Style::applyStyle(Frame::Corner*, Reader r) {
return false;
}
bool Style::applyStyle(Frame::Border*, Reader r) {
return false;
}
Widget::LAYER Style::strToLayer(const std::string& layer) {
std::string l = lowerCase(layer);
if(l == "top") return Widget::LAYER_TOP;
else if(l == "high") return Widget::LAYER_HIGH;
else if(l == "middle") return Widget::LAYER_MIDDLE;
else if(l == "low") return Widget::LAYER_LOW;
else if(l == "bg") return Widget::LAYER_BG;
else {
warn() << "Unkown Layer name [" << layer << "]; using LAYER_MIDDLE." << std::endl;
return Widget::LAYER_MIDDLE;
}
}
Widget::VERTICAL_ALIGNMENT Style::strToVAlign(const std::string& valign) {
std::string va = lowerCase(valign);
if(va == "center") return Widget::VA_CENTER;
else if(va == "top") return Widget::VA_TOP;
else if(va == "bottom") return Widget::VA_BOTTOM;
else {
warn() << "Unkown VAlign name [" << valign << "]; using VA_CENTER." << std::endl;
return Widget::VA_CENTER;
}
}
Widget::HORIZONTAL_ALIGNMENT Style::strToHAlign(const std::string& halign) {
std::string ha = lowerCase(halign);
if(ha == "center") return Widget::HA_CENTER;
else if(ha == "left") return Widget::HA_LEFT;
else if(ha == "right") return Widget::HA_RIGHT;
else {
warn() << "Unkown HAlign name [" << halign << "]; using HA_CENTER." << std::endl;
return Widget::HA_CENTER;
}
}
Widget::COORDINATE_MODE Style::strToCoordMode(const std::string& coordmode) {
std::string cm = lowerCase(coordmode);
if(cm == "absolute") return Widget::CM_ABSOLUTE;
else if(cm == "relative") return Widget::CM_RELATIVE;
else {
warn()
<< "Unkown CoordMode name [" << coordmode
<< "]; using CM_ABSOLUTE." << std::endl
;
return Widget::CM_ABSOLUTE;
}
}
bool Style::strToFill(const std::string& fill) {
std::string cm = lowerCase(fill);
if(cm == "true") return true;
else if(cm == "false") return false;
else {
warn()
<< "Unkown Fill name [" << fill
<< "]; using false." << std::endl
;
return false;
}
}
StyleManager::StyleManager() {
}
StyleManager::StyleManager(const StyleManager& manager, const osg::CopyOp& co):
osg::Object(manager, co) {
for(ConstIterator i = _styles.begin(); i != _styles.end(); i++) if(i->second.valid()) {
_styles[i->first] = new Style(*i->second.get(), osg::CopyOp::DEEP_COPY_ALL);
}
}
bool StyleManager::_applyStyleToObject(osg::Object* obj, const std::string& style) {
std::string c = obj->className();
if(!std::string("Widget").compare(c)) return _coerceAndApply<Widget>(
obj,
style,
c
);
else if(!std::string("Label").compare(c)) return _coerceAndApply<Label>(
obj,
style,
c
);
else if(!std::string("Box").compare(c)) return _coerceAndApply<Box>(
obj,
style,
c
);
else warn()
<< "StyleManager does not support coercion of objects of type "
<< c << "." << std::endl
;
return false;
}
bool StyleManager::addStyle(Style* style) {
if(!style || style->getName().empty()) {
warn() << "Cannot add a NULL or nameless Style object." << std::endl;
return false;
}
_styles[style->getName()] = style;
return true;
}
}

225
src/osgWidget/Table.cpp Normal file
View File

@ -0,0 +1,225 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: Table.cpp 48 2008-05-05 14:13:20Z cubicool $
#include <osgWidget/Table>
namespace osgWidget {
// TODO: There is a serious, outstanding bug with regards to USING a table before ALL Widgets
// are set! FIX THIS!!!
Table::Table(const std::string& name, unsigned int rows, unsigned int cols):
Window (name),
_rows (rows),
_cols (cols),
_lastRowAdd (0),
_lastColAdd (0) {
_objects.resize(_rows * _cols);
}
Table::Table(const Table& table, const osg::CopyOp& co):
Window (table, co),
_rows (table._rows),
_cols (table._cols),
_lastRowAdd (table._lastRowAdd),
_lastColAdd (table._lastColAdd) {
}
unsigned int Table::_calculateIndex(unsigned int row, unsigned int col) const {
return (row * _cols) + col;
}
void Table::_getRows(CellSizes& rows, Getter get) const {
for(unsigned int i = 0; i < _rows; i++) rows.push_back(
_compare<Greater>(get, i * _cols, (i * _cols) + _cols)
);
}
void Table::_getColumns(CellSizes& cols, Getter get) const {
for(unsigned int i = 0; i < _cols; i++) cols.push_back(
_compare<Greater>(get, i, 0, _cols)
);
}
void Table::_resizeImplementation(point_type width, point_type height) {
// We use these vectors so that we don't have to repeatedly call isFillable
// all the time. Usage such as this can really generate a lot of moronic,
// misinformed opposition, but until std::bit_vector is available, this is
// what we get. Deal with it.
std::vector<bool> rowFills;
std::vector<bool> colFills;
point_type numRowFills = 0.0f;
point_type numColFills = 0.0f;
// Enumerate each row and determine whether it can fill. If so, increment
// our numRowFills variable and set the position in rowFills to "true."
for(unsigned int row = 0; row < _rows; row++) {
bool fill = isRowVerticallyFillable(row);
if(fill) numRowFills++;
rowFills.push_back(fill);
}
// Enumerate each column and determine whether it can fill. If so, increment
// our numColFills variable and set the position in colFills to "true."
for(unsigned int col = 0; col < _cols; col++) {
bool fill = isColumnHorizontallyFillable(col);
if(fill) numColFills++;
colFills.push_back(fill);
}
int wrem = 0;
int hrem = 0;
if(numRowFills > 0.0f) {
hrem = static_cast<int>(height) % static_cast<int>(numRowFills);
unsigned int cur = 0;
for(unsigned int row = 0; row < _rows; row++) {
point_type h = height / numRowFills;
if(cur >= _lastRowAdd && hrem) {
_lastRowAdd++;
h++;
hrem--;
}
if(rowFills[row]) addHeightToRow(row, h);
cur++;
}
}
if(numColFills > 0.0f) {
wrem = static_cast<int>(width) % static_cast<int>(numColFills);
unsigned int cur = 0;
for(unsigned int col = 0; col < _cols; col++) {
point_type w = width / numColFills;
if(cur >= _lastColAdd && wrem) {
_lastColAdd++;
w++;
wrem--;
}
if(colFills[col]) addWidthToColumn(col, w);
cur++;
}
}
CellSizes rowHeights;
CellSizes colWidths;
getRowHeights(rowHeights);
getColumnWidths(colWidths);
point_type y = 0.0f;
for(unsigned int row = 0; row < _rows; row++) {
point_type x = 0.0f;
for(unsigned int col = 0; col < _cols; col++) {
Widget* widget = _objects[_calculateIndex(row, col)].get();
if(widget) {
widget->setOrigin(x, y);
_positionWidget(widget, colWidths[col], rowHeights[row]);
}
x += colWidths[col];
}
y += rowHeights[row];
}
}
Window::Sizes Table::_getWidthImplementation() const {
CellSizes cols;
CellSizes minCols;
getColumnWidths(cols);
getColumnMinWidths(minCols);
return Sizes(
std::accumulate(cols.begin(), cols.end(), 0.0f, Plus()),
std::accumulate(minCols.begin(), minCols.end(), 0.0f, Plus())
);
}
Window::Sizes Table::_getHeightImplementation() const {
CellSizes rows;
CellSizes minRows;
getRowHeights(rows);
getRowMinHeights(minRows);
return Sizes(
std::accumulate(rows.begin(), rows.end(), 0.0f, Plus()),
std::accumulate(minRows.begin(), minRows.end(), 0.0f, Plus())
);
}
bool Table::addWidget(Widget* widget) {
return addWidget(widget, 0, 0);
}
bool Table::addWidget(Widget* widget, unsigned int row, unsigned int col) {
return Window::insertWidget(widget, _calculateIndex(row, col));
}
void Table::getRowHeights(CellSizes& rowHeights) const {
_getRows(rowHeights, &Widget::getHeightTotal);
}
void Table::getRowMinHeights(CellSizes& rowMinHeights) const {
_getRows(rowMinHeights, &Widget::getMinHeightTotal);
}
void Table::getColumnWidths(CellSizes& colWidths) const {
_getColumns(colWidths, &Widget::getWidthTotal);
}
void Table::getColumnMinWidths(CellSizes& colMinWidths) const {
_getColumns(colMinWidths, &Widget::getMinWidthTotal);
}
void Table::addHeightToRow(unsigned int row, point_type height) {
for(
Iterator i = begin() + (row * _cols);
i != begin() + ((row * _cols) + _cols);
i++
) if(i->valid()) i->get()->addHeight(height);
}
void Table::addWidthToColumn(unsigned int col, point_type width) {
// See the documentation in include/osgWidget/Window::_forEachApplyOrAssign if you want
// to know why we need this variable.
unsigned int c = col;
for(Iterator i = begin() + col; i < end(); c += _cols) {
if(i->valid()) i->get()->addWidth(width);
if((c + _cols) < size()) i += _cols;
else i = end();
}
}
bool Table::isRowVerticallyFillable(unsigned int row) const {
return static_cast<point_type>(_cols) == _getNumFill(row * _cols, (row * _cols) + _cols);
}
bool Table::isColumnHorizontallyFillable(unsigned int col) const {
return static_cast<point_type>(_rows) == _getNumFill(col, 0, _cols);
}
}

176
src/osgWidget/Util.cpp Normal file
View File

@ -0,0 +1,176 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: Util.cpp 59 2008-05-15 20:55:31Z cubicool $
#include <osg/io_utils>
#include <osgGA/TrackballManipulator>
#include <osgGA/StateSetManipulator>
#include <osgDB/FileUtils>
#include <osgDB/WriteFile>
#include <osgViewer/ViewerEventHandlers>
#include <osgWidget/Util>
#include <osgWidget/ViewerEventHandlers>
#include <osgWidget/WindowManager>
namespace osgWidget {
std::string getFilePath(const std::string& filename) {
osgDB::FilePathList path;
char* fp = getenv("OSGWIDGET_FILE_PATH");
osgDB::convertStringPathIntoFilePathList(fp ? fp : ".", path);
return osgDB::findFileInPath(filename, path);
}
std::string generateRandomName(const std::string& base) {
static unsigned int count = 0;
std::stringstream ss;
ss << base << "_" << count;
count++;
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();
camera->getOrCreateStateSet()->setMode(
GL_LIGHTING,
osg::StateAttribute::PROTECTED | osg::StateAttribute::OFF
);
camera->setProjectionMatrix(osg::Matrix::ortho2D(0.0, width, 0.0f, height));
camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
camera->setViewMatrix(osg::Matrix::identity());
camera->setClearMask(GL_DEPTH_BUFFER_BIT);
camera->setRenderOrder(osg::Camera::POST_RENDER);
return camera;
}
osg::Camera* createInvertedYOrthoCamera(matrix_type width, matrix_type height) {
osg::Camera* camera = createOrthoCamera(width, height);
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,
static_cast<int>(wm->getWidth()),
static_cast<int>(wm->getHeight())
);
osg::Group* group = new osg::Group();
osg::Camera* camera = wm->createParentOrthoCamera();
group->addChild(camera);
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()
));
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");
return true;
}
}

83
src/osgWidget/Version.cpp Normal file
View File

@ -0,0 +1,83 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: Version.cpp 64 2008-06-30 21:32:00Z cubicool $
#include <sstream>
#include <osgWidget/Version>
extern "C" {
const unsigned int OSGWIDGET_MAJOR_VERSION = 0;
const unsigned int OSGWIDGET_MINOR_VERSION = 1;
const unsigned int OSGWIDGET_PATCH_VERSION = 8;
const char* OSGWIDGET_EXTRA_TEXT = "(pre-merge)";
unsigned int osgWidgetGetMajorVersion() {
return OSGWIDGET_MAJOR_VERSION;
}
unsigned int osgWidgetGetMinorVersion() {
return OSGWIDGET_MINOR_VERSION;
}
unsigned int osgWidgetGetPatchVersion() {
return OSGWIDGET_PATCH_VERSION;
}
const char* osgWidgetGetExtraText() {
return OSGWIDGET_EXTRA_TEXT;
}
const char* osgWidgetGetVersion() {
static std::string version;
static bool versionInit = true;
if(versionInit) {
std::stringstream stream;
stream.str(std::string());
stream
<< OSGWIDGET_MAJOR_VERSION << "."
<< OSGWIDGET_MINOR_VERSION << "."
<< OSGWIDGET_PATCH_VERSION << " "
<< OSGWIDGET_EXTRA_TEXT
;
version = stream.str();
versionInit = false;
}
return version.c_str();
}
const char* osgWidgetGetLibraryName() {
static std::string name("OpenSceneGraph Widget Library");
return name.c_str();
}
bool osgWidgetVersionMinimum(unsigned int major, unsigned int minor, unsigned int patch) {
return
OSGWIDGET_MAJOR_VERSION >= major &&
OSGWIDGET_MINOR_VERSION >= minor &&
OSGWIDGET_PATCH_VERSION >= patch
;
}
bool osgWidgetVersionMaximum(unsigned int major, unsigned int minor, unsigned int patch) {
return
// OSGWIDGET_MAJOR_VERSION <= major &&
OSGWIDGET_MINOR_VERSION <= minor &&
OSGWIDGET_PATCH_VERSION <= patch
;
}
bool osgWidgetVersionRequired(unsigned int major, unsigned int minor, unsigned int patch) {
return
OSGWIDGET_MAJOR_VERSION == major &&
OSGWIDGET_MINOR_VERSION == minor &&
OSGWIDGET_PATCH_VERSION == patch
;
}
}

View File

@ -0,0 +1,190 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: ViewerEventHandlers.cpp 59 2008-05-15 20:55:31Z cubicool $
#include <osgWidget/ViewerEventHandlers>
namespace osgWidget {
MouseHandler::MouseHandler(WindowManager* wm):
_wm(wm) {
}
bool MouseHandler::handle(
const osgGA::GUIEventAdapter& gea,
osgGA::GUIActionAdapter& gaa,
osg::Object* obj,
osg::NodeVisitor* nv
) {
osgGA::GUIEventAdapter::EventType ev = gea.getEventType();
MouseAction ma = _isMouseEvent(ev);
if(ma) {
// If we're scrolling, we need to inform the WindowManager of that.
_wm->setScrollingMotion(gea.getScrollingMotion());
return (this->*ma)(gea.getX(), gea.getY(), gea.getButton());
}
return false;
}
bool MouseHandler::_handleMousePush(float x, float y, int button) {
if(button == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON) return _doMouseEvent(
x,
y,
&WindowManager::mousePushedLeft
);
else if(button == osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON) return _doMouseEvent(
x,
y,
&WindowManager::mousePushedRight
);
else if(button == osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON) return _doMouseEvent(
x,
y,
&WindowManager::mousePushedMiddle
);
else return false;
}
bool MouseHandler::_handleMouseRelease(float x, float y, int button) {
if(button == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON) return _doMouseEvent(
x,
y,
&WindowManager::mouseReleasedLeft
);
else if(button == osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON) return _doMouseEvent(
x,
y,
&WindowManager::mouseReleasedRight
);
else if(button == osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON) return _doMouseEvent(
x,
y,
&WindowManager::mouseReleasedMiddle
);
else return false;
}
bool MouseHandler::_handleMouseDoubleClick(float x, float y, int button) {
return false;
}
bool MouseHandler::_handleMouseDrag(float x, float y, int button) {
return _doMouseEvent(x, y, &WindowManager::pointerDrag);
}
bool MouseHandler::_handleMouseMove(float x, float y, int button) {
return _doMouseEvent(x, y, &WindowManager::pointerMove);
}
bool MouseHandler::_handleMouseScroll(float x, float y, int) {
return _doMouseEvent(x, y, &WindowManager::mouseScroll);
}
MouseHandler::MouseAction MouseHandler::_isMouseEvent(
osgGA::GUIEventAdapter::EventType ev
) const {
if(ev == osgGA::GUIEventAdapter::PUSH) return
&MouseHandler::_handleMousePush
;
else if(ev == osgGA::GUIEventAdapter::RELEASE) return
&MouseHandler::_handleMouseRelease
;
else if(ev == osgGA::GUIEventAdapter::DOUBLECLICK) return
&MouseHandler::_handleMouseDoubleClick
;
else if(ev == osgGA::GUIEventAdapter::DRAG) return
&MouseHandler::_handleMouseDrag
;
else if(ev == osgGA::GUIEventAdapter::MOVE) return
&MouseHandler::_handleMouseMove
;
else if(ev == osgGA::GUIEventAdapter::SCROLL) return
&MouseHandler::_handleMouseScroll
;
else return 0;
}
bool MouseHandler::_doMouseEvent(float x, float y, MouseEvent me) {
bool handled = (_wm.get()->*me)(x, y);
// This is called LAST for things like drag, which needs to calculate a mouse difference.
_wm->setPointerXY(x, y);
return handled;
}
KeyboardHandler::KeyboardHandler(WindowManager* wm):
_wm(wm) {
}
bool KeyboardHandler::handle(
const osgGA::GUIEventAdapter& gea,
osgGA::GUIActionAdapter& gaa,
osg::Object* obj,
osg::NodeVisitor* nv
) {
osgGA::GUIEventAdapter::EventType ev = gea.getEventType();
if(
ev != osgGA::GUIEventAdapter::KEYDOWN &&
ev != osgGA::GUIEventAdapter::KEYUP
) return false;
int key = gea.getKey();
int keyMask = gea.getModKeyMask();
// -1 is the "key invalid" return code.
if(key == -1) return false;
if(ev == osgGA::GUIEventAdapter::KEYDOWN) return _wm->keyDown(key, keyMask);
else if(ev == osgGA::GUIEventAdapter::KEYUP) return _wm->keyUp(key, keyMask);
return false;
}
ResizeHandler::ResizeHandler(WindowManager* wm, osg::Camera* camera):
_wm (wm),
_camera (camera) {
}
bool ResizeHandler::handle(
const osgGA::GUIEventAdapter& gea,
osgGA::GUIActionAdapter& gaa,
osg::Object* obj,
osg::NodeVisitor* nv
) {
osgGA::GUIEventAdapter::EventType ev = gea.getEventType();
if(ev != osgGA::GUIEventAdapter::RESIZE) return false;
osg::Matrix::value_type w = gea.getWindowWidth();
osg::Matrix::value_type h = gea.getWindowHeight();
if(_wm->isInvertedY()) _camera->setProjectionMatrix(
createInvertedYOrthoProjectionMatrix(w, h)
);
else _camera->setProjectionMatrix(osg::Matrix::ortho2D(0.0f, w, 0.0f, h));
_wm->setSize(w, h);
_wm->resizeAllWindows();
return true;
}
}

524
src/osgWidget/Widget.cpp Normal file
View File

@ -0,0 +1,524 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: Widget.cpp 64 2008-06-30 21:32:00Z cubicool $
#include <osg/io_utils>
#include <osg/Math>
#include <osg/BlendFunc>
#include <osg/TexMat>
#include <osgDB/ReadFile>
#include <osgDB/FileUtils>
#include <osgWidget/WindowManager>
// Don't use these macros! :) They're simply for internal optimization!
#define MACRO_WIDGET_X(v) (*v)[LL].x()
#define MACRO_WIDGET_Y(v) (*v)[LL].y()
#define MACRO_WIDGET_W(v) (*v)[LR].x() - (*v)[LL].x()
#define MACRO_WIDGET_H(v) (*v)[UL].y() - (*v)[LL].y()
namespace osgWidget {
osg::ref_ptr<PointArray> Widget::_norms;
Widget::Widget(const std::string& name, point_type w, point_type h):
_parent (0),
_index (0),
_layer (LAYER_LOW),
_padLeft (0.0f),
_padRight (0.0f),
_padTop (0.0f),
_padBottom (0.0f),
_valign (VA_CENTER),
_halign (HA_CENTER),
_coordMode (CM_ABSOLUTE),
_canFill (false),
_canClone (true),
_isManaged (false),
_isStyled (false),
_minWidth (w),
_minHeight (h) {
_name = name.size() ? name : generateRandomName("Widget");
if(!_norms.valid()) {
_norms = new PointArray(1);
(*_norms)[0].set(0.0f, 0.0f, 1.0f);
(*_norms)[0].normalize();
}
TexCoordArray* texs = new TexCoordArray(4);
// Fill our texture coordinates with null stuff for now, since we aren't using them
// until an Image is set at some later point.
std::fill(texs->begin(), texs->end(), osg::Vec2(0.0f, 0.0f));
setUseDisplayList(false);
setDataVariance(osg::Object::DYNAMIC);
setVertexArray(new PointArray(4));
setColorArray(new ColorArray(4));
setNormalArray(_norms.get());
setTexCoordArray(0, texs);
setNormalBinding(osg::Geometry::BIND_OVERALL);
setColorBinding(osg::Geometry::BIND_PER_VERTEX);
addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));
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):
osg::Geometry (widget, co),
EventInterface (widget),
StyleInterface (widget),
_parent (0),
_index (0),
_layer (widget._layer),
_padLeft (widget._padLeft),
_padRight (widget._padRight),
_padTop (widget._padTop),
_padBottom (widget._padBottom),
_valign (widget._valign),
_halign (widget._halign),
_coordMode (widget._coordMode),
_canFill (widget._canFill),
_canClone (widget._canClone),
_isManaged (false),
_isStyled (widget._isStyled),
_minWidth (widget._minWidth),
_minHeight (widget._minHeight) {
}
// This takes an integer value and translates it into a value that will be added to
// the parent window's Z value.
point_type Widget::_calculateZ(unsigned int layer) const {
point_type zRange = 0.0f;
if(_parent) zRange = _parent->getZRange();
return (static_cast<point_type>(layer) / static_cast<point_type>(LAYER_TOP + 1)) * zRange;
}
WindowManager* Widget::_getWindowManager() const {
if(!_parent) return 0;
return _parent->getWindowManager();
}
osg::Image* Widget::_getImage() const {
const osg::Texture2D* 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()
<< "Widget [" << _name
<< "] was asked to set it's width to " << w
<< ", but the minimum width is " << _minWidth
<< "." << std::endl
;
w = _minWidth;
}
if(h != -1.0f && h < _minHeight) {
warn()
<< "Widget [" << _name
<< "] was asked to set it's height to " << h
<< ", but the minimum height is " << _minHeight
<< "." << std::endl
;
h = _minHeight;
}
PointArray* verts = _verts();
if(_coordMode == CM_ABSOLUTE) {
// If any of our values are 0, replace them with the current value.
// We could just call getWidth(), etc., but all those dynamic_casts could eventually
// get expensive, so we just use the already-created verts() array directly.
if(x < 0.0f) x = MACRO_WIDGET_X(verts);
if(y < 0.0f) y = MACRO_WIDGET_Y(verts);
if(w < 0.0f) w = MACRO_WIDGET_W(verts);
if(h < 0.0f) h = MACRO_WIDGET_H(verts);
}
else {
if(x < 0.0f) x = _relCoords[0];
if(y < 0.0f) y = _relCoords[1];
if(w < 0.0f) w = _relCoords[2];
if(h < 0.0f) h = _relCoords[3];
}
if(z < 0.0f) z = _calculateZ(_layer);
// Now, we need to determine if the dimensions are actually percentage of the parent's
// size, rather than an absolute values. The Widget must be parented for this to be
// valid, however.
if(_coordMode == CM_RELATIVE) {
XYCoord size;
if(_parent) size = _parent->getSize();
if(x >= 0.0f && x <= 1.0f) {
_relCoords[0] = x;
x = size.x() * x;
}
if(y >= 0.0f && y <= 1.0f) {
_relCoords[1] = y;
y = size.y() * y;
}
if(w >= 0.0f && w <= 1.0f) {
_relCoords[2] = w;
w = size.x() * w;
}
if(h >= 0.0f && h <= 1.0f) {
_relCoords[3] = h;
h = size.y() * h;
}
}
(*verts)[LL].set(x, y, z);
(*verts)[LR].set(x + w, y, z);
(*verts)[UR].set(x + w, y + h, z);
(*verts)[UL].set(x, y + h, z);
}
void Widget::setColor(color_type r, color_type g, color_type b, color_type a, POINT p) {
ColorArray* cols = _cols();
if(p == ALL_POINTS) {
(*cols)[LL].set(r, g, b, a);
(*cols)[LR].set(r, g, b, a);
(*cols)[UR].set(r, g, b, a);
(*cols)[UL].set(r, g, b, a);
}
else (*cols)[convertPoint(p)].set(r, g, b, a);
}
void Widget::addColor(color_type r, color_type g, color_type b, color_type a, POINT p) {
ColorArray* cols = _cols();
if(p == ALL_POINTS) {
(*cols)[LL] += Color(r, g, b, a);
(*cols)[LR] += Color(r, g, b, a);
(*cols)[UR] += Color(r, g, b, a);
(*cols)[UL] += Color(r, g, b, a);
}
else (*cols)[convertPoint(p)] += Color(r, g, b, a);
}
void Widget::setTexCoord(texcoord_type tx, texcoord_type ty, POINT p) {
TexCoordArray* texs = _texs();
if(p == ALL_POINTS) {
(*texs)[LL].set(tx, ty);
(*texs)[LR].set(tx, ty);
(*texs)[UR].set(tx, ty);
(*texs)[UL].set(tx, ty);
}
else (*texs)[convertPoint(p)].set(tx, ty);
}
void Widget::setTexCoordRegion(point_type x, point_type y, point_type w, point_type h) {
osg::Image* image = _image();
if(!image) return;
point_type tw = image->s();
point_type th = image->t();
TexCoordArray* texs = _texs();
// Set the LOWER_LEFT point.
XYCoord t(x / tw, y / tw);
(*texs)[UL] = t;
// Set the LOWER_RIGHT point.
t += XYCoord(w / tw, 0.0f);
(*texs)[UR] = t;
// Set the UPPER_RIGHT point.
t += XYCoord(0.0f, h / th);
(*texs)[LR] = t;
// Set the UPPER_LEFT point.
t += XYCoord(-(w / tw), 0.0f);
(*texs)[LL] = t;
}
void Widget::setTexCoordWrapHorizontal() {
osg::Image* image = _image();
osg::Texture2D* texture = _texture();
if(!image || !texture || image->s() == 0.0f) return;
texture->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
setTexCoord(getWidth() / image->s(), 0.0f, LOWER_RIGHT);
setTexCoord(getWidth() / image->s(), 1.0f, UPPER_RIGHT);
}
void Widget::setTexCoordWrapVertical() {
osg::Image* image = _image();
osg::Texture2D* texture = _texture();
if(!image || !texture || image->t() == 0.0f) return;
texture->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);
setTexCoord(0.0f, getHeight() / image->t(), UPPER_LEFT);
setTexCoord(1.0f, getHeight() / image->t(), UPPER_RIGHT);
}
XYCoord Widget::localXY(double _x, double _y) const {
if(!_parent) return XYCoord(_x, _y);
return _parent->localXY(_x, _y) - getOrigin();
}
bool Widget::setImage(osg::Image* image, bool setTexCoords) {
if(!image) {
warn() << "Widget [" << _name << "] cannot use a NULL image." << std::endl;
return false;
}
osg::Texture2D* texture = new osg::Texture2D();
texture->setDataVariance(osg::Object::DYNAMIC);
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;
}
bool Widget::setImage(const std::string& filePath, bool setTexCoords) {
if(!osgDB::findDataFile(filePath).size()) {
warn()
<< "Widget [" << _name
<< "] cannot find file " << filePath
<< " to set as it's Image." << std::endl
;
return false;
}
return setImage(osgDB::readImageFile(filePath), setTexCoords);
}
void Widget::setPadding(point_type pad) {
_padLeft = _padRight = _padTop = _padBottom = pad;
}
void Widget::addX(point_type x) {
if(_coordMode == CM_ABSOLUTE) setDimensions(MACRO_WIDGET_X(_verts()) + x);
else setDimensions(_relCoords[0] + x);
}
void Widget::addY(point_type y) {
if(_coordMode == CM_ABSOLUTE) setDimensions(-1.0f, MACRO_WIDGET_Y(_verts()) + y);
else setDimensions(-1.0f, _relCoords[1] + y);
}
void Widget::addWidth(point_type w) {
if(_coordMode == CM_ABSOLUTE) setDimensions(-1.0f, -1.0f, MACRO_WIDGET_W(_verts()) + w);
else setDimensions(-1.0f, -1.0f, _relCoords[2] + w);
}
void Widget::addHeight(point_type h) {
if(_coordMode == CM_ABSOLUTE) setDimensions(
-1.0f,
-1.0f,
-1.0f,
MACRO_WIDGET_H(_verts()) + h
);
else setDimensions(-1.0f, -1.0f, -1.0f, _relCoords[3] + h);
}
void Widget::addOrigin(point_type x, point_type y) {
if(_coordMode == CM_ABSOLUTE) {
PointArray* verts = _verts();
setDimensions(
MACRO_WIDGET_X(verts) + x,
MACRO_WIDGET_Y(verts) + y
);
}
else setDimensions(_relCoords[0] + x, _relCoords[1] + y);
}
void Widget::addSize(point_type w, point_type h) {
if(_coordMode == CM_ABSOLUTE) {
PointArray* verts = _verts();
setDimensions(
-1.0f,
-1.0f,
MACRO_WIDGET_W(verts) + w,
MACRO_WIDGET_H(verts) + h
);
}
else setDimensions(-1.0f, -1.0f, _relCoords[2] + w, _relCoords[3] + h);
}
point_type Widget::getWidth() const {
const PointArray* verts = _verts();
return MACRO_WIDGET_W(verts);
}
point_type Widget::getHeight() const {
const PointArray* verts = _verts();
return MACRO_WIDGET_H(verts);
}
point_type Widget::getX() const {
return MACRO_WIDGET_X(_verts());
}
point_type Widget::getY() const {
return MACRO_WIDGET_Y(_verts());
}
point_type Widget::getZ() const {
return (*_verts())[LL].z();
}
point_type Widget::getPadHorizontal() const {
return _padLeft + _padRight;
}
point_type Widget::getPadVertical() const {
return _padTop + _padBottom;
}
const Point& Widget::getPoint(POINT p) const {
POINT point = p;
if(p == ALL_POINTS) point = UPPER_LEFT;
return (*_verts())[convertPoint(point)];
}
const Color& Widget::getColor(POINT p) const {
POINT point = p;
if(p == ALL_POINTS) point = UPPER_LEFT;
return (*_cols())[convertPoint(point)];
}
const TexCoord& Widget::getTexCoord(POINT p) const {
POINT point = p;
if(p == ALL_POINTS) point = UPPER_LEFT;
return (*_texs())[convertPoint(point)];
}
// This converts our points back and forth depding on whether or not we're in an
// inverted-Y WindowManager.
Widget::POINT Widget::convertPoint(POINT 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;
}
Color Widget::getImageColorAtXY(point_type x, point_type y) const {
const osg::Image* image = _image();
if(!image) return Color();
const TexCoordArray* texs = _texs();
/*
How do we do this? First we need to make sure our right side is larger
than our left side and that the top side is larger the bottom; otherwise,
they're using strange tex coords.
Then, we find the percent area being used in both dimensions. We multiply
the XY values by those ratios and then add those values to the "offsets."
*/
point_type width = fabs((*texs)[LR].x() - (*texs)[LL].x());
point_type height = fabs((*texs)[LR].y() - (*texs)[UR].y());
point_type X = ((x / getWidth()) * width) + (*texs)[LL].x();
point_type Y = (((getHeight() - y) / getHeight()) * height) + (*texs)[UR].y();
return image->getColor(TexCoord(X, Y));
}
bool Widget::isPaddingUniform() const {
return
_padLeft == _padRight &&
_padLeft == _padTop &&
_padLeft == _padBottom
;
}
}

959
src/osgWidget/Window.cpp Normal file
View File

@ -0,0 +1,959 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: Window.cpp 66 2008-07-14 21:54:09Z cubicool $
#include <algorithm>
#include <osgGA/GUIEventAdapter>
#include <osgWidget/WindowManager>
namespace osgWidget {
bool callbackWindowMove(Event& ev) {
if(!ev.getWindow() || !ev.getWindowManager()->isLeftMouseButtonDown()) return false;
ev.getWindow()->addOrigin(ev.x, ev.y);
ev.getWindow()->update();
return true;
}
bool callbackWindowRotate(Event& ev) {
if(!ev.getWindow() || !ev.getWindowManager()->isRightMouseButtonDown()) return false;
ev.getWindow()->addRotate(ev.y);
ev.getWindow()->update();
return true;
}
bool callbackWindowScale(Event& ev) {
if(!ev.getWindow() || !ev.getWindowManager()->isMiddleMouseButtonDown()) return false;
ev.getWindow()->addScale(ev.y);
ev.getWindow()->update();
return true;
}
bool callbackWindowTabFocus(Event& ev) {
if(!ev.getWindow() || ev.key != osgGA::GUIEventAdapter::KEY_Tab) return false;
return ev.getWindow()->setNextFocusable();
}
Window::EmbeddedWindow::EmbeddedWindow(const std::string& name, point_type w, point_type h):
Widget(name, w, h) {
}
Window::EmbeddedWindow::EmbeddedWindow(const EmbeddedWindow& wiw, const osg::CopyOp& co):
Widget(wiw, co) {
// TODO: Get this!
// _window = 0;
}
void Window::EmbeddedWindow::parented(Window* parent) {
if(!_window.valid()) return;
if(!_window->_parent) {
_window->_parent = parent;
// Add this Window to the Window, on the same level as a Window's
// internal Geode. This will require special handling of events!
parent->addChild(_window.get());
}
else warn()
<< "EmbeddedWindow Widget [" << _name
<< "] cannot embed itself in Window [" << _window->getName()
<< "], since it is already a child of [" << _window->_parent->getName()
<< "]" << std::endl
;
}
void Window::EmbeddedWindow::unparented(Window*) {
// TODO: Figure out what's necessary here...
}
void Window::EmbeddedWindow::managed(WindowManager* wm) {
if(!_window.valid()) return;
_window->setNodeMask(wm->getNodeMask());
_window->managed(wm);
}
void Window::EmbeddedWindow::unmanaged(WindowManager* wm) {
_window->unmanaged(wm);
}
void Window::EmbeddedWindow::positioned() {
if(!_window.valid()) return;
point_type x = getX();
point_type y = getY();
point_type w = getWidth();
point_type h = getHeight();
// 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->setVisibleArea(0, 0, static_cast<int>(w), static_cast<int>(h));
_window->resize(w, h);
}
bool Window::EmbeddedWindow::setWindow(Window* win) {
if(!win) {
warn()
<< "EmbeddedWindow [" << _name
<< "] attempted to set a NULL Window." << std::endl
;
return false;
}
// TODO: I need to handle there already being a Window here.
_window = win;
_window->resize();
_window->setVisibilityMode(VM_PARTIAL);
if(_parent) parented(_parent);
WindowManager* wm = _getWindowManager();
if(wm) managed(wm);
return true;
}
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) {
_name = name.size() ? name : generateRandomName("Window");
// TODO: Fix the "bg" name.
osg::Geode* geode = new osg::Geode();
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);
_setParented(bg);
geode->addDrawable(bg);
addChild(geode);
setDataVariance(osg::Object::DYNAMIC);
setEventMask(EVENT_ALL);
getOrCreateStateSet()->setAttributeAndModes(
new osg::Scissor(0, 0, 0, 0),
osg::StateAttribute::ON
);
}
Window::Window(const Window& window, const osg::CopyOp& co):
MatrixTransform (window, co),
EventInterface (window),
StyleInterface (window),
_parent (0),
_wm (0),
_x (window._x),
_y (window._y),
_z (window._z),
_zRange (window._zRange),
_strata (window._strata),
_vis (window._vis),
_r (window._r),
_s (window._s),
_scaleDenom (window._scaleDenom),
_width (window._width),
_height (window._height),
_vAnchor (window._vAnchor),
_hAnchor (window._hAnchor),
_visibleArea (window._visibleArea) {
// Construct our vector of Widgets for easier use. :)
// TODO: I almost certainly will need to use the getPosition() thing here eventually
// for things to work 100% properly. For example, some Geodes may contain labels,
// etc. Also, any widget that doesn't support simple addWidget probably won't
// work (Table?)
osg::Geode* geode = _geode();
Widget* bg = dynamic_cast<Widget*>(geode->getDrawable(0));
if(bg) {
_setParented(bg);
// TODO: This is silly...
bg->setName(_name + "bg");
}
for(unsigned int i = 1; i < geode->getNumDrawables(); i++) {
Widget* widget = dynamic_cast<Widget*>(geode->getDrawable(i));
if(!widget || !widget->canClone()) continue;
_setParented(widget);
_objects.push_back(widget);
}
geode->setName(_name);
}
// This is the method by which all Windows are redrawn/resized. Keep in mind that not all
// Windows are required to absolutely honor a resize request, which is why we call the
// _getWidthImplementation() and _getHeightImplementation() functions instead of using the
// values passed in.
bool Window::resize(point_type width, point_type height) {
// First, we query and store what sizes the Window currently is.
_setWidthAndHeight();
// Second, we determine if there is a difference between what the size currently
// is and what the user has requested.
point_type diffWidth = width > 0.0f ? width - _width.cur : 0.0f;
point_type diffHeight = height > 0.0f ? height - _height.cur : 0.0f;
return resizeAdd(diffWidth, diffHeight);
}
bool Window::resizeAdd(point_type diffWidth, point_type diffHeight) {
if(
_width.cur + diffWidth < _width.min ||
_height.cur + diffHeight < _height.min
) {
warn()
<< "Window [" << _name << "] can't call resizeAdd() with the "
<< "values " << diffWidth << " and " << diffHeight << std::endl
;
return false;
}
// Now we initiate the resize, which may or may not succeed.
_resizeImplementation(diffWidth, diffHeight);
// Inform each widget that it has been positioned.
for(Iterator i = begin(); i != end(); i++) if(i->valid()) {
i->get()->dirtyBound();
i->get()->setDimensions();
i->get()->positioned();
}
_setWidthAndHeight();
Widget* bg = _bg();
bg->setSize(_width.cur, _height.cur);
bg->dirtyBound();
bg->positioned();
update();
return true;
}
bool Window::resizePercent(point_type width, point_type height) {
if(!_parent && !_wm) {
warn()
<< "Window [" << _name
<< "] cannot resizePercent without being managed or parented."
<< std::endl
;
return false;
}
if(!_parent) return resize(
_wm->getWidth() * (width / 100.0f),
_wm->getHeight() * (height / 100.0f)
);
else return resize(
_parent->getWidth() * (width / 100.0f),
_parent->getHeight() * (height / 100.0f)
);
}
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();
}
matrix_type x = _x;
matrix_type y = _y;
XYCoord xy = getAbsoluteOrigin();
// We only honor ANCHOR requests on topmost Windows, not embedded ones.
if((_vAnchor != VA_NONE || _hAnchor != HA_NONE) && !_parent && _wm) {
if(_vAnchor == VA_TOP) y = 0.0f;
else if(_vAnchor == VA_CENTER) y = osg::round(_wm->getHeight() / 2.0f);
else if(_vAnchor == VA_BOTTOM) y = _wm->getHeight() - _height.cur;
if(_hAnchor == HA_LEFT) x = 0.0f;
else if(_hAnchor == HA_CENTER) x = osg::round(_wm->getWidth() / 2.0f);
else if(_hAnchor == HA_RIGHT) x = _wm->getWidth() - _width.cur + _visibleArea[2];
xy.set(x, y);
}
// Update the Window itself, setting it's matrix according to translate, rotate, and
// scale values.
osg::Matrix r = osg::Matrix::rotate(
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);
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.cur);
int h = static_cast<int>(_height.cur);
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) {
warn()
<< "Window [" << _name << "] doesn't know its " << size
<< " (" << val << ")." << std::endl
;
}
void Window::_setWidthAndHeightNotPAError(const std::string& size, point_type val) {
warn()
<< "Window [" << _name
<< "] should be pixel-aligned, but a remainder was detected for it's "
<< size << " (" << val << ")." << std::endl
;
}
// Since there is so much error-checking associated with setting the width and height properly
// of a Window, this function attempts to abstract some of that tedium.
void Window::_setWidthAndHeight() {
_width = _getWidthImplementation();
_height = _getHeightImplementation();
if(_width.cur < 0.0f) _setWidthAndHeightUnknownSizeError("current width", _width.cur);
if(_width.min < 0.0f) _setWidthAndHeightUnknownSizeError("minimum width", _width.min);
if(_height.cur < 0.0f) _setWidthAndHeightUnknownSizeError("current height", _height.cur);
if(_height.min < 0.0f) _setWidthAndHeightUnknownSizeError("minimum height", _height.min);
if(hasDecimal(_width.cur)) _setWidthAndHeightNotPAError("current width", _width.cur);
if(hasDecimal(_width.min)) _setWidthAndHeightNotPAError("minimum width", _width.min);
if(hasDecimal(_height.cur)) _setWidthAndHeightNotPAError("current height", _height.cur);
if(hasDecimal(_height.min)) _setWidthAndHeightNotPAError("minimum height", _height.min);
}
void Window::_removeFromGeode(Widget* widget) {
if(!widget) return;
widget->_index = -1;
_setParented(widget, true);
_geode()->removeDrawable(widget);
}
// This is a somewhat complicated function designed to only be called by derived classes,
// allowing them to insert Widgets (which can be added to the Window in any way the derived
// class sees fit) into the REAL internal _objects container.
// TODO: This doesn't handle insertion properly!!!
bool Window::_setWidget(Widget* widget, int index) {
if(!widget) {
warn() << "Window [" << _name << "] called addWidget with NULL." << std::endl;
return false;
}
if(widget->_parent) {
warn()
<< "Window [" << _name
<< "] attempted to parent Widget [" << widget->getName()
<< "], which is already parented by [" << widget->_parent->getName()
<< "]." << std::endl
;
return false;
}
if(index >= 0 && index >= static_cast<int>(size())) {
warn()
<< "Window [" << _name
<< "] attempted to manually insert the Widget [" << widget->getName()
<< "] at position " << index
<< ", but there is not enough space available."
<< std::endl
;
return false;
}
// If we're just appending another widget...
if(index < 0) _objects.push_back(widget);
// Otherwise, we're inserting and need to call removeWidget on the old
// one (if valid)...
else {
if(_objects[index].valid()) _removeFromGeode(_objects[index].get());
_objects[index] = widget;
}
osg::Geode* geode = _geode();
widget->_index = geode->getNumDrawables();
geode->addDrawable(widget);
_setParented(widget);
_setManaged(widget);
_setStyled(widget);
// We make sure and resize after every added Widget. This ensures the most
// accurate geometry...
resize();
return true;
}
bool Window::_setVisible(bool visible) {
if(!_wm) return false;
_wm->setValue(_index, visible);
return true;
}
void Window::_setFocused(Widget* widget) {
if(widget && _wm) {
Event ev(_wm);
ev._window = this;
if(_focused.valid()) {
ev._widget = _focused.get();
_focused->callMethodAndCallbacks(ev.makeType(EVENT_UNFOCUS));
}
_focused = widget;
ev._widget = widget;
_focused->callMethodAndCallbacks(ev.makeType(EVENT_FOCUS));
}
}
void Window::_setStyled(Widget* widget) {
if(!widget || !_wm) return;
if(!widget->_isStyled) return;
widget->_isStyled = true;
_wm->getStyleManager()->applyStyles(widget);
}
void Window::_setParented(Widget* widget, bool setUnparented) {
if(!widget) return;
if(!setUnparented) {
widget->_parent = this;
widget->parented(this);
}
else {
widget->_parent = 0;
widget->unparented(this);
}
}
void Window::_setManaged(Widget* widget, bool setUnmanaged) {
if(!widget || !_wm) return;
// Tell the widget it's managed if it isn't already...
if(!setUnmanaged) {
if(widget->_isManaged) return;
widget->_isManaged = true;
widget->managed(_wm);
}
// Otherwise, make sure it IS managed and tell it that it no longer will be. :)
else {
if(!widget->_isManaged) return;
widget->_isManaged = false;
widget->unmanaged(_wm);
}
}
Widget* Window::_getBackground() const {
const osg::Geode* geode = _geode();
// lol...
if(geode) return dynamic_cast<Widget*>(const_cast<osg::Drawable*>(geode->getDrawable(0)));
return 0;
}
Window* Window::_getTopmostParent() const {
WindowList windowList;
getParentList(windowList);
return windowList.back().get();
}
// This will position a widget based on the amount of width and height it has
// to fill. The x/y values should already be set, since we will be adding here.
// However, the width and height can be anything and will be adjusted accordingly.
void Window::_positionWidget(Widget* widget, point_type width, point_type height) {
point_type w = widget->getWidth();
point_type h = widget->getHeight();
point_type pl = widget->getPadLeft();
point_type pr = widget->getPadRight();
point_type pt = widget->getPadTop();
point_type pb = widget->getPadBottom();
if(widget->canFill()) {
point_type nw = osg::round(width - pr - pl);
point_type nh = osg::round(height - pt - pb);
widget->addOrigin(pl, pb);
if(w != nw) widget->setWidth(nw);
if(h != nh) widget->setHeight(nh);
return;
}
point_type ha = osg::round((width - w - pl - pr) / 2.0f);
point_type va = osg::round((height - h - pt - pb) / 2.0f);
// Handle HORIZONTAL alignment.
if(widget->getAlignHorizontal() == Widget::HA_LEFT) widget->addX(pl);
else if(widget->getAlignHorizontal() == Widget::HA_RIGHT) widget->addX(width - w - pr);
else widget->addX(ha + pl);
// Handle VERTICAL alignment.
if(widget->getAlignVertical() == Widget::VA_BOTTOM) widget->addY(height - h - pt);
else if(widget->getAlignVertical() == Widget::VA_TOP) widget->addY(pb);
else widget->addY(va + pb);
}
bool Window::isVisible() const {
if(!_wm) return false;
return _wm->getValue(_index);
}
bool Window::isXYWithinVisible(float x, float y) const {
return
(x >= _visibleArea[0] && x <= (_visibleArea[0] + _visibleArea[2])) &&
(y >= _visibleArea[1] && y <= (_visibleArea[1] + _visibleArea[3]))
;
}
void Window::setVisibleArea(int x, int y, int w, int h) {
_visibleArea[0] = x;
_visibleArea[1] = y;
_visibleArea[2] = w;
_visibleArea[3] = h;
}
void Window::addVisibleArea(int x, int y, int w, int h) {
_visibleArea[0] += x;
_visibleArea[1] += y;
_visibleArea[2] += w;
_visibleArea[3] += h;
}
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.
if(!widget) {
warn() << "Window [" << _name << "] can't focus a NULL Widget." << std::endl;
return false;
}
ConstIterator i = std::find(begin(), end(), widget);
if(i == end()) {
warn()
<< "Window [" << _name
<< "] couldn't find the Widget [" << widget->getName()
<< "] in it's object list." << std::endl
;
return false;
}
_setFocused(i->get());
return true;
}
bool Window::setFocused(const std::string& name) {
Widget* w = getByName(name);
if(!w) {
warn()
<< "Window [" << _name
<< "] couldn't find a Widget named [" << name
<< "] to set as it's focus." << std::endl
;
return false;
}
_setFocused(w);
return true;
}
bool Window::setFirstFocusable() {
WidgetList focusList;
if(getFocusList(focusList)) {
_setFocused(focusList.front().get());
return true;
}
return false;
}
bool Window::setNextFocusable() {
WidgetList focusList;
if(!getFocusList(focusList)) return false;
WidgetList::iterator w = focusList.begin();
// TODO: This needs to be a more complicated object, since the focus may be
// in a child Window instead of a Widget.
unsigned int focusedIndex = 0;
for(unsigned int i = 0; w != focusList.end(); w++, i++) if(*w == _focused) {
focusedIndex = i;
break;
}
if(focusedIndex < focusList.size() - 1) _setFocused((++w)->get());
else _setFocused(focusList.front().get());
return true;
}
XYCoord Window::localXY(double absx, double absy) const {
XYCoord xy = getAbsoluteOrigin();
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]);
}
XYCoord Window::getAbsoluteOrigin() const {
XYCoord xy(0, 0);
WindowList windowList;
getParentList(windowList);
for(WindowList::iterator i = windowList.begin(); i != windowList.end(); i++) {
if(!i->valid()) continue;
xy.x() += static_cast<int>(i->get()->getX());
xy.y() += static_cast<int>(i->get()->getY());
}
return xy;
}
Window::EmbeddedWindow* Window::embed() {
EmbeddedWindow* ew = new EmbeddedWindow(_name + "Embedded", getWidth(), getHeight());
ew->setWindow(this);
ew->setSize(getWidth(), getHeight());
ew->setMinimumSize(getMinWidth(), getMinHeight());
ew->setCanFill(true);
return ew;
}
bool Window::getFocusList(WidgetList& wl) const {
for(ConstIterator i = begin(); i != end(); i++) if(i->valid()) {
EmbeddedWindow* ew = dynamic_cast<EmbeddedWindow*>(i->get());
if(!ew) {
if(i->get()->canFocus()) wl.push_back(i->get());
}
else {
if(ew->getWindow()) ew->getWindow()->getFocusList(wl);
}
}
return wl.size() != 0;
}
bool Window::getEmbeddedList(WindowList& wl) const {
for(ConstIterator i = begin(); i != end(); i++) if(i->valid()) {
EmbeddedWindow* ew = dynamic_cast<EmbeddedWindow*>(i->get());
if(!ew || !ew->getWindow()) continue;
wl.push_back(ew->getWindow());
}
return wl.size() != 0;
}
void Window::getParentList(WindowList& wl) const {
const Window* current = this;
while(current) {
wl.push_back(const_cast<Window*>(current));
if(current->_parent) current = current->_parent;
else current = 0;
}
}
void Window::managed(WindowManager* wm) {
_wm = wm;
for(Iterator i = begin(); i != end(); i++) {
_setManaged(i->get());
_setStyled(i->get());
}
setFirstFocusable();
resize();
update();
}
void Window::unmanaged(WindowManager* wm) {
for(Iterator i = begin(); i != end(); i++) _setManaged(i->get(), true);
_wm = 0;
}
bool Window::addWidget(Widget* widget) {
return _setWidget(widget);
}
bool Window::insertWidget(Widget* widget, unsigned int pos) {
return _setWidget(widget, pos);
}
bool Window::removeWidget(Widget* widget) {
if(!widget) return false;
if(_remove(widget)) {
_removeFromGeode(widget);
resize();
return true;
}
return false;
}
bool Window::replaceWidget(Widget* oldWidget, Widget* newWidget) {
return false;
}
unsigned int Window::addDrawableAndGetIndex(osg::Drawable* drawable) {
osg::Geode* geode = _geode();
if(geode->addDrawable(drawable)) return geode->getDrawableIndex(drawable);
// 0 is a valid error return code here, since our background widget should be
// the first child.
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...
point_type Window::_getMinWidgetWidth(int begin, int end, int add) const {
return _compare<Less>(&Widget::getWidth, begin, end, add);
}
point_type Window::_getMinWidgetHeight(int begin, int end, int add) const {
return _compare<Less>(&Widget::getHeight, begin, end, add);
}
point_type Window::_getMaxWidgetWidth(int begin, int end, int add) const {
return _compare<Greater>(&Widget::getWidth, begin, end, add);
}
point_type Window::_getMaxWidgetHeight(int begin, int end, int add) const {
return _compare<Greater>(&Widget::getHeight, begin, end, add);
}
point_type Window::_getMinWidgetMinWidth(int begin, int end, int add) const {
return _compare<Less>(&Widget::getMinWidth, begin, end, add);
}
point_type Window::_getMinWidgetMinHeight(int begin, int end, int add) const {
return _compare<Less>(&Widget::getMinHeight, begin, end, add);
}
point_type Window::_getMaxWidgetMinWidth(int begin, int end, int add) const {
return _compare<Greater>(&Widget::getMinWidth, begin, end, add);
}
point_type Window::_getMaxWidgetMinHeight(int begin, int end, int add) const {
return _compare<Greater>(&Widget::getMinHeight, begin, end, add);
}
point_type Window::_getMinWidgetWidthTotal(int begin, int end, int add) const {
return _compare<Less>(&Widget::getWidthTotal, begin, end, add);
}
point_type Window::_getMinWidgetHeightTotal(int begin, int end, int add) const {
return _compare<Less>(&Widget::getHeightTotal, begin, end, add);
}
point_type Window::_getMaxWidgetWidthTotal(int begin, int end, int add) const {
return _compare<Greater>(&Widget::getWidthTotal, begin, end, add);
}
point_type Window::_getMaxWidgetHeightTotal(int begin, int end, int add) const {
return _compare<Greater>(&Widget::getHeightTotal, begin, end, add);
}
point_type Window::_getMinWidgetMinWidthTotal(int begin, int end, int add) const {
return _compare<Less>(&Widget::getMinWidthTotal, begin, end, add);
}
point_type Window::_getMinWidgetMinHeightTotal(int begin, int end, int add) const {
return _compare<Less>(&Widget::getMinHeightTotal, begin, end, add);
}
point_type Window::_getMaxWidgetMinWidthTotal(int begin, int end, int add) const {
return _compare<Greater>(&Widget::getMinWidthTotal, begin, end, add);
}
point_type Window::_getMaxWidgetMinHeightTotal(int begin, int end, int add) const {
return _compare<Greater>(&Widget::getMinHeightTotal, begin, end, add);
}
point_type Window::_getMinWidgetPadHorizontal(int begin, int end, int add) const {
return _compare<Less>(&Widget::getPadHorizontal, begin, end, add);
}
point_type Window::_getMinWidgetPadVertical(int begin, int end, int add) const {
return _compare<Less>(&Widget::getPadVertical, begin, end, add);
}
point_type Window::_getMaxWidgetPadHorizontal(int begin, int end, int add) const {
return _compare<Greater>(&Widget::getPadHorizontal, begin, end, add);
}
point_type Window::_getMaxWidgetPadVertical(int begin, int end, int add) const {
return _compare<Greater>(&Widget::getPadVertical, begin, end, add);
}
point_type Window::_getNumFill(int begin, int end, int add) const {
return _accumulate<Plus>(&Widget::getFillAsNumeric, begin, end, add);
}
Window::Sizes Window::_getWidthImplementation() const {
osg::BoundingBox bb = getGeode()->getBoundingBox();
point_type w = osg::round(bb.xMax() - bb.xMin());
return Sizes(w, w);
}
Window::Sizes Window::_getHeightImplementation() const {
osg::BoundingBox bb = getGeode()->getBoundingBox();
point_type h = osg::round(bb.yMax() - bb.yMin());
return Sizes(h, h);
}
}

View File

@ -0,0 +1,587 @@
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008
// $Id: WindowManager.cpp 66 2008-07-14 21:54:09Z cubicool $
#include <iostream>
#include <algorithm>
#include <osg/io_utils>
#include <osgWidget/Types>
#include <osgWidget/Util>
#include <osgWidget/WindowManager>
#include <osgWidget/Lua>
#include <osgWidget/Python>
#include <osgWidget/Box>
#include <osgWidget/Label>
namespace osgWidget {
WindowManager::WindowManager(
osgViewer::View* view,
point_type width,
point_type height,
unsigned int nodeMask,
unsigned int flags
):
_width (width),
_height (height),
_zNear (0.0f),
_zFar (-1.0f),
_numForeground (0.0f),
_numBackground (0.0f),
_flags (flags),
_nodeMask (nodeMask),
_view (view),
_lastX (0.0f),
_lastY (0.0f),
_lastEvent (0),
_lastPush (0),
_lastVertical (PD_NONE),
_lastHorizontal (PD_NONE),
_focusMode (PFM_FOCUS),
_leftDown (false),
_middleDown (false),
_rightDown (false),
_scrolling (osgGA::GUIEventAdapter::SCROLL_NONE),
_styleManager (new StyleManager()) {
_name = generateRandomName("WindowManager");
if(_flags & WM_USE_LUA) {
_lua = new LuaEngine(this);
if(!_lua->initialize()) warn() << "Error creating LuaEngine." << std::endl;
}
if(_flags & WM_USE_PYTHON) {
_python = new PythonEngine(this);
if(!_python->initialize()) warn() << "Error creating PythonEngine." << std::endl;
}
// Setup our picking debug (is debug the right word here?) Window...
if(_flags & WM_PICK_DEBUG) {
_pickWindow = new Box("PickWindow", Box::VERTICAL);
Label* label = new Label("PickLabel");
label->setFontSize(13);
label->setFontColor(1.0f, 1.0f, 1.0f, 1.0f);
label->setFont("fonts/monospace.ttf");
label->setPadding(5.0f);
label->setCanFill(true);
_pickWindow->getBackground()->setColor(0.0f, 0.0f, 0.0f, 0.85f);
_pickWindow->addWidget(label);
_pickWindow->setNodeMask(~_nodeMask);
_pickWindow->removeEventMask(EVENT_MASK_FOCUS);
_pickWindow->setStrata(Window::STRATA_FOREGROUND);
addChild(_pickWindow.get());
_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);
}
}
WindowManager::WindowManager(const WindowManager& wm, const osg::CopyOp& co):
osg::Switch(wm, co) {
}
WindowManager::~WindowManager() {
if(_flags & WM_USE_LUA) _lua->close();
if(_flags & WM_USE_PYTHON) _python->close();
}
void WindowManager::setEventFromInterface(Event& ev, EventInterface* ei) {
Widget* widget = dynamic_cast<Widget*>(ei);
Window* window = dynamic_cast<Window*>(ei);
if(widget) {
ev._window = widget->getParent();
ev._widget = widget;
}
else if(window) ev._window = window;
}
bool WindowManager::_handleMousePushed(float x, float y, bool& down) {
down = true;
Event ev(this, EVENT_MOUSE_PUSH);
WidgetList widgetList;
if(!pickAtXY(x, y, widgetList)) return false;
ev.makeMouse(x, y);
_lastPush = getFirstEventInterface(widgetList, ev);
if(!_lastPush) return false;
bool handled = _lastPush->callMethodAndCallbacks(ev);
if(_focusMode != PFM_SLOPPY) {
if(ev._window) {
Window* topmostWindow = ev._window->getTopmostParent();
setFocused(topmostWindow);
if(ev._widget) topmostWindow->setFocused(ev._widget);
}
// If the user wants to be able to "unfocus" the last Window.
else if(_focusMode == PFM_UNFOCUS) setFocused(0);
}
return handled;
}
bool WindowManager::_handleMouseReleased(float x, float y, bool& down) {
down = false;
// If were were in a drag state, reset our boolean flag.
// if(_lastDrag) _lastDrag = 0;
if(!_lastPush) return false;
// By design, we can only release an EventInterface we previously pressed.
// Whether or not we're ON the EventInterface when the release occurs isn't important.
Event ev(this, EVENT_MOUSE_RELEASE);
setEventFromInterface(ev, _lastPush);
bool handled = _lastPush->callMethodAndCallbacks(ev);
_lastPush = 0;
return handled;
}
void WindowManager::_getPointerXYDiff(float& x, float& y) {
x -= _lastX;
if(isInvertedY()) y = -(y - _lastY);
else y -= _lastY;
}
void WindowManager::_updatePickWindow(const WidgetList* wl, point_type x, point_type y) {
Label* label = dynamic_cast<Label*>(_pickWindow->getByName("PickLabel"));
if(!wl) {
setValue(0, false);
return;
}
setValue(0, true);
std::stringstream ss;
point_type xdiff = x;
point_type ydiff = y;
_getPointerXYDiff(xdiff, ydiff);
ss
<< "At XY Coords: " << x << ", " << _height - y
<< " ( diff " << xdiff << ", " << ydiff << " )"
<< std::endl
;
const Window* parent = wl->back()->getParent();
ss
<< "Window: " << parent->getName()
<< " ( xyz " << parent->getPosition() << " )"
<< " { zRange " << parent->getZRange() << " }"
<< " < size " << parent->getSize() << " >"
<< " EventMask: " << std::hex << parent->getEventMask()
<< std::endl
;
for(WidgetList::const_iterator i = wl->begin(); i != wl->end(); i++) {
Widget* widget = i->get();
ss
<< " - " << widget->getName()
<< " ( xyz " << widget->getPosition() << " )"
<< " [ XYZ " << widget->getPosition() * parent->getMatrix()
<< " ] < size " << widget->getSize() << " >"
<< " EventMask: " << std::hex << widget->getEventMask()
<< std::endl
;
}
label->setLabel(ss.str());
XYCoord size = label->getTextSize();
_pickWindow->resize(size.x() + 10.0f, size.y() + 10.0f);
_pickWindow->setOrigin(5.0f, _height - _pickWindow->getHeight() - 5.0f);
_pickWindow->update();
}
void WindowManager::childInserted(unsigned int i) {
Window* window = dynamic_cast<Window*>(getChild(i));
if(!window) return;
_objects.push_back(window);
window->_index = i;
setFocused(window);
window->setNodeMask(_nodeMask);
window->managed(this);
for(Window::Iterator w = window->begin(); w != window->end(); w++) if(w->valid()) {
_styleManager->applyStyles(w->get());
}
_styleManager->applyStyles(window);
}
void WindowManager::childRemoved(unsigned int start, unsigned int end) {
while(start < end) {
Window* window = getByIndex(start);
if(!window) continue;
if(_remove(window)) {
window->_index = -1;
window->unmanaged(this);
}
start++;
}
}
// This method performs intersection testing at the given XY coords, and returns true if
// any intersections were found. It will break after processing the first pickable Window
// it finds.
bool WindowManager::pickAtXY(float x, float y, WidgetList& wl) {
Intersections intr;
if(_view->computeIntersections(x, y, intr, _nodeMask)) {
// Get the first Window at the XY coordinates; if you want a Window to be
// non-pickable, set the NodeMask to something else.
Window* activeWin = 0;
// Iterate over every picked result and create a list of Widgets that belong
// to that Window.
for(Intersections::iterator i = intr.begin(); i != intr.end(); i++) {
Window* win = dynamic_cast<Window*>(i->nodePath.back()->getParent(0));
// 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)
) continue;
// Set our activeWin, so that we know when we've got all the Widgets
// that belong to it.
if(!activeWin) activeWin = win;
// If we've found a new Widnow, break out!
else if(activeWin != win) break;
Widget* widget = dynamic_cast<Widget*>(i->drawable.get());
if(!widget) continue;
// We need to return a list of every Widget that was picked, so
// that the handler can operate on it accordingly.
else wl.push_back(widget);
}
if(wl.size()) {
// Potentially VERY expensive; only to be used for debugging. :)
if(_flags & WM_PICK_DEBUG) _updatePickWindow(&wl, x, y);
return true;
}
}
if(_flags & WM_PICK_DEBUG) _updatePickWindow(0, x, y);
return false;
}
bool WindowManager::setFocused(Window* window) {
Event ev(this);
ev._window = window;
// Inform the previously focused Window that it is going to be unfocused.
if(_focused.valid()) _focused->callMethodAndCallbacks(ev.makeType(EVENT_UNFOCUS));
_focused = window;
if(!window || !window->canFocus()) return false;
// Build a vector of every Window that is focusable, in the foreground, and in the
// background. All these Windows are handled differently.
Vector focusable;
Vector bg;
Vector fg;
for(ConstIterator i = begin(); i != end(); i++) if(i->valid()) {
Window* w = i->get();
if(w->getStrata() == Window::STRATA_FOREGROUND) fg.push_back(w);
else if(w->getStrata() == Window::STRATA_BACKGROUND) bg.push_back(w);
else focusable.push_back(w);
}
// After this call to sort, the internal objects will be arranged such that the
// previously focused window is the first, followed by all other Windows in
// descending order.
std::sort(focusable.begin(), focusable.end(), WindowZCompare());
// This is the depth range for each Window. Each Window object must be informed of
// 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);
// Our offset for the following for() loop.
unsigned int i = 3;
// Handle all of our focusable Windows.
for(Iterator w = focusable.begin(); w != focusable.end(); w++) {
Window* win = w->get();
// Set our newly focused Window as the topmost element.
if(*w == window) win->_z = -zRange * 2.0f;
// Set the current Z of the remaining Windows and set their zRange so that
// they can update their own children.
else {
win->_z = -zRange * i;
i++;
}
}
// Handled our special BACKGROUND Windows.
for(Iterator w = bg.begin(); w != bg.end(); w++) w->get()->_z = -zRange * i;
// Handle our special FOREGOUND Windows.
for(Iterator w = fg.begin(); w != fg.end(); w++) w->get()->_z = -zRange;
// Update every window, regardless.
for(Iterator w = begin(); w != end(); w++) {
Window* win = w->get();
win->_zRange = zRange;
win->update();
}
_focused->callMethodAndCallbacks(ev.makeType(EVENT_FOCUS));
return true;
}
void WindowManager::setPointerXY(float x, float y) {
float xdiff = x;
float ydiff = y;
_getPointerXYDiff(xdiff, ydiff);
// If ydiff isn't NEAR 0 (floating point booleans aren't 100% reliable, but that
// doesn't matter in our case), assume we have either up or down movement.
if(ydiff != 0.0f) _lastVertical = ydiff > 0.0f ? PD_UP : PD_DOWN;
else _lastVertical = PD_NONE;
// If xdiff isn't 0, assume we have either left or right movement.
if(xdiff != 0.0f) _lastHorizontal = xdiff > 0.0f ? PD_RIGHT : PD_LEFT;
else _lastHorizontal = PD_NONE;
_lastX = x;
_lastY = y;
}
void WindowManager::setStyleManager(StyleManager* sm) {
_styleManager = sm;
for(Iterator i = begin(); i != end(); i++) if(i->valid()) {
Window* window = i->get();
for(Window::Iterator w = window->begin(); w != window->end(); w++) {
if(!w->valid()) continue;
_styleManager->applyStyles(w->get());
}
_styleManager->applyStyles(window);
}
}
void WindowManager::resizeAllWindows(bool visible) {
for(Iterator i = begin(); i != end(); i++) if(i->valid()) {
if(visible && !getValue(i->get()->_index)) continue;
i->get()->resize();
}
}
// 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.
bool WindowManager::pointerMove(float x, float y) {
WidgetList wl;
Event ev(this);
if(!pickAtXY(x, y, wl)) {
if(_lastEvent) {
setEventFromInterface(ev.makeMouse(x, y, EVENT_MOUSE_LEAVE), _lastEvent);
_lastEvent->callMethodAndCallbacks(ev);
}
if(_focusMode == PFM_SLOPPY) setFocused(0);
_lastEvent = 0;
_leftDown = 0;
_middleDown = 0;
_rightDown = 0;
return false;
}
EventInterface* ei = getFirstEventInterface(wl, ev.makeMouse(x, y, EVENT_MOUSE_OVER));
if(!ei) return false;
if(_lastEvent != ei) {
if(_lastEvent) {
Event evLeave(this);
evLeave.makeMouse(x, y, EVENT_MOUSE_LEAVE);
setEventFromInterface(evLeave, _lastEvent);
_lastEvent->callMethodAndCallbacks(evLeave);
}
_lastEvent = ei;
if(_focusMode == PFM_SLOPPY && ev._window) setFocused(ev._window);
_lastEvent->callMethodAndCallbacks(ev.makeMouse(x, y, EVENT_MOUSE_ENTER));
}
ei->callMethodAndCallbacks(ev.makeMouse(x, y, EVENT_MOUSE_OVER));
return true;
}
bool WindowManager::pointerDrag(float x, float y) {
WidgetList widgetList;
Event ev(this);
float xdiff = x;
float ydiff = y;
_getPointerXYDiff(xdiff, ydiff);
ev.makeMouse(xdiff, ydiff, EVENT_MOUSE_DRAG);
// If we're still in the drag state...
if(_lastPush) {
setEventFromInterface(ev, _lastPush);
return _lastPush->callMethodAndCallbacks(ev);
}
return false;
}
bool WindowManager::mouseScroll(float x, float y) {
WidgetList wl;
if(!pickAtXY(x, y, wl)) return false;
Event ev(this, EVENT_MOUSE_SCROLL);
EventInterface* ei = getFirstEventInterface(wl, ev);
if(!ei) return false;
return ei->callMethodAndCallbacks(ev);
}
// Keypresses only go the focused Window.
bool WindowManager::keyDown(int key, int mask) {
if(_focused.valid()) {
Event ev(this, EVENT_KEY_DOWN);
ev.makeKey(key, mask);
Widget* focusedWidget = _focused->getFocused();
ev._window = _focused.get();
ev._widget = focusedWidget;
bool handled = false;
if(focusedWidget) handled = focusedWidget->callMethodAndCallbacks(ev);
if(!handled) return _focused->callMethodAndCallbacks(ev);
else return true;
}
return false;
}
bool WindowManager::keyUp(int key, int mask) {
return true;
}
// 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);
camera->addChild(this);
return camera;
}
}