root/OpenSceneGraph/trunk/examples/osgwidgetwindow/osgwidgetwindow.cpp
@
13306
| Revision 12529, 9.3 kB (checked in by robert, 2 years ago) | |
|---|---|
|
|
| Line | |
|---|---|
| 1 | // -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008 |
| 2 | // $Id: osgwidgetwindow.cpp 66 2008-07-14 21:54:09Z cubicool $ |
| 3 | |
| 4 | #include <iostream> |
| 5 | #include <osgDB/ReadFile> |
| 6 | #include <osgGA/StateSetManipulator> |
| 7 | #include <osgViewer/Viewer> |
| 8 | #include <osgViewer/ViewerEventHandlers> |
| 9 | #include <osgWidget/WindowManager> |
| 10 | #include <osgWidget/ViewerEventHandlers> |
| 11 | #include <osgWidget/Box> |
| 12 | |
| 13 | const unsigned int MASK_2D = 0xF0000000; |
| 14 | const unsigned int MASK_3D = 0x0F000000; |
| 15 | |
| 16 | // Here we create (and later demonstrate) the use of a simple function callback. |
| 17 | bool windowClicked(osgWidget::Event& ev) { |
| 18 | std::cout << "windowClicked: " << ev.getWindow()->getName() << std::endl; |
| 19 | |
| 20 | if(ev.getData()) { |
| 21 | std::string* s = static_cast<std::string*>(ev.getData()); |
| 22 | |
| 23 | std::cout << "This is data attached to the event: " << *s << std::endl; |
| 24 | } |
| 25 | |
| 26 | return true; |
| 27 | } |
| 28 | |
| 29 | bool windowScrolled(osgWidget::Event& ev) { |
| 30 | osgWidget::warn() |
| 31 | << "scrolling up? " << ev.getWindowManager()->isMouseScrollingUp() |
| 32 | << std::endl |
| 33 | ; |
| 34 | |
| 35 | return true; |
| 36 | } |
| 37 | |
| 38 | // Here we dcreate a new class and show how to use a method callback (which differs from |
| 39 | // a function callback in that we are required to also pass the "this" argument). |
| 40 | struct Object { |
| 41 | bool windowClicked(osgWidget::Event& ev) { |
| 42 | std::cout << "Object::windowClicked " << ev.getWindow()->getName() << std::endl; |
| 43 | |
| 44 | return true; |
| 45 | } |
| 46 | }; |
| 47 | |
| 48 | // This is the more "traditional" method of creating a callback. |
| 49 | struct CallbackObject: public osgWidget::Callback { |
| 50 | CallbackObject(osgWidget::EventType evType): |
| 51 | osgWidget::Callback(evType) { |
| 52 | } |
| 53 | |
| 54 | virtual bool operator()(osgWidget::Event& ev) { |
| 55 | std::cout << "here" << std::endl; |
| 56 | |
| 57 | return false; |
| 58 | } |
| 59 | }; |
| 60 | |
| 61 | int main(int argc, char** argv) { |
| 62 | osgViewer::Viewer viewer; |
| 63 | |
| 64 | // Let's get busy! The WindowManager class is actually an osg::Switch, |
| 65 | // so you can add it to (ideally) an orthographic camera and have it behave as |
| 66 | // expected. Note that you create a WindowManager with a NodeMask--it is very important |
| 67 | // that this be unique for picking to work properly. This also makes it possible to have |
| 68 | // multiple WindowManagers each operating on their own, unique set of Window objects. |
| 69 | // The final bool argument is a group of flags that introduce optional functionality |
| 70 | // for the WindowManager. In our case we include the flags USE_PYTHON and USE_LUA, |
| 71 | // to demonstrate (and test) their usage. Finally, we pass the temporary WM_NO_BETA_WARN |
| 72 | // argument, which prevents creating the orange warning window. :) It will be shown |
| 73 | // in other examples... |
| 74 | osgWidget::WindowManager* wm = new osgWidget::WindowManager( |
| 75 | &viewer, |
| 76 | 1280.0f, |
| 77 | 1024.0f, |
| 78 | MASK_2D, |
| 79 | osgWidget::WindowManager::WM_USE_LUA | |
| 80 | osgWidget::WindowManager::WM_USE_PYTHON | |
| 81 | osgWidget::WindowManager::WM_PICK_DEBUG |
| 82 | ); |
| 83 | |
| 84 | // An actual osgWidget::Window is pure virtual, so we've got to use the osgWidget::Box |
| 85 | // implementation for now. At a later time, support for Tables and other kinds of |
| 86 | // advanced layout Window types will be added. |
| 87 | osgWidget::Window* box = new osgWidget::Box("box", osgWidget::Box::HORIZONTAL); |
| 88 | |
| 89 | // Now we actually attach our two types of callbacks to the box instance. The first |
| 90 | // uses the simple function signature, the second uses a bound method, passing "this" |
| 91 | // as the second argument to the Callback constructor. |
| 92 | // Object obj; |
| 93 | |
| 94 | static std::string data = "lol ur face!"; |
| 95 | |
| 96 | /* |
| 97 | box->addCallback(new osgWidget::Callback(&windowClicked, osgWidget::EVENT_MOUSE_PUSH, &data)); |
| 98 | box->addCallback(new osgWidget::Callback(&windowScrolled, osgWidget::EVENT_MOUSE_SCROLL)); |
| 99 | box->addCallback(osgWidget::Callback( |
| 100 | &Object::windowClicked, |
| 101 | &obj, |
| 102 | osgWidget::EVENT_MOUSE_PUSH |
| 103 | )); |
| 104 | */ |
| 105 | |
| 106 | box->addCallback(new CallbackObject(osgWidget::EVENT_MOUSE_PUSH)); |
| 107 | |
| 108 | // Create some of our "testing" Widgets; included are two Widget subclasses I made |
| 109 | // during testing which I've kept around for testing purposes. You'll notice |
| 110 | // that you cannot move the box using the NullWidget, and that the NotifyWidget |
| 111 | // is a bit verbose. :) |
| 112 | osgWidget::Widget* widget1 = new osgWidget::NotifyWidget("widget1", 300.0f, 100.0f); |
| 113 | osgWidget::Widget* widget2 = new osgWidget::NullWidget("widget2", 400.0f, 75.0f); |
| 114 | osgWidget::Widget* widget3 = new osgWidget::Widget("widget3", 100.0f, 100.0f); |
| 115 | // Set the colors of widget1 and widget3 to green. |
| 116 | widget1->setColor(0.0f, 1.0f, 0.0f, 1.0f); |
| 117 | widget1->setCanFill(true); |
| 118 | widget3->setColor(0.0f, 1.0f, 0.0f, 1.0f); |
| 119 | |
| 120 | widget1->setImage(osgDB::readImageFile("Images/Saturn.TGA"), true); |
| 121 | |
| 122 | // Set the color of widget2, to differentiate it and make it sassy. This is |
| 123 | // like a poor man's gradient! |
| 124 | widget2->setColor(0.9f, 0.0f, 0.0f, 0.9f, osgWidget::Widget::LOWER_LEFT); |
| 125 | widget2->setColor(0.9f, 0.0f, 0.0f, 0.9f, osgWidget::Widget::LOWER_RIGHT); |
| 126 | widget2->setColor(0.0f, 0.0f, 0.9f, 0.9f, osgWidget::Widget::UPPER_RIGHT); |
| 127 | widget2->setColor(0.0f, 0.0f, 0.9f, 0.9f, osgWidget::Widget::UPPER_LEFT); |
| 128 | |
| 129 | // Now add our newly created widgets to our box. |
| 130 | box->addWidget(widget1); |
| 131 | box->addWidget(widget2); |
| 132 | box->addWidget(widget3); |
| 133 | |
| 134 | // For maximum efficiency, Windows don't automatically reallocate their geometry |
| 135 | // and internal positioning every time a widget is added. Thus, we either have to |
| 136 | // call the WindowManger::resizeAllWindows method or manually call |
| 137 | // Window::resize when we're ready. |
| 138 | box->resize(); |
| 139 | |
| 140 | // Now, lets clone our existing box and create a new copy of of it, also adding that |
| 141 | // to the WindowManager. This demonstrates the usages of OSG's ->clone() support, |
| 142 | // though that is abstracted by our META_UIObject macro. |
| 143 | osgWidget::Window* boxCopy = osg::clone(box, "newBox", osg::CopyOp::DEEP_COPY_ALL); |
| 144 | |
| 145 | // Move our copy to make it visible. |
| 146 | boxCopy->setOrigin(0.0f, 125.0f); |
| 147 | |
| 148 | boxCopy->getByName("widget1")->setColor(0.5f, 0.0f, 1.0f, 1.0f); |
| 149 | boxCopy->getByName("widget3")->setColor(0.5f, 0.0f, 1.0f, 1.0f); |
| 150 | |
| 151 | // Add the successfully created Box (if we get this far) into the WindowManager, so |
| 152 | // that they can receive events. |
| 153 | wm->addChild(box); |
| 154 | wm->addChild(boxCopy); |
| 155 | |
| 156 | // Now, ask our new box to be 100% the width of the WindowManager. |
| 157 | boxCopy->resizePercent(100.0f, 0.0f); |
| 158 | |
| 159 | // Here we demonstrate the use of osgWidget/io_utils. This is really only useful for |
| 160 | // debugging at the moment. |
| 161 | // std::cout << *box << std::endl << *boxCopy << std::endl; |
| 162 | |
| 163 | // Setup our OSG objects for our scene; note the use of the utility function |
| 164 | // createOrthoCamera, which is just a helper for setting up a proper viewing area. |
| 165 | // An alternative (and a MUCH easier alternative at that!) is to |
| 166 | // simply use the createParentOrthoCamera method of the WindowManager class, |
| 167 | // which will wrap the calls to createOrthoCamera and addChild for us! Check out |
| 168 | // some of the other examples to see this in action... |
| 169 | osg::Group* group = new osg::Group(); |
| 170 | osg::Camera* camera = osgWidget::createOrthoCamera(1280.0f, 1024.0f); |
| 171 | osg::Node* model = osgDB::readNodeFile("cow.osgt"); |
| 172 | |
| 173 | // Add our event handler; is this better as a MatrixManipulator? Add a few other |
| 174 | // helpful ViewerEventHandlers. |
| 175 | viewer.addEventHandler(new osgWidget::MouseHandler(wm)); |
| 176 | viewer.addEventHandler(new osgWidget::KeyboardHandler(wm)); |
| 177 | viewer.addEventHandler(new osgWidget::ResizeHandler(wm, camera)); |
| 178 | viewer.addEventHandler(new osgWidget::CameraSwitchHandler(wm, camera)); |
| 179 | viewer.addEventHandler(new osgViewer::StatsHandler()); |
| 180 | viewer.addEventHandler(new osgViewer::WindowSizeHandler()); |
| 181 | viewer.addEventHandler(new osgGA::StateSetManipulator( |
| 182 | viewer.getCamera()->getOrCreateStateSet() |
| 183 | )); |
| 184 | |
| 185 | // Set our first non-UI node to be something other than the mask we created our |
| 186 | // WindowManager with to avoid picking. |
| 187 | // TODO: Do I need to create a mechanism for doing this automatically, or should |
| 188 | // that be the responsibility of the users of osgWidget? |
| 189 | model->setNodeMask(MASK_3D); |
| 190 | |
| 191 | // Add the WindowManager instance to the 2D camera. This isn't strictly necessary, |
| 192 | // and you can get some cool results putting the WindowManager directly into a |
| 193 | // 3D scene. This is not necessary if you use WindowManager::createParentOrthoCamera. |
| 194 | camera->addChild(wm); |
| 195 | |
| 196 | // Add our camera and a testing 3D model to the scene. |
| 197 | group->addChild(camera); |
| 198 | group->addChild(model); |
| 199 | |
| 200 | // Here we show how to both run simple strings of code AND run entire files. These |
| 201 | // assume that you're running the osgwidgetwindow example from the build directory, |
| 202 | // otherwise you'll need to adjust the file path below in the call to runFile(). |
| 203 | wm->getLuaEngine()->eval("window = osgwidget.newWindow()"); |
| 204 | wm->getLuaEngine()->runFile("osgWidget/osgwidgetwindow.lua"); |
| 205 | |
| 206 | wm->getPythonEngine()->eval("import osgwidget"); |
| 207 | wm->getPythonEngine()->runFile("osgWidget/osgwidgetwindow.py"); |
| 208 | |
| 209 | viewer.setUpViewInWindow(0, 0, 1280, 1024); |
| 210 | viewer.setSceneData(group); |
| 211 | |
| 212 | /* |
| 213 | osgViewer::Viewer::Cameras cameras; |
| 214 | viewer.getCameras(cameras); |
| 215 | osg::Camera* c = cameras[0]; |
| 216 | osg::Matrix s = osg::Matrix::scale(1.0f, -1.0f, 1.0f); |
| 217 | c->setProjectionMatrix(s * c->getProjectionMatrix()); |
| 218 | */ |
| 219 | |
| 220 | return viewer.run(); |
| 221 | } |
Note: See TracBrowser
for help on using the browser.
