6a67be2e32
forcing users to use osgDB::readRef*File() methods. The later is preferable as it closes a potential threading bug when using paging databases in conjunction with the osgDB::Registry Object Cache. This threading bug occurs when one thread gets an object from the Cache via an osgDB::read*File() call where only a pointer to the object is passed back, so taking a reference to the object is delayed till it gets reassigned to a ref_ptr<>, but at the same time another thread calls a flush of the Object Cache deleting this object as it's referenceCount is now zero. Using osgDB::readREf*File() makes sure the a ref_ptr<> is passed back and the referenceCount never goes to zero. To ensure the OSG builds when OSG_PROVIDE_READFILE is to OFF the many cases of osgDB::read*File() usage had to be replaced with a ref_ptr<> osgDB::readRef*File() usage. The avoid this change causing lots of other client code to be rewritten to handle the use of ref_ptr<> in place of C pointer I introduced a serious of templte methods in various class to adapt ref_ptr<> to the underly C pointer to be passed to old OSG API's, example of this is found in include/osg/Group: bool addChild(Node* child); // old method which can only be used with a Node* tempalte<class T> bool addChild(const osg::ref_ptr<T>& child) { return addChild(child.get()); } // adapter template method These changes together cover 149 modified files, so it's a large submission. This extent of changes are warrent to make use of the Object Cache and multi-threaded loaded more robust. git-svn-id: http://svn.openscenegraph.org/osg/OpenSceneGraph/branches/OpenSceneGraph-3.4@15165 16af8721-9629-0410-8352-f15c8da7e697
222 lines
9.3 KiB
C++
222 lines
9.3 KiB
C++
// -*-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;
|
|
}
|
|
};
|
|
|
|
// This is the more "traditional" method of creating a callback.
|
|
struct CallbackObject: public osgWidget::Callback {
|
|
CallbackObject(osgWidget::EventType evType):
|
|
osgWidget::Callback(evType) {
|
|
}
|
|
|
|
virtual bool operator()(osgWidget::Event& ev) {
|
|
std::cout << "here" << std::endl;
|
|
|
|
return false;
|
|
}
|
|
};
|
|
|
|
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
|
|
);
|
|
|
|
// 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(new osgWidget::Callback(&windowClicked, osgWidget::EVENT_MOUSE_PUSH, &data));
|
|
box->addCallback(new osgWidget::Callback(&windowScrolled, osgWidget::EVENT_MOUSE_SCROLL));
|
|
box->addCallback(osgWidget::Callback(
|
|
&Object::windowClicked,
|
|
&obj,
|
|
osgWidget::EVENT_MOUSE_PUSH
|
|
));
|
|
*/
|
|
|
|
box->addCallback(new CallbackObject(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::readRefImageFile("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 = osg::clone(box, "newBox", osg::CopyOp::DEEP_COPY_ALL);
|
|
|
|
// 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.
|
|
// std::cout << *box << std::endl << *boxCopy << std::endl;
|
|
|
|
// 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::ref_ptr<osg::Group> group = new osg::Group();
|
|
osg::ref_ptr<osg::Camera> camera = osgWidget::createOrthoCamera(1280.0f, 1024.0f);
|
|
osg::ref_ptr<osg::Node> model = osgDB::readRefNodeFile("cow.osgt");
|
|
|
|
// 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 osgWidget::ResizeHandler(wm, camera.get()));
|
|
viewer.addEventHandler(new osgWidget::CameraSwitchHandler(wm, camera.get()));
|
|
viewer.addEventHandler(new osgViewer::StatsHandler());
|
|
viewer.addEventHandler(new osgViewer::WindowSizeHandler());
|
|
viewer.addEventHandler(new osgGA::StateSetManipulator(
|
|
viewer.getCamera()->getOrCreateStateSet()
|
|
));
|
|
|
|
// 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();
|
|
}
|