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:
parent
0c3d119cea
commit
c2b77aa08e
@ -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)
|
||||
|
||||
|
9
examples/osgwidgetaddremove/CMakeLists.txt
Normal file
9
examples/osgwidgetaddremove/CMakeLists.txt
Normal 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)
|
134
examples/osgwidgetaddremove/osgwidgetaddremove.cpp
Normal file
134
examples/osgwidgetaddremove/osgwidgetaddremove.cpp
Normal 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);
|
||||
}
|
9
examples/osgwidgetbox/CMakeLists.txt
Normal file
9
examples/osgwidgetbox/CMakeLists.txt
Normal 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)
|
122
examples/osgwidgetbox/osgwidgetbox.cpp
Normal file
122
examples/osgwidgetbox/osgwidgetbox.cpp
Normal 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);
|
||||
}
|
9
examples/osgwidgetcanvas/CMakeLists.txt
Normal file
9
examples/osgwidgetcanvas/CMakeLists.txt
Normal 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)
|
118
examples/osgwidgetcanvas/osgwidgetcanvas.cpp
Normal file
118
examples/osgwidgetcanvas/osgwidgetcanvas.cpp
Normal 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);
|
||||
}
|
9
examples/osgwidgetframe/CMakeLists.txt
Normal file
9
examples/osgwidgetframe/CMakeLists.txt
Normal 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)
|
89
examples/osgwidgetframe/osgwidgetframe.cpp
Normal file
89
examples/osgwidgetframe/osgwidgetframe.cpp
Normal 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);
|
||||
}
|
9
examples/osgwidgetinput/CMakeLists.txt
Normal file
9
examples/osgwidgetinput/CMakeLists.txt
Normal 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)
|
186
examples/osgwidgetinput/osgwidgetinput.cpp
Normal file
186
examples/osgwidgetinput/osgwidgetinput.cpp
Normal 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;
|
||||
}
|
9
examples/osgwidgetlabel/CMakeLists.txt
Normal file
9
examples/osgwidgetlabel/CMakeLists.txt
Normal 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)
|
120
examples/osgwidgetlabel/osgwidgetlabel.cpp
Normal file
120
examples/osgwidgetlabel/osgwidgetlabel.cpp
Normal 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);
|
||||
}
|
9
examples/osgwidgetmenu/CMakeLists.txt
Normal file
9
examples/osgwidgetmenu/CMakeLists.txt
Normal 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)
|
129
examples/osgwidgetmenu/osgwidgetmenu.cpp
Normal file
129
examples/osgwidgetmenu/osgwidgetmenu.cpp
Normal 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);
|
||||
}
|
9
examples/osgwidgetnotebook/CMakeLists.txt
Normal file
9
examples/osgwidgetnotebook/CMakeLists.txt
Normal 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)
|
134
examples/osgwidgetnotebook/osgwidgetnotebook.cpp
Normal file
134
examples/osgwidgetnotebook/osgwidgetnotebook.cpp
Normal 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);
|
||||
}
|
9
examples/osgwidgetscrolled/CMakeLists.txt
Normal file
9
examples/osgwidgetscrolled/CMakeLists.txt
Normal 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)
|
134
examples/osgwidgetscrolled/osgwidgetscrolled.cpp
Normal file
134
examples/osgwidgetscrolled/osgwidgetscrolled.cpp
Normal 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);
|
||||
}
|
9
examples/osgwidgetshader/CMakeLists.txt
Normal file
9
examples/osgwidgetshader/CMakeLists.txt
Normal 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)
|
74
examples/osgwidgetshader/osgwidgetshader.cpp
Normal file
74
examples/osgwidgetshader/osgwidgetshader.cpp
Normal 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);
|
||||
}
|
9
examples/osgwidgetstyled/CMakeLists.txt
Normal file
9
examples/osgwidgetstyled/CMakeLists.txt
Normal 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)
|
83
examples/osgwidgetstyled/osgwidgetstyled.cpp
Normal file
83
examples/osgwidgetstyled/osgwidgetstyled.cpp
Normal 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);
|
||||
}
|
9
examples/osgwidgettable/CMakeLists.txt
Normal file
9
examples/osgwidgettable/CMakeLists.txt
Normal 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)
|
69
examples/osgwidgettable/osgwidgettable.cpp
Normal file
69
examples/osgwidgettable/osgwidgettable.cpp
Normal 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);
|
||||
}
|
9
examples/osgwidgetversion/CMakeLists.txt
Normal file
9
examples/osgwidgetversion/CMakeLists.txt
Normal 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)
|
14
examples/osgwidgetversion/osgwidgetversion.cpp
Normal file
14
examples/osgwidgetversion/osgwidgetversion.cpp
Normal 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;
|
||||
}
|
9
examples/osgwidgetwindow/CMakeLists.txt
Normal file
9
examples/osgwidgetwindow/CMakeLists.txt
Normal 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)
|
204
examples/osgwidgetwindow/osgwidgetwindow.cpp
Normal file
204
examples/osgwidgetwindow/osgwidgetwindow.cpp
Normal 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
39
include/osgWidget/Box
Normal 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
28
include/osgWidget/Canvas
Normal 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
|
376
include/osgWidget/EventInterface
Normal file
376
include/osgWidget/EventInterface
Normal 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
47
include/osgWidget/Export
Normal 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
161
include/osgWidget/Frame
Normal 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
77
include/osgWidget/Input
Normal 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
59
include/osgWidget/Label
Normal 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
31
include/osgWidget/Lua
Normal 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
28
include/osgWidget/Python
Normal 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
|
29
include/osgWidget/ScriptEngine
Normal file
29
include/osgWidget/ScriptEngine
Normal 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
|
39
include/osgWidget/StyleInterface
Normal file
39
include/osgWidget/StyleInterface
Normal 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
|
175
include/osgWidget/StyleManager
Normal file
175
include/osgWidget/StyleManager
Normal 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
63
include/osgWidget/Table
Normal 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
31
include/osgWidget/Types
Normal 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
|
123
include/osgWidget/UIObjectParent
Normal file
123
include/osgWidget/UIObjectParent
Normal 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
79
include/osgWidget/Util
Normal 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
23
include/osgWidget/Version
Normal 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
|
78
include/osgWidget/ViewerEventHandlers
Normal file
78
include/osgWidget/ViewerEventHandlers
Normal 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
626
include/osgWidget/Widget
Normal 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
636
include/osgWidget/Window
Normal 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
|
358
include/osgWidget/WindowManager
Normal file
358
include/osgWidget/WindowManager
Normal 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
|
@ -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)
|
||||
|
@ -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)
|
||||
|
113
src/osgPlugins/osgWidget/Box.cpp
Normal file
113
src/osgPlugins/osgWidget/Box.cpp
Normal 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
|
||||
);
|
19
src/osgPlugins/osgWidget/CMakeLists.txt
Normal file
19
src/osgPlugins/osgWidget/CMakeLists.txt
Normal 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)
|
||||
|
||||
|
32
src/osgPlugins/osgWidget/EmbeddedWindow.cpp
Normal file
32
src/osgPlugins/osgWidget/EmbeddedWindow.cpp
Normal 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
|
||||
);
|
30
src/osgPlugins/osgWidget/Frame.cpp
Normal file
30
src/osgPlugins/osgWidget/Frame.cpp
Normal 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
|
||||
);
|
30
src/osgPlugins/osgWidget/Input.cpp
Normal file
30
src/osgPlugins/osgWidget/Input.cpp
Normal 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
|
||||
);
|
30
src/osgPlugins/osgWidget/Label.cpp
Normal file
30
src/osgPlugins/osgWidget/Label.cpp
Normal 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
|
||||
);
|
30
src/osgPlugins/osgWidget/Table.cpp
Normal file
30
src/osgPlugins/osgWidget/Table.cpp
Normal 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
|
||||
);
|
75
src/osgPlugins/osgWidget/Widget.cpp
Normal file
75
src/osgPlugins/osgWidget/Widget.cpp
Normal 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
|
||||
);
|
30
src/osgPlugins/osgWidget/WindowManager.cpp
Normal file
30
src/osgPlugins/osgWidget/WindowManager.cpp
Normal 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
194
src/osgWidget/Box.cpp
Normal 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()
|
||||
);
|
||||
}
|
||||
|
||||
}
|
66
src/osgWidget/CMakeLists.txt
Normal file
66
src/osgWidget/CMakeLists.txt
Normal 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
32
src/osgWidget/Canvas.cpp
Normal 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
251
src/osgWidget/Frame.cpp
Normal 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
176
src/osgWidget/Input.cpp
Normal 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
140
src/osgWidget/Label.cpp
Normal 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
171
src/osgWidget/Lua.cpp
Normal 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
215
src/osgWidget/Python.cpp
Normal 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
|
||||
}
|
||||
|
||||
}
|
376
src/osgWidget/StyleManager.cpp
Normal file
376
src/osgWidget/StyleManager.cpp
Normal 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
225
src/osgWidget/Table.cpp
Normal 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
176
src/osgWidget/Util.cpp
Normal 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
83
src/osgWidget/Version.cpp
Normal 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
|
||||
;
|
||||
}
|
||||
|
||||
}
|
190
src/osgWidget/ViewerEventHandlers.cpp
Normal file
190
src/osgWidget/ViewerEventHandlers.cpp
Normal 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
524
src/osgWidget/Widget.cpp
Normal 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
959
src/osgWidget/Window.cpp
Normal 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);
|
||||
}
|
||||
|
||||
}
|
587
src/osgWidget/WindowManager.cpp
Normal file
587
src/osgWidget/WindowManager.cpp
Normal 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;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user