/* -*-c++-*- * Copyright (C) 2010 Jeremy Moles * * 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. */ #include #include #include #include #include #include #include #include #include #include #include class EaseMotionSampler; const unsigned int WINDOW_WIDTH = 800; const unsigned int WINDOW_HEIGHT = 600; const unsigned int MASK_2D = 0xF0000000; const unsigned int MASK_3D = 0x0F000000; const float M_START = 0.0f; const float M_DURATION = 2.0f; const float M_CHANGE = 1.0f; EaseMotionSampler* EASE_MOTION_SAMPLER = 0; osg::Geode* EASE_MOTION_GEODE = 0; osg::Geometry* createEaseMotionGeometry(osgAnimation::Motion* motion) { osg::Geometry* geom = new osg::Geometry(); osg::Vec4Array* cols = new osg::Vec4Array(); osg::Vec3Array* v = new osg::Vec3Array(); for(float i = 0.0f; i < M_DURATION; i += M_DURATION / 256.0f) v->push_back( osg::Vec3(i * 30.0f, motion->getValueAt(i) * 30.0f, 0.0f) ); cols->push_back(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f)); geom->setUseDisplayList(false); geom->setVertexArray(v); geom->setColorArray(cols); geom->setColorBinding(osg::Geometry::BIND_OVERALL); geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP, 0, v->size())); return geom; } class EaseMotionSampler: public osg::NodeCallback { public: float _previous; osg::Vec3 _pos; osg::ref_ptr _motion; EaseMotionSampler(const osg::Vec3& pos): _previous (0.0f), _pos (pos) { } void operator()(osg::Node* node, osg::NodeVisitor* nv) { if(!_motion.valid()) return; osg::MatrixTransform* mt = dynamic_cast(node); if(!mt) return; double t = nv->getFrameStamp()->getSimulationTime(); // This avoids a little glitch when the animation doesn't start right away // when the application is launched. if(_previous == 0.0f) _previous = t; _motion->update(t - _previous); _previous = t; mt->setMatrix(osg::Matrix::translate(_pos * _motion->getValue())); } template void setMotion() { _motion = new T(M_START, M_DURATION, M_CHANGE, osgAnimation::Motion::LOOP); EASE_MOTION_GEODE->removeDrawables(0, EASE_MOTION_GEODE->getNumDrawables()); EASE_MOTION_GEODE->addDrawable(createEaseMotionGeometry(_motion.get())); } }; struct ColorLabel: public osgWidget::Label { ColorLabel(const char* label): osgWidget::Label(label, "") { setFont("fonts/VeraMono.ttf"); setFontSize(14); setFontColor(1.0f, 1.0f, 1.0f, 1.0f); setColor(0.3f, 0.3f, 0.3f, 1.0f); setPadding(2.0f); setCanFill(true); addSize(150.0f, 25.0f); setLabel(label); setEventMask(osgWidget::EVENT_MOUSE_PUSH | osgWidget::EVENT_MASK_MOUSE_MOVE); } bool mousePush(double, double, const osgWidget::WindowManager*) { osgWidget::Table* p = dynamic_cast(_parent); if(!p) return false; p->hide(); const std::string& name = getName(); if(!name.compare("OutQuadMotion")) EASE_MOTION_SAMPLER->setMotion() ; else if(!name.compare("InQuadMotion")) EASE_MOTION_SAMPLER->setMotion() ; else if(!name.compare("InOutQuadMotion")) EASE_MOTION_SAMPLER->setMotion() ; else if(!name.compare("OutCubicMotion")) EASE_MOTION_SAMPLER->setMotion() ; else if(!name.compare("InCubicMotion")) EASE_MOTION_SAMPLER->setMotion() ; else if(!name.compare("InOutCubicMotion")) EASE_MOTION_SAMPLER->setMotion() ; else if(!name.compare("OutQuartMotion")) EASE_MOTION_SAMPLER->setMotion() ; else if(!name.compare("InQuartMotion")) EASE_MOTION_SAMPLER->setMotion() ; else if(!name.compare("InOutQuartMotion")) EASE_MOTION_SAMPLER->setMotion() ; else if(!name.compare("OutBounceMotion")) EASE_MOTION_SAMPLER->setMotion() ; else if(!name.compare("InBounceMotion")) EASE_MOTION_SAMPLER->setMotion() ; else if(!name.compare("InOutBounceMotion")) EASE_MOTION_SAMPLER->setMotion() ; else if(!name.compare("OutElasticMotion")) EASE_MOTION_SAMPLER->setMotion() ; else if(!name.compare("InElasticMotion")) EASE_MOTION_SAMPLER->setMotion() ; else if(!name.compare("InOutElasticMotion")) EASE_MOTION_SAMPLER->setMotion() ; else if(!name.compare("OutSineMotion")) EASE_MOTION_SAMPLER->setMotion() ; else if(!name.compare("InSineMotion")) EASE_MOTION_SAMPLER->setMotion() ; else if(!name.compare("InOutSineMotion")) EASE_MOTION_SAMPLER->setMotion() ; else if(!name.compare("OutBackMotion")) EASE_MOTION_SAMPLER->setMotion() ; else if(!name.compare("InBackMotion")) EASE_MOTION_SAMPLER->setMotion() ; else if(!name.compare("InOutBackMotion")) EASE_MOTION_SAMPLER->setMotion() ; else if(!name.compare("OutCircMotion")) EASE_MOTION_SAMPLER->setMotion() ; else if(!name.compare("InCircMotion")) EASE_MOTION_SAMPLER->setMotion() ; else if(!name.compare("InOutCircMotion")) EASE_MOTION_SAMPLER->setMotion() ; else if(!name.compare("OutExpoMotion")) EASE_MOTION_SAMPLER->setMotion() ; else if(!name.compare("InExpoMotion")) EASE_MOTION_SAMPLER->setMotion() ; else if(!name.compare("InOutExpoMotion")) EASE_MOTION_SAMPLER->setMotion() ; else EASE_MOTION_SAMPLER->setMotion(); return true; } bool mouseEnter(double, double, const osgWidget::WindowManager*) { setColor(0.9f, 0.6f, 0.1f, 1.0f); return true; } bool mouseLeave(double, double, const osgWidget::WindowManager*) { setColor(0.3f, 0.3f, 0.3f, 1.0f); return true; } }; class ColorLabelMenu: public ColorLabel { osg::ref_ptr _window; public: ColorLabelMenu(const char* label): ColorLabel(label) { _window = new osgWidget::Table(std::string("Menu_") + label, 6, 5); _window->addWidget(new ColorLabel("OutQuadMotion"), 0, 0); _window->addWidget(new ColorLabel("InQuadMotion"), 1, 0); _window->addWidget(new ColorLabel("InOutQuadMotion"), 2, 0); _window->addWidget(new ColorLabel("OutCubicMotion"), 3, 0); _window->addWidget(new ColorLabel("InCubicMotion"), 4, 0); _window->addWidget(new ColorLabel("InOutCubicMotion"), 5, 0); _window->addWidget(new ColorLabel("OutQuartMotion"), 0, 1); _window->addWidget(new ColorLabel("InQuartMotion"), 1, 1); _window->addWidget(new ColorLabel("InOutQuartMotion"), 2, 1); _window->addWidget(new ColorLabel("OutBounceMotion"), 3, 1); _window->addWidget(new ColorLabel("InBounceMotion"), 4, 1); _window->addWidget(new ColorLabel("InOutBounceMotion"), 5, 1); _window->addWidget(new ColorLabel("OutElasticMotion"), 0, 2); _window->addWidget(new ColorLabel("InElasticMotion"), 1, 2); _window->addWidget(new ColorLabel("InOutElasticMotion"), 2, 2); _window->addWidget(new ColorLabel("OutSineMotion"), 3, 2); _window->addWidget(new ColorLabel("InSineMotion"), 4, 2); _window->addWidget(new ColorLabel("InOutSineMotion"), 5, 2); _window->addWidget(new ColorLabel("OutBackMotion"), 0, 3); _window->addWidget(new ColorLabel("InBackMotion"), 1, 3); _window->addWidget(new ColorLabel("InOutBackMotion"), 2, 3); _window->addWidget(new ColorLabel("OutCircMotion"), 3, 3); _window->addWidget(new ColorLabel("InCircMotion"), 4, 3); _window->addWidget(new ColorLabel("InOutCircMotion"), 5, 3); _window->addWidget(new ColorLabel("OutExpoMotion"), 0, 4); _window->addWidget(new ColorLabel("InExpoMotion"), 1, 4); _window->addWidget(new ColorLabel("InOutExpoMotion"), 2, 4); _window->addWidget(new ColorLabel("Linear"), 3, 4); _window->resize(); } void managed(osgWidget::WindowManager* wm) { osgWidget::Label::managed(wm); wm->addChild(_window.get()); _window->hide(); } void positioned() { osgWidget::Label::positioned(); _window->setOrigin(_parent->getX(), _parent->getY() + _parent->getHeight()); } bool mousePush(double, double, const osgWidget::WindowManager*) { if(!_window->isVisible()) _window->show(); else _window->hide(); return true; } }; int main(int argc, char** argv) { osgViewer::Viewer viewer; osgWidget::WindowManager* wm = new osgWidget::WindowManager( &viewer, WINDOW_WIDTH, WINDOW_HEIGHT, MASK_2D ); osgWidget::Window* menu = new osgWidget::Box("menu", osgWidget::Box::HORIZONTAL); menu->addWidget(new ColorLabelMenu("Choose EaseMotion")); menu->getBackground()->setColor(1.0f, 1.0f, 1.0f, 1.0f); menu->setPosition(15.0f, 15.0f, 0.0f); wm->addChild(menu); osg::Group* group = new osg::Group(); osg::Geode* geode = new osg::Geode(); osg::MatrixTransform* mt = new osg::MatrixTransform(); geode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(), 4.0f))); EASE_MOTION_SAMPLER = new EaseMotionSampler(osg::Vec3(50.0f, 0.0f, 0.0f)); EASE_MOTION_GEODE = new osg::Geode(); mt->addChild(geode); mt->setUpdateCallback(EASE_MOTION_SAMPLER); mt->setNodeMask(MASK_3D); viewer.setCameraManipulator(new osgGA::TrackballManipulator()); viewer.getCameraManipulator()->setHomePosition( osg::Vec3d(0.0f, 0.0f, 200.0f), osg::Vec3d(20.0f, 0.0f, 0.0f), osg::Vec3d(0.0f, 1.0f, 0.0f) ); viewer.home(); group->addChild(mt); group->addChild(EASE_MOTION_GEODE); return osgWidget::createExample(viewer, wm, group); }