408 lines
11 KiB
C++
408 lines
11 KiB
C++
|
/* -*-c++-*-
|
||
|
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
|
||
|
*
|
||
|
* 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.
|
||
|
*
|
||
|
* Authors:
|
||
|
* Cedric Pinson <mornifle@plopbyte.net>
|
||
|
* jeremy Moles <jeremy@emperorlinux.com>
|
||
|
*/
|
||
|
|
||
|
#include "AnimtkViewer"
|
||
|
#include "AnimtkViewerGUI"
|
||
|
|
||
|
#include <osg/Version>
|
||
|
#include <osgWidget/WindowManager>
|
||
|
#include <osgAnimation/EaseMotion>
|
||
|
|
||
|
const std::string IMAGE_PATH = "osgAnimation/Images/";
|
||
|
|
||
|
template <class T>
|
||
|
struct Sampler: public osg::Drawable::UpdateCallback
|
||
|
{
|
||
|
T _motion;
|
||
|
Sampler() {
|
||
|
}
|
||
|
};
|
||
|
|
||
|
typedef Sampler<osgAnimation::OutQuadMotion> WidgetSampler;
|
||
|
|
||
|
struct ButtonFunctor: public WidgetSampler
|
||
|
{
|
||
|
float _direction;
|
||
|
float _previous;
|
||
|
|
||
|
const float _speed;
|
||
|
|
||
|
ButtonFunctor(): _speed(5) { _direction = -_speed; _previous = 0;}
|
||
|
|
||
|
bool enter(osgWidget::Event& ev)
|
||
|
{
|
||
|
_direction = _speed;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool leave(osgWidget::Event& ev)
|
||
|
{
|
||
|
_direction = -_speed;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void update(osg::NodeVisitor* nv , osg::Drawable* geom)
|
||
|
{
|
||
|
const osg::FrameStamp* f = nv->getFrameStamp();
|
||
|
float dt = f->getSimulationTime() - _previous;
|
||
|
_previous = f->getSimulationTime();
|
||
|
update(dt,dynamic_cast<osgWidget::Widget*>(geom));
|
||
|
}
|
||
|
|
||
|
void update(float t, osgWidget::Widget* w)
|
||
|
{
|
||
|
if (!w) return;
|
||
|
_motion.update(t*_direction);
|
||
|
float val = _motion.getValue()*0.5;
|
||
|
val += 0.5;
|
||
|
if (val >= 1.0)
|
||
|
val = 1.0;
|
||
|
w->setColor(osg::Vec4(val, val, val, 1));
|
||
|
}
|
||
|
};
|
||
|
|
||
|
struct LabelFunctor: public WidgetSampler
|
||
|
{
|
||
|
float _previous;
|
||
|
bool _active;
|
||
|
|
||
|
const float _fadeOutTime;
|
||
|
|
||
|
osgAnimation::OutCubicMotion _scaleSampler;
|
||
|
|
||
|
LabelFunctor():
|
||
|
_fadeOutTime(1.5f)
|
||
|
{
|
||
|
_previous = 0.0f;
|
||
|
_active = false;
|
||
|
|
||
|
_scaleSampler = osgAnimation::OutCubicMotion(0.5, 1.0, 1.0);
|
||
|
}
|
||
|
|
||
|
void setActive(bool active)
|
||
|
{
|
||
|
_active = active;
|
||
|
|
||
|
if(active) _motion.reset();
|
||
|
|
||
|
_scaleSampler.reset();
|
||
|
}
|
||
|
|
||
|
void update(osg::NodeVisitor* nv , osg::Drawable* geom)
|
||
|
{
|
||
|
const osg::FrameStamp* f = nv->getFrameStamp();
|
||
|
|
||
|
float st = f->getSimulationTime();
|
||
|
float dt = st - _previous;
|
||
|
|
||
|
_previous = st;
|
||
|
|
||
|
if(!_active) return;
|
||
|
|
||
|
update(dt, dynamic_cast<osgWidget::Label*>(geom));
|
||
|
updateScale(dt, dynamic_cast<osgWidget::Label*>(geom));
|
||
|
}
|
||
|
|
||
|
void update(float t, osgWidget::Label* w)
|
||
|
{
|
||
|
if(!w) return;
|
||
|
|
||
|
_motion.update(t / _fadeOutTime);
|
||
|
|
||
|
float val = _motion.getValue();
|
||
|
|
||
|
if(val >= 1.0f) {
|
||
|
_motion.reset();
|
||
|
_active = false;
|
||
|
}
|
||
|
|
||
|
w->setFontColor(osg::Vec4(0.0f, 0.0f, 0.0f, (1.0f - val) * 0.7f));
|
||
|
}
|
||
|
|
||
|
void updateScale(float t, osgWidget::Label* w)
|
||
|
{
|
||
|
_scaleSampler.update(t);
|
||
|
float val = _scaleSampler.getValue();
|
||
|
osgWidget::Window* win = w->getParent();
|
||
|
win->setScale(val);
|
||
|
win->update();
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
|
||
|
struct ListFunctor: public osg::NodeCallback
|
||
|
{
|
||
|
float _previous;
|
||
|
int _direction;
|
||
|
|
||
|
osgAnimation::InQuadMotion _transformSampler;
|
||
|
|
||
|
ListFunctor()
|
||
|
{
|
||
|
_direction = 1;
|
||
|
_previous = 0;
|
||
|
|
||
|
_transformSampler.update(1.0f);
|
||
|
}
|
||
|
|
||
|
void toggleShown()
|
||
|
{
|
||
|
if(_direction == 1) _direction = -1;
|
||
|
|
||
|
else _direction = 1;
|
||
|
}
|
||
|
|
||
|
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
|
||
|
{
|
||
|
const osg::FrameStamp* f = nv->getFrameStamp();
|
||
|
|
||
|
float st = f->getSimulationTime();
|
||
|
float dt = st - _previous;
|
||
|
|
||
|
_previous = st;
|
||
|
|
||
|
_transformSampler.update((dt * _direction) / 0.5f);
|
||
|
|
||
|
float val = _transformSampler.getValue();
|
||
|
|
||
|
if(val > 1.0f || val < 0.0f) return;
|
||
|
|
||
|
osgWidget::Window* win = dynamic_cast<osgWidget::Window*>(node);
|
||
|
|
||
|
float w = win->getWidth();
|
||
|
float wmw = win->getWindowManager()->getWidth();
|
||
|
|
||
|
win->setX((wmw - w) + (val * w));
|
||
|
win->update();
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
// This is a temporary hack to "prevent" dragging on Widgets and Windows.
|
||
|
bool eatDrag(osgWidget::Event&)
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
AnimtkViewerGUI::AnimtkViewerGUI(osgViewer::View* view, float w, float h, unsigned int mask):
|
||
|
osgWidget::WindowManager(view, w, h, mask, 0)
|
||
|
{
|
||
|
_createButtonBox();
|
||
|
_createLabelBox();
|
||
|
_createListBox();
|
||
|
|
||
|
_labelBox->setAnchorHorizontal(osgWidget::Window::HA_LEFT);
|
||
|
_labelBox->setY(74.0f);
|
||
|
_labelBox->setVisibilityMode(osgWidget::Window::VM_ENTIRE);
|
||
|
|
||
|
_listBox->setOrigin(getWidth(), 74.0f);
|
||
|
|
||
|
addChild(_buttonBox.get());
|
||
|
addChild(_labelBox.get());
|
||
|
addChild(_listBox.get());
|
||
|
|
||
|
resizeAllWindows();
|
||
|
|
||
|
// Remember, you can't call resizePercent until AFTER the box is parented
|
||
|
// by a WindowManager; how could it possibly resize itself if it doesn't know
|
||
|
// how large it's viewable area is?
|
||
|
_buttonBox->resizePercent(100.0f);
|
||
|
_buttonBox->resizeAdd(0.0f, 10.0f);
|
||
|
}
|
||
|
|
||
|
osgWidget::Widget* AnimtkViewerGUI::_createButton(const std::string& name)
|
||
|
{
|
||
|
osgWidget::Widget* b = new osgWidget::Widget(name, 64.0f, 64.0f);
|
||
|
|
||
|
if(!b) return 0;
|
||
|
|
||
|
b->setImage(IMAGE_PATH + name + ".png", true);
|
||
|
b->setEventMask(osgWidget::EVENT_MASK_MOUSE_DRAG);
|
||
|
|
||
|
ButtonFunctor* bt = new ButtonFunctor();
|
||
|
b->setUpdateCallback(bt);
|
||
|
|
||
|
b->addCallback(new osgWidget::Callback(&ButtonFunctor::enter, bt, osgWidget::EVENT_MOUSE_ENTER));
|
||
|
b->addCallback(new osgWidget::Callback(&ButtonFunctor::leave, bt, osgWidget::EVENT_MOUSE_LEAVE));
|
||
|
b->addCallback(new osgWidget::Callback(&AnimtkViewerGUI::_buttonPush, this, osgWidget::EVENT_MOUSE_PUSH));
|
||
|
b->addCallback(new osgWidget::Callback(&eatDrag, osgWidget::EVENT_MOUSE_DRAG));
|
||
|
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
bool AnimtkViewerGUI::_listMouseHover(osgWidget::Event& ev)
|
||
|
{
|
||
|
osgWidget::Label* l = dynamic_cast<osgWidget::Label*>(ev.getWidget());
|
||
|
|
||
|
if(!l) return false;
|
||
|
|
||
|
if(ev.type == osgWidget::EVENT_MOUSE_ENTER) l->setFontColor(1.0f, 1.0f, 1.0f, 1.0f);
|
||
|
|
||
|
else if(ev.type == osgWidget::EVENT_MOUSE_LEAVE) l->setFontColor(1.0f, 1.0f, 1.0f, 0.3f);
|
||
|
|
||
|
else if(ev.type == osgWidget::EVENT_MOUSE_PUSH) {
|
||
|
AnimtkViewerModelController::instance().playByName(ev.getWidget()->getName());
|
||
|
}
|
||
|
|
||
|
else return false;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool AnimtkViewerGUI::_buttonPush(osgWidget::Event& ev)
|
||
|
{
|
||
|
if(!ev.getWidget()) return false;
|
||
|
|
||
|
osgWidget::Label* l = static_cast<osgWidget::Label*>(_labelBox->getByName("label"));
|
||
|
|
||
|
if(!l) return false;
|
||
|
|
||
|
LabelFunctor* lf = dynamic_cast<LabelFunctor*>(l->getUpdateCallback());
|
||
|
|
||
|
if(!lf) return false;
|
||
|
|
||
|
// We're safe at this point, so begin processing.
|
||
|
AnimtkViewerModelController& mc = AnimtkViewerModelController::instance();
|
||
|
std::string name = ev.getWidget()->getName();
|
||
|
|
||
|
if(name == "play") mc.play();
|
||
|
|
||
|
else if(name == "stop") mc.stop();
|
||
|
|
||
|
else if(name == "next")
|
||
|
{
|
||
|
mc.next();
|
||
|
|
||
|
l->setFontColor(osg::Vec4(0.0f, 0.0f, 0.0f, 0.7f));
|
||
|
l->setLabel(mc.getCurrentAnimationName());
|
||
|
lf->setActive(true);
|
||
|
}
|
||
|
|
||
|
else if(name == "back")
|
||
|
{
|
||
|
mc.previous();
|
||
|
|
||
|
l->setFontColor(osg::Vec4(0.0f, 0.0f, 0.0f, 0.7f));
|
||
|
l->setLabel(mc.getCurrentAnimationName());
|
||
|
lf->setActive(true);
|
||
|
}
|
||
|
|
||
|
else if(name == "pause")
|
||
|
{
|
||
|
}
|
||
|
|
||
|
else if(name == "open")
|
||
|
{
|
||
|
ListFunctor* lsf = dynamic_cast<ListFunctor*>(_listBox->getUpdateCallback());
|
||
|
|
||
|
if(!lsf) return false;
|
||
|
|
||
|
lsf->toggleShown();
|
||
|
}
|
||
|
|
||
|
else return false;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void AnimtkViewerGUI::_createButtonBox()
|
||
|
{
|
||
|
_buttonBox = new osgWidget::Box("buttonBox", osgWidget::Box::HORIZONTAL);
|
||
|
|
||
|
osgWidget::Widget* space = new osgWidget::Widget("nullSpace", 0.0f, 0.0f);
|
||
|
osgWidget::Widget* back = _createButton("back");
|
||
|
osgWidget::Widget* next = _createButton("next");
|
||
|
osgWidget::Widget* play = _createButton("play");
|
||
|
osgWidget::Widget* pause = _createButton("pause");
|
||
|
osgWidget::Widget* stop = _createButton("stop");
|
||
|
osgWidget::Widget* open = _createButton("open");
|
||
|
|
||
|
space->setCanFill(true);
|
||
|
space->setColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||
|
|
||
|
_buttonBox->addWidget(space);
|
||
|
_buttonBox->addWidget(back);
|
||
|
_buttonBox->addWidget(next);
|
||
|
_buttonBox->addWidget(play);
|
||
|
_buttonBox->addWidget(pause);
|
||
|
_buttonBox->addWidget(stop);
|
||
|
_buttonBox->addWidget(open);
|
||
|
_buttonBox->addWidget(osg::clone(space, "space1", osg::CopyOp::DEEP_COPY_ALL));
|
||
|
_buttonBox->getBackground()->setColor(0.0f, 0.0f, 0.0f, 0.7f);
|
||
|
|
||
|
_buttonBox->setEventMask(osgWidget::EVENT_MASK_MOUSE_DRAG);
|
||
|
_buttonBox->addCallback(new osgWidget::Callback(&eatDrag, osgWidget::EVENT_MOUSE_DRAG));
|
||
|
}
|
||
|
|
||
|
void AnimtkViewerGUI::_createListBox()
|
||
|
{
|
||
|
_listBox = new osgWidget::Box("listBox", osgWidget::Box::VERTICAL);
|
||
|
|
||
|
const AnimtkViewerModelController::AnimationMapVector& amv =
|
||
|
AnimtkViewerModelController::instance().getAnimationMap()
|
||
|
;
|
||
|
|
||
|
for(
|
||
|
AnimtkViewerModelController::AnimationMapVector::const_iterator i = amv.begin();
|
||
|
i != amv.end();
|
||
|
i++
|
||
|
)
|
||
|
{
|
||
|
osgWidget::Label* label = new osgWidget::Label(*i);
|
||
|
|
||
|
label->setCanFill(true);
|
||
|
label->setFont("fonts/Vera.ttf");
|
||
|
label->setFontSize(15);
|
||
|
label->setFontColor(1.0f, 1.0f, 1.0f, 0.3f);
|
||
|
label->setPadding(5.0f);
|
||
|
label->setAlignHorizontal(osgWidget::Widget::HA_RIGHT);
|
||
|
label->setLabel(*i);
|
||
|
label->setEventMask(osgWidget::EVENT_MASK_MOUSE_DRAG);
|
||
|
label->addCallback(new osgWidget::Callback(&AnimtkViewerGUI::_listMouseHover, this, osgWidget::EVENT_MOUSE_ENTER));
|
||
|
label->addCallback(new osgWidget::Callback(&AnimtkViewerGUI::_listMouseHover, this, osgWidget::EVENT_MOUSE_LEAVE));
|
||
|
label->addCallback(new osgWidget::Callback(&AnimtkViewerGUI::_listMouseHover, this, osgWidget::EVENT_MOUSE_PUSH));
|
||
|
|
||
|
_listBox->addWidget(label);
|
||
|
}
|
||
|
|
||
|
ListFunctor* lf = new ListFunctor();
|
||
|
|
||
|
_listBox->setUpdateCallback(lf);
|
||
|
_listBox->getBackground()->setColor(0.0f, 0.0f, 0.0f, 0.7f);
|
||
|
}
|
||
|
|
||
|
void AnimtkViewerGUI::_createLabelBox()
|
||
|
{
|
||
|
_labelBox = new osgWidget::Box("labelBox", osgWidget::Box::VERTICAL);
|
||
|
|
||
|
osgWidget::Label* label = new osgWidget::Label("label");
|
||
|
|
||
|
label->setFont("fonts/Vera.ttf");
|
||
|
label->setFontSize(50);
|
||
|
label->setFontColor(0.0f, 0.0f, 0.0f, 0.7f);
|
||
|
label->setAlignHorizontal(osgWidget::Widget::HA_LEFT);
|
||
|
label->setPadding(10.0f);
|
||
|
|
||
|
LabelFunctor* lf = new LabelFunctor();
|
||
|
label->setUpdateCallback(lf);
|
||
|
|
||
|
_labelBox->addWidget(label);
|
||
|
_labelBox->getBackground()->setColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||
|
}
|