From Cedric Pinson, split timeline classes in differents files, cleanup and add a statshandler to visualize current action in timeline
This commit is contained in:
208
include/osgAnimation/Action
Normal file
208
include/osgAnimation/Action
Normal file
@@ -0,0 +1,208 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_ACTION_H
|
||||
#define OSGANIMATION_ACTION_H
|
||||
|
||||
#include <osgAnimation/Export>
|
||||
#include <osgAnimation/Animation>
|
||||
#include <osgAnimation/ActionVisitor>
|
||||
#include <osgAnimation/FrameAction>
|
||||
#include <iostream>
|
||||
|
||||
#define META_Action(library,name) \
|
||||
virtual osg::Object* cloneType() const { return new name (); } \
|
||||
virtual osg::Object* clone(const osg::CopyOp& copyop) const { return new name (*this,copyop); } \
|
||||
virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const name *>(obj)!=NULL; } \
|
||||
virtual const char* className() const { return #name; } \
|
||||
virtual const char* libraryName() const { return #library; } \
|
||||
virtual void accept(osgAnimation::ActionVisitor& nv) { nv.apply(*this); } \
|
||||
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
class OSGANIMATION_EXPORT Action : public osg::Object
|
||||
{
|
||||
public:
|
||||
|
||||
class Callback : public osg::Object
|
||||
{
|
||||
public:
|
||||
Callback(){}
|
||||
Callback(const Callback& nc,const osg::CopyOp&) :
|
||||
_nestedCallback(nc._nestedCallback) {}
|
||||
|
||||
META_Object(osgAnimation,Callback);
|
||||
|
||||
virtual void operator()(Action* action, osgAnimation::ActionVisitor* nv) {}
|
||||
|
||||
Callback* getNestedCallback() { return _nestedCallback.get(); }
|
||||
void addNestedCallback(Callback* callback)
|
||||
{
|
||||
if (_nestedCallback.valid())
|
||||
_nestedCallback->addNestedCallback(callback);
|
||||
else
|
||||
_nestedCallback = callback;
|
||||
}
|
||||
|
||||
protected:
|
||||
osg::ref_ptr<Callback> _nestedCallback;
|
||||
};
|
||||
|
||||
|
||||
typedef std::map<unsigned int, osg::ref_ptr<Callback> > FrameCallback;
|
||||
|
||||
META_Action(osgAnimation, Action);
|
||||
|
||||
Action();
|
||||
Action(const Action&,const osg::CopyOp&);
|
||||
|
||||
void setCallback(double when, Callback* callback)
|
||||
{
|
||||
setCallback(static_cast<unsigned int>(floor(when*_fps)), callback);
|
||||
}
|
||||
|
||||
void setCallback(unsigned int frame, Callback* callback)
|
||||
{
|
||||
if (_framesCallback[frame].valid())
|
||||
_framesCallback[frame]->addNestedCallback(callback);
|
||||
else
|
||||
_framesCallback[frame] = callback;
|
||||
}
|
||||
Callback* getCallback(unsigned int frame)
|
||||
{
|
||||
if (_framesCallback.find(frame) == _framesCallback.end())
|
||||
return 0;
|
||||
return _framesCallback[frame].get();
|
||||
}
|
||||
|
||||
Callback* getFrameCallback(unsigned int frame);
|
||||
Callback* getFrameCallback(double time);
|
||||
unsigned int getFramesPerSecond() const { return _fps; }
|
||||
|
||||
void setNumFrames(unsigned int numFrames) { _numberFrame = numFrames;}
|
||||
void setDuration(double duration) { _numberFrame = static_cast<unsigned int>(floor(duration * _fps)); }
|
||||
unsigned int getNumFrames() const { return _numberFrame;}
|
||||
double getDuration() const { return _numberFrame * 1.0 / _fps; }
|
||||
|
||||
// 0 means infini else it's the number of loop
|
||||
virtual void setLoop(int nb) { _loop = nb; }
|
||||
virtual unsigned int getLoop() const { return _loop;}
|
||||
|
||||
// get the number of loop, the frame relative to loop.
|
||||
// return true if in range, and false if out of range.
|
||||
bool evaluateFrame(unsigned int frame, unsigned int& resultframe, unsigned int& nbloop );
|
||||
virtual void traverse(ActionVisitor& visitor) {}
|
||||
//virtual void evaluate(unsigned int frame);
|
||||
|
||||
protected:
|
||||
FrameCallback _framesCallback;
|
||||
|
||||
double _speed;
|
||||
unsigned int _fps;
|
||||
unsigned int _numberFrame;
|
||||
unsigned int _loop;
|
||||
|
||||
enum Status
|
||||
{
|
||||
Play,
|
||||
Stop
|
||||
};
|
||||
|
||||
Status _state;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// blend in from 0 to weight in duration
|
||||
class BlendIn : public Action
|
||||
{
|
||||
double _weight;
|
||||
osg::ref_ptr<Animation> _animation;
|
||||
|
||||
public:
|
||||
META_Action(osgAnimation, BlendIn);
|
||||
BlendIn() : _weight(0) {}
|
||||
BlendIn(const BlendIn& a, const osg::CopyOp& c) : Action(a,c) { _weight = a._weight; _animation = a._animation;}
|
||||
BlendIn(Animation* animation, double duration, double weight);
|
||||
double getWeight() const { return _weight;}
|
||||
Animation* getAnimation() { return _animation.get(); }
|
||||
void computeWeight(unsigned int frame);
|
||||
};
|
||||
|
||||
// blend in from 0 to weight in duration
|
||||
class BlendOut : public Action
|
||||
{
|
||||
double _weight;
|
||||
osg::ref_ptr<Animation> _animation;
|
||||
public:
|
||||
META_Action(osgAnimation, BlendOut);
|
||||
BlendOut() : _weight(0) {}
|
||||
BlendOut(const BlendOut& a, const osg::CopyOp& c) : Action(a,c) { _weight = a._weight; _animation = a._animation;}
|
||||
BlendOut(Animation* animation, double duration);
|
||||
Animation* getAnimation() { return _animation.get(); }
|
||||
double getWeight() const { return _weight;}
|
||||
void computeWeight(unsigned int frame);
|
||||
};
|
||||
|
||||
|
||||
class ActionAnimation : public Action
|
||||
{
|
||||
public:
|
||||
META_Action(osgAnimation, ActionAnimation);
|
||||
ActionAnimation() {}
|
||||
ActionAnimation(const ActionAnimation& a, const osg::CopyOp& c) : Action(a,c) { _animation = a._animation;}
|
||||
ActionAnimation(Animation* animation);
|
||||
void updateAnimation(unsigned int frame);
|
||||
Animation* getAnimation() { return _animation.get(); }
|
||||
|
||||
protected:
|
||||
osg::ref_ptr<Animation> _animation;
|
||||
};
|
||||
|
||||
|
||||
// encapsulate animation with blend in blend out for classic usage
|
||||
class StripAnimation : public Action
|
||||
{
|
||||
public:
|
||||
META_Action(osgAnimation, StripAnimation);
|
||||
StripAnimation() {}
|
||||
StripAnimation(const StripAnimation& a, const osg::CopyOp& c);
|
||||
StripAnimation(Animation* animation, double blendInDuration = 0.0, double blendOutDuration = 0.0, double blendInWeightTarget = 1.0 );
|
||||
ActionAnimation* getActionAnimation() { return _animation.get(); }
|
||||
BlendIn* getBlendIn() { return _blendIn.get(); }
|
||||
BlendOut* getBlendOut() { return _blendOut.second.get(); }
|
||||
const ActionAnimation* getActionAnimation() const { return _animation.get(); }
|
||||
const BlendIn* getBlendIn() const { return _blendIn.get(); }
|
||||
const BlendOut* getBlendOut() const { return _blendOut.second.get(); }
|
||||
unsigned int getBlendOutStartFrame() const { return _blendOut.first; }
|
||||
|
||||
unsigned int getLoop() const { return _animation->getLoop(); }
|
||||
void setLoop(unsigned int loop);
|
||||
void computeWeightAndUpdateAnimation(unsigned int frame);
|
||||
|
||||
protected:
|
||||
typedef std::pair<unsigned int, osg::ref_ptr<BlendOut> > FrameBlendOut;
|
||||
osg::ref_ptr<BlendIn> _blendIn;
|
||||
FrameBlendOut _blendOut;
|
||||
osg::ref_ptr<ActionAnimation> _animation;
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
37
include/osgAnimation/ActionCallback
Normal file
37
include/osgAnimation/ActionCallback
Normal file
@@ -0,0 +1,37 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_ACTION_CALLBACK_H
|
||||
#define OSGANIMATION_ACTION_CALLBACK_H
|
||||
|
||||
#include <osgAnimation/Action>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
/** Callback used to run new action on the timeline.*/
|
||||
class RunAction : public Action::Callback
|
||||
{
|
||||
public:
|
||||
RunAction(Action* a) : _action(a) {}
|
||||
virtual void operator()(Action* action, ActionVisitor* visitor);
|
||||
|
||||
protected:
|
||||
osg::ref_ptr<Action> _action;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
110
include/osgAnimation/ActionVisitor
Normal file
110
include/osgAnimation/ActionVisitor
Normal file
@@ -0,0 +1,110 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_ACTIONVISITOR_H
|
||||
#define OSGANIMATION_ACTIONVISITOR_H
|
||||
|
||||
#include <vector>
|
||||
#include <osgAnimation/Export>
|
||||
#include <osg/Referenced>
|
||||
#include <osgAnimation/FrameAction>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
class Timeline;
|
||||
class Action;
|
||||
class BlendIn;
|
||||
class BlendOut;
|
||||
class ActionAnimation;
|
||||
class StripAnimation;
|
||||
|
||||
#define META_ActionVisitor(library,name) \
|
||||
virtual const char* libraryName() const { return #library; }\
|
||||
virtual const char* className() const { return #name; }
|
||||
|
||||
|
||||
class OSGANIMATION_EXPORT ActionVisitor : public osg::Referenced
|
||||
{
|
||||
public:
|
||||
std::vector<FrameAction> _stackFrameAction;
|
||||
std::vector<osg::ref_ptr<Timeline> > _stackTimeline;
|
||||
|
||||
META_ActionVisitor(osgAnimation, ActionVisitor);
|
||||
void traverse(Action& visitor);
|
||||
|
||||
void pushFrameActionOnStack(FrameAction& fa);
|
||||
void popFrameAction();
|
||||
|
||||
void pushTimelineOnStack(Timeline* tm);
|
||||
void popTimeline();
|
||||
|
||||
Timeline* getCurrentTimeline();
|
||||
|
||||
virtual void apply(Action& action);
|
||||
virtual void apply(Timeline& tm);
|
||||
virtual void apply(BlendIn& action);
|
||||
virtual void apply(BlendOut& action);
|
||||
virtual void apply(ActionAnimation& action);
|
||||
virtual void apply(StripAnimation& action);
|
||||
};
|
||||
|
||||
|
||||
class OSGANIMATION_EXPORT UpdateActionVisitor : public osgAnimation::ActionVisitor
|
||||
{
|
||||
protected:
|
||||
unsigned int _frame;
|
||||
|
||||
public:
|
||||
META_ActionVisitor(osgAnimation, UpdateActionVisitor);
|
||||
UpdateActionVisitor();
|
||||
void setFrame(unsigned int frame) { _frame = frame;}
|
||||
|
||||
bool isActive() const;
|
||||
unsigned int getLocalFrame() const;
|
||||
|
||||
void apply(Timeline& action);
|
||||
void apply(Action& action);
|
||||
void apply(BlendIn& action);
|
||||
void apply(BlendOut& action);
|
||||
void apply(ActionAnimation& action);
|
||||
void apply(StripAnimation& action);
|
||||
|
||||
};
|
||||
|
||||
|
||||
class OSGANIMATION_EXPORT ClearActionVisitor : public osgAnimation::ActionVisitor
|
||||
{
|
||||
public:
|
||||
enum ClearType {
|
||||
BEFORE_FRAME,
|
||||
AFTER_FRAME
|
||||
};
|
||||
|
||||
META_ActionVisitor(osgAnimation, ClearActionVisitor);
|
||||
ClearActionVisitor(ClearType type = BEFORE_FRAME);
|
||||
void setFrame(unsigned int frame) { _frame = frame;}
|
||||
|
||||
void apply(Timeline& action);
|
||||
void apply(Action& action);
|
||||
|
||||
protected:
|
||||
unsigned int _frame;
|
||||
std::vector<osg::ref_ptr<Action> > _remove;
|
||||
ClearType _clearType;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
|
||||
* Copyright (C) 2008 Cedric Pinson <cedric.pinson@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
|
||||
@@ -110,7 +110,7 @@ namespace osgAnimation
|
||||
_scale = new osgAnimation::Vec3Target;
|
||||
}
|
||||
|
||||
void update(osgAnimation::Bone& bone)
|
||||
void update(osgAnimation::Bone& bone)
|
||||
{
|
||||
bone.setTranslation(_position->getValue());
|
||||
bone.setRotation(_quaternion->getValue());
|
||||
@@ -126,25 +126,25 @@ namespace osgAnimation
|
||||
|
||||
bool link(osgAnimation::Channel* channel)
|
||||
{
|
||||
if (channel->getName().find("quaternion") != std::string::npos)
|
||||
if (channel->getName().find("quaternion") != std::string::npos)
|
||||
{
|
||||
osgAnimation::QuatSphericalLinearChannel* qc = dynamic_cast<osgAnimation::QuatSphericalLinearChannel*>(channel);
|
||||
if (qc)
|
||||
if (qc)
|
||||
{
|
||||
qc->setTarget(_quaternion.get());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (channel->getName().find("position") != std::string::npos)
|
||||
else if (channel->getName().find("position") != std::string::npos)
|
||||
{
|
||||
osgAnimation::Vec3LinearChannel* vc = dynamic_cast<osgAnimation::Vec3LinearChannel*>(channel);
|
||||
if (vc)
|
||||
if (vc)
|
||||
{
|
||||
vc->setTarget(_position.get());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (channel->getName().find("scale") != std::string::npos)
|
||||
}
|
||||
else if (channel->getName().find("scale") != std::string::npos)
|
||||
{
|
||||
osgAnimation::Vec3LinearChannel* vc = dynamic_cast<osgAnimation::Vec3LinearChannel*>(channel);
|
||||
if (vc)
|
||||
@@ -152,7 +152,7 @@ namespace osgAnimation
|
||||
vc->setTarget(_scale.get());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Channel " << channel->getName() << " does not contain a valid symbolic name for this class" << std::endl;
|
||||
|
||||
26
include/osgAnimation/FrameAction
Normal file
26
include/osgAnimation/FrameAction
Normal file
@@ -0,0 +1,26 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_FRAMEACTION_H
|
||||
#define OSGANIMATION_FRAMEACTION_H
|
||||
|
||||
#include <map>
|
||||
#include <osg/ref_ptr>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
class Action;
|
||||
typedef std::pair<unsigned int, osg::ref_ptr<Action> > FrameAction;
|
||||
}
|
||||
#endif
|
||||
@@ -89,7 +89,7 @@ namespace osgAnimation
|
||||
RigGeometry* geom = dynamic_cast<RigGeometry*>(drw);
|
||||
if (!geom)
|
||||
return;
|
||||
if (!geom->getSkeleton() && !geom->getParents().empty())
|
||||
if (!geom->getSkeleton() && !geom->getParents().empty())
|
||||
{
|
||||
FindNearestParentSkeleton finder;
|
||||
if (geom->getParents().size() > 1)
|
||||
|
||||
115
include/osgAnimation/StatsHandler
Normal file
115
include/osgAnimation/StatsHandler
Normal file
@@ -0,0 +1,115 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 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.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_STATSHANDLER_H
|
||||
#define OSGANIMATION_STATSHANDLER_H
|
||||
|
||||
#include <osgAnimation/Timeline>
|
||||
#include <osgGA/GUIEventHandler>
|
||||
#include <osgViewer/ViewerBase>
|
||||
#include <osgViewer/Viewer>
|
||||
#include <osgText/Text>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
#if 0
|
||||
struct StatAction
|
||||
{
|
||||
|
||||
std::string _name;
|
||||
osg::ref_ptr<osg::Group> _group;
|
||||
osg::ref_ptr<osg::Geode> _label;
|
||||
osg::ref_ptr<osg::MatrixTransform> _graph;
|
||||
osg::ref_ptr<osgText::Text> _textLabel;
|
||||
|
||||
void init(osg::Stats* stats, const std::string& name, const osg::Vec3& pos, float width, float heigh, const osg::Vec4& color);
|
||||
void setPosition(const osg::Vec3& pos);
|
||||
void setAlpha(float v);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/** Event handler for adding on screen stats reporting to Viewers.*/
|
||||
class OSGANIMATION_EXPORT StatsHandler : public osgGA::GUIEventHandler
|
||||
{
|
||||
public:
|
||||
|
||||
StatsHandler();
|
||||
|
||||
enum StatsType
|
||||
{
|
||||
NO_STATS = 0,
|
||||
FRAME_RATE = 1,
|
||||
LAST = 2
|
||||
};
|
||||
|
||||
void setKeyEventTogglesOnScreenStats(int key) { _keyEventTogglesOnScreenStats = key; }
|
||||
int getKeyEventTogglesOnScreenStats() const { return _keyEventTogglesOnScreenStats; }
|
||||
|
||||
void setKeyEventPrintsOutStats(int key) { _keyEventPrintsOutStats = key; }
|
||||
int getKeyEventPrintsOutStats() const { return _keyEventPrintsOutStats; }
|
||||
|
||||
double getBlockMultiplier() const { return _blockMultiplier; }
|
||||
|
||||
void reset();
|
||||
|
||||
osg::Camera* getCamera() { return _camera.get(); }
|
||||
const osg::Camera* getCamera() const { return _camera.get(); }
|
||||
|
||||
virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa);
|
||||
|
||||
/** Get the keyboard and mouse usage of this manipulator.*/
|
||||
virtual void getUsage(osg::ApplicationUsage& usage) const;
|
||||
|
||||
void updateGraph(osgAnimation::StatsActionVisitor* visitor); //, float width, float height, float ystart);
|
||||
|
||||
protected:
|
||||
|
||||
void setUpHUDCamera(osgViewer::ViewerBase* viewer);
|
||||
|
||||
osg::Geometry* createBackgroundRectangle(const osg::Vec3& pos, const float width, const float height, osg::Vec4& color);
|
||||
|
||||
osg::Geometry* createGeometry(const osg::Vec3& pos, float height, const osg::Vec4& colour, unsigned int numBlocks);
|
||||
|
||||
osg::Geometry* createFrameMarkers(const osg::Vec3& pos, float height, const osg::Vec4& colour, unsigned int numBlocks);
|
||||
|
||||
osg::Geometry* createTick(const osg::Vec3& pos, float height, const osg::Vec4& colour, unsigned int numTicks);
|
||||
|
||||
osg::Node* createCameraTimeStats(const std::string& font, osg::Vec3& pos, float startBlocks, bool acquireGPUStats, float characterSize, osg::Stats* viewerStats, osg::Camera* camera);
|
||||
|
||||
void setUpScene(osgViewer::Viewer* viewer);
|
||||
|
||||
int _keyEventTogglesOnScreenStats;
|
||||
int _keyEventPrintsOutStats;
|
||||
|
||||
int _statsType;
|
||||
|
||||
bool _initialized;
|
||||
osg::ref_ptr<osg::Camera> _camera;
|
||||
|
||||
osg::ref_ptr<osg::Switch> _switch;
|
||||
osg::ref_ptr<osg::Group> _group;
|
||||
|
||||
unsigned int _frameRateChildNum;
|
||||
unsigned int _numBlocks;
|
||||
double _blockMultiplier;
|
||||
|
||||
float _statsWidth;
|
||||
float _statsHeight;
|
||||
|
||||
// std::map<std::string, StatAction > _actions;
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
53
include/osgAnimation/StatsVisitor
Normal file
53
include/osgAnimation/StatsVisitor
Normal file
@@ -0,0 +1,53 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@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.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_STATSVISITOR_H
|
||||
#define OSGANIMATION_STATSVISITOR_H
|
||||
|
||||
#include <osgAnimation/Export>
|
||||
#include <osgAnimation/ActionVisitor>
|
||||
#include <osg/Stats>
|
||||
#include <vector>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
|
||||
class OSGANIMATION_EXPORT StatsActionVisitor : public osgAnimation::UpdateActionVisitor
|
||||
{
|
||||
protected:
|
||||
osg::ref_ptr<osg::Stats> _stats;
|
||||
std::vector<std::string> _channels;
|
||||
|
||||
public:
|
||||
META_ActionVisitor(osgAnimation, StatsActionVisitor);
|
||||
|
||||
StatsActionVisitor();
|
||||
StatsActionVisitor(osg::Stats* stats, unsigned int frame);
|
||||
void reset();
|
||||
const std::vector<std::string>& getChannels() const { return _channels; }
|
||||
osg::Stats* getStats() { return _stats; }
|
||||
void setStats(osg::Stats* stats) { _stats = stats; }
|
||||
void setFrame(unsigned int frame) { _frame = frame; }
|
||||
void apply(Timeline& action);
|
||||
void apply(Action& action);
|
||||
void apply(BlendIn& action);
|
||||
void apply(BlendOut& action);
|
||||
void apply(ActionAnimation& action);
|
||||
void apply(StripAnimation& action);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
|
||||
* Copyright (C) 2008 Cedric Pinson <cedric.pinson@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
|
||||
@@ -67,7 +67,7 @@ namespace osgAnimation
|
||||
}
|
||||
const T& getValue() const { return _target;}
|
||||
|
||||
void normalize()
|
||||
void normalize()
|
||||
{
|
||||
float weightSummed = getWeight();
|
||||
if (fabs(weightSummed) < 1e-4 || fabs(weightSummed-1) < 1e-4)
|
||||
@@ -91,6 +91,7 @@ namespace osgAnimation
|
||||
|
||||
TemplateTarget () {}
|
||||
TemplateTarget (const osg::Quat& q) { setValue(q); }
|
||||
|
||||
const osg::Quat& getValue() const { return _target;}
|
||||
void update(float weight, const osg::Quat& val)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
|
||||
* Copyright (C) 2008 Cedric Pinson <cedric.pinson@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
|
||||
@@ -16,161 +16,27 @@
|
||||
#define OSGANIMATION_TIMELINE_H
|
||||
|
||||
#include <osgAnimation/Export>
|
||||
#include <osg/Object>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <osg/Notify>
|
||||
#include <osg/Group>
|
||||
#include <osgAnimation/Animation>
|
||||
#include <osg/Stats>
|
||||
#include <osgAnimation/Action>
|
||||
#include <osgAnimation/FrameAction>
|
||||
#include <osgAnimation/AnimationManagerBase>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
class StatsActionVisitor;
|
||||
|
||||
class Action : public osg::Object
|
||||
class OSGANIMATION_EXPORT Timeline : public Action //osg::Object
|
||||
{
|
||||
public:
|
||||
|
||||
class Callback : public osg::Object
|
||||
{
|
||||
public:
|
||||
Callback(){}
|
||||
Callback(const Callback&,const osg::CopyOp&) {}
|
||||
|
||||
META_Object(osgAnimation,Callback);
|
||||
|
||||
virtual void operator()(Action* /*action*/) {}
|
||||
|
||||
void addNestedCallback(Callback* callback)
|
||||
{
|
||||
if (_nested.valid())
|
||||
_nested->addNestedCallback(callback);
|
||||
else
|
||||
_nested = callback;
|
||||
}
|
||||
|
||||
protected:
|
||||
osg::ref_ptr<Callback> _nested;
|
||||
};
|
||||
|
||||
|
||||
typedef std::map<unsigned int, osg::ref_ptr<Callback> > FrameCallback;
|
||||
|
||||
META_Object(osgAnimation, Action);
|
||||
|
||||
Action()
|
||||
{
|
||||
_numberFrame = 25;
|
||||
_fps = 25;
|
||||
_speed = 1.0;
|
||||
_loop = 1;
|
||||
}
|
||||
|
||||
Action(const Action&,const osg::CopyOp&) {}
|
||||
|
||||
void setCallback(double when, Callback* callback)
|
||||
{
|
||||
setCallback(static_cast<unsigned int>(floor(when*_fps)), callback);
|
||||
}
|
||||
|
||||
void setCallback(unsigned int frame, Callback* callback)
|
||||
{
|
||||
if (_framesCallback[frame].valid())
|
||||
_framesCallback[frame]->addNestedCallback(callback);
|
||||
else
|
||||
_framesCallback[frame] = callback;
|
||||
}
|
||||
Callback* getCallback(unsigned int frame)
|
||||
{
|
||||
if (_framesCallback.find(frame) == _framesCallback.end())
|
||||
return 0;
|
||||
return _framesCallback[frame].get();
|
||||
}
|
||||
|
||||
void setNumFrames(unsigned int numFrames) { _numberFrame = numFrames;}
|
||||
void setDuration(double duration) { _numberFrame = static_cast<unsigned int>(floor(duration * _fps)); }
|
||||
|
||||
unsigned int getNumFrames() const { return _numberFrame;}
|
||||
double getDuration() const { return _numberFrame * 1.0 / _fps; }
|
||||
|
||||
// 0 means infini else it's the number of loop
|
||||
virtual void setLoop(int nb) { _loop = nb; }
|
||||
virtual unsigned int getLoop() const { return _loop;}
|
||||
|
||||
// get the number of loop, the frame relative to loop.
|
||||
// return true if in range, and false if out of range.
|
||||
bool evaluateFrame(unsigned int frame, unsigned int& resultframe, unsigned int& nbloop )
|
||||
{
|
||||
nbloop = frame / getNumFrames();
|
||||
resultframe = frame;
|
||||
|
||||
if (frame > getNumFrames()-1)
|
||||
{
|
||||
if (!getLoop())
|
||||
resultframe = frame % getNumFrames();
|
||||
else
|
||||
{
|
||||
if (nbloop >= getLoop())
|
||||
return false;
|
||||
else
|
||||
resultframe = frame % getNumFrames();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void evaluate(unsigned int frame)
|
||||
{
|
||||
unsigned int frameInAction;
|
||||
unsigned int loopDone;
|
||||
if (!evaluateFrame(frame, frameInAction, loopDone))
|
||||
osg::notify(osg::DEBUG_INFO) << getName() << " Action frame " << frameInAction << " finished" << std::endl;
|
||||
else
|
||||
osg::notify(osg::DEBUG_INFO) << getName() << " Action frame " << frame << " relative to loop " << frameInAction << " no loop " << loopDone<< std::endl;
|
||||
}
|
||||
|
||||
virtual void evaluateCallback(unsigned int frame)
|
||||
{
|
||||
unsigned int frameInAction;
|
||||
unsigned int loopDone;
|
||||
if (!evaluateFrame(frame, frameInAction, loopDone))
|
||||
return;
|
||||
|
||||
frame = frameInAction;
|
||||
if (_framesCallback.find(frame) != _framesCallback.end())
|
||||
{
|
||||
std::cout << getName() << " evaluate callback " << _framesCallback[frame]->getName() << " at " << frame << std::endl;
|
||||
(*_framesCallback[frame])(this);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
FrameCallback _framesCallback;
|
||||
|
||||
double _speed;
|
||||
unsigned int _fps;
|
||||
unsigned int _numberFrame;
|
||||
unsigned int _loop;
|
||||
|
||||
enum ActionStatus
|
||||
{
|
||||
Play,
|
||||
Stop
|
||||
};
|
||||
|
||||
ActionStatus _state;
|
||||
};
|
||||
|
||||
|
||||
class OSGANIMATION_EXPORT Timeline : public osg::Object
|
||||
{
|
||||
public:
|
||||
|
||||
META_Object(osgAnimation, Timeline);
|
||||
|
||||
Timeline();
|
||||
Timeline(const Timeline& nc,const osg::CopyOp& op = osg::CopyOp::SHALLOW_COPY);
|
||||
|
||||
META_Action(osgAnimation, Timeline);
|
||||
|
||||
enum TimelineStatus
|
||||
{
|
||||
Play,
|
||||
@@ -179,14 +45,10 @@ namespace osgAnimation
|
||||
|
||||
TimelineStatus getStatus() const { return _state; }
|
||||
|
||||
typedef std::pair<unsigned int, osg::ref_ptr<Action> > FrameAction;
|
||||
typedef std::vector<FrameAction> ActionList;
|
||||
typedef std::map<int, ActionList> ActionLayers;
|
||||
|
||||
const ActionList& getActionLayer(int i)
|
||||
{
|
||||
return _actions[i];
|
||||
}
|
||||
const ActionList& getActionLayer(int i) { return _actions[i];}
|
||||
unsigned int getCurrentFrame() const { return _currentFrame;}
|
||||
double getCurrentTime() const { return _currentFrame * 1.0 / _fps;}
|
||||
|
||||
@@ -195,139 +57,44 @@ namespace osgAnimation
|
||||
void stop() { _state = Stop; }
|
||||
bool getEvaluating() const { return _evaluating;}
|
||||
|
||||
bool isActive(Action* activeAction)
|
||||
{
|
||||
// update from high priority to low priority
|
||||
for( ActionLayers::iterator iterAnim = _actions.begin(); iterAnim != _actions.end(); ++iterAnim )
|
||||
{
|
||||
// update all animation
|
||||
ActionList& list = iterAnim->second;
|
||||
for (unsigned int i = 0; i < list.size(); i++)
|
||||
{
|
||||
Action* action = list[i].second.get();
|
||||
if (action == activeAction)
|
||||
{
|
||||
unsigned int firstFrame = list[i].first;
|
||||
// check if current frame of timeline hit an action interval
|
||||
if (_currentFrame >= firstFrame &&
|
||||
_currentFrame < (firstFrame + action->getNumFrames()) )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool isActive(Action* activeAction);
|
||||
|
||||
void removeAction(Action* action)
|
||||
{
|
||||
if (getEvaluating())
|
||||
_removeActionOperations.push_back(FrameAction(0, action));
|
||||
else
|
||||
internalRemoveAction(action);
|
||||
}
|
||||
void removeAction(Action* action);
|
||||
virtual void addActionAt(unsigned int frame, Action* action, int priority = 0);
|
||||
virtual void addActionAt(double t, Action* action, int priority = 0);
|
||||
void addActionNow(Action* action, int priority = 0);
|
||||
|
||||
virtual void addActionAt(unsigned int frame, Action* action, int priority = 0)
|
||||
{
|
||||
if (getEvaluating())
|
||||
_addActionOperations.push_back(Command(priority,FrameAction(frame, action)));
|
||||
else
|
||||
internalAddAction(priority, FrameAction(frame, action));
|
||||
}
|
||||
virtual void addActionAt(double t, Action* action, int priority = 0)
|
||||
{
|
||||
unsigned int frame = static_cast<unsigned int>(floor(t * _fps));
|
||||
addActionAt(frame, action, priority);
|
||||
}
|
||||
void clearActions();
|
||||
|
||||
virtual void evaluate(unsigned int frame)
|
||||
{
|
||||
setEvaluating(true);
|
||||
osg::notify(osg::DEBUG_INFO) << getName() << " evaluate frame " << _currentFrame << std::endl;
|
||||
virtual void update(double simulationTime);
|
||||
void setLastFrameEvaluated(unsigned int frame) { _previousFrameEvaluated = frame; }
|
||||
|
||||
// update from high priority to low priority
|
||||
for( ActionLayers::reverse_iterator iterAnim = _actions.rbegin(); iterAnim != _actions.rend(); ++iterAnim )
|
||||
{
|
||||
// update all animation
|
||||
ActionList& list = iterAnim->second;
|
||||
for (unsigned int i = 0; i < list.size(); i++)
|
||||
{
|
||||
unsigned int firstFrame = list[i].first;
|
||||
Action* action = list[i].second.get();
|
||||
// check if current frame of timeline hit an action interval
|
||||
if (frame >= firstFrame &&
|
||||
frame < (firstFrame + action->getNumFrames()) )
|
||||
action->evaluate(frame - firstFrame);
|
||||
}
|
||||
}
|
||||
setEvaluating(false);
|
||||
void setEvaluating(bool state) { _evaluating = state;}
|
||||
void traverse(ActionVisitor& visitor);
|
||||
|
||||
// evaluate callback after updating all animation
|
||||
evaluateCallback(frame);
|
||||
_previousFrameEvaluated = frame;
|
||||
}
|
||||
void setStats(osg::Stats* stats);
|
||||
osg::Stats* getStats();
|
||||
void collectStats(bool state);
|
||||
osgAnimation::StatsActionVisitor* getStatsVisitor();
|
||||
|
||||
virtual void evaluateCallback(unsigned int frame)
|
||||
{
|
||||
// update from high priority to low priority
|
||||
for( ActionLayers::reverse_iterator iterAnim = _actions.rbegin(); iterAnim != _actions.rend(); ++iterAnim )
|
||||
{
|
||||
// update all animation
|
||||
ActionList& list = iterAnim->second;
|
||||
for (unsigned int i = 0; i < list.size(); i++)
|
||||
{
|
||||
unsigned int firstFrame = list[i].first;
|
||||
Action* action = list[i].second.get();
|
||||
// check if current frame of timeline hit an action interval
|
||||
if (frame >= firstFrame &&
|
||||
frame < (firstFrame + action->getNumFrames()) )
|
||||
action->evaluateCallback(frame - firstFrame);
|
||||
}
|
||||
}
|
||||
processPendingOperation();
|
||||
}
|
||||
const ActionLayers& getActionLayers() const { return _actions; }
|
||||
|
||||
virtual void update(double simulationTime)
|
||||
{
|
||||
// first time we call update we generate one frame
|
||||
if (!_initFirstFrame)
|
||||
{
|
||||
_lastUpdate = simulationTime;
|
||||
_initFirstFrame = true;
|
||||
evaluate(_currentFrame);
|
||||
}
|
||||
|
||||
// find the number of frame pass since the last update
|
||||
double delta = (simulationTime - _lastUpdate);
|
||||
double nbframes = delta * _fps * _speed;
|
||||
unsigned int nb = static_cast<unsigned int>(floor(nbframes));
|
||||
|
||||
for (unsigned int i = 0; i < nb; i++)
|
||||
{
|
||||
if (_state == Play)
|
||||
_currentFrame++;
|
||||
evaluate(_currentFrame);
|
||||
}
|
||||
if (nb)
|
||||
{
|
||||
_lastUpdate += ((double)nb) / _fps;
|
||||
}
|
||||
}
|
||||
void processPendingOperation();
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
ActionLayers _actions;
|
||||
double _lastUpdate;
|
||||
double _speed;
|
||||
unsigned int _currentFrame;
|
||||
unsigned int _fps;
|
||||
unsigned int _numberFrame;
|
||||
unsigned int _previousFrameEvaluated;
|
||||
bool _loop;
|
||||
bool _initFirstFrame;
|
||||
|
||||
TimelineStatus _state;
|
||||
|
||||
bool _collectStats;
|
||||
osg::ref_ptr<osg::Stats> _stats;
|
||||
osg::ref_ptr<osgAnimation::StatsActionVisitor> _statsVisitor;
|
||||
|
||||
// to manage pending operation
|
||||
bool _evaluating;
|
||||
|
||||
@@ -343,199 +110,13 @@ namespace osgAnimation
|
||||
CommandList _addActionOperations;
|
||||
ActionList _removeActionOperations;
|
||||
|
||||
void setEvaluating(bool state) { _evaluating = state;}
|
||||
void processPendingOperation()
|
||||
{
|
||||
// process all pending add action operation
|
||||
while( !_addActionOperations.empty())
|
||||
{
|
||||
internalAddAction(_addActionOperations.back()._priority, _addActionOperations.back()._action);
|
||||
_addActionOperations.pop_back();
|
||||
}
|
||||
|
||||
// process all pending remove action operation
|
||||
while( !_removeActionOperations.empty())
|
||||
{
|
||||
internalRemoveAction(_removeActionOperations.back().second.get());
|
||||
_removeActionOperations.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
void internalRemoveAction(Action* action)
|
||||
{
|
||||
for (ActionLayers::iterator it = _actions.begin(); it != _actions.end(); it++)
|
||||
{
|
||||
ActionList& fa = it->second;
|
||||
for (unsigned int i = 0; i < fa.size(); i++)
|
||||
if (fa[i].second.get() == action)
|
||||
{
|
||||
fa.erase(fa.begin() + i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
void internalAddAction(int priority, const FrameAction& ftl)
|
||||
{
|
||||
_actions[priority].push_back(ftl);
|
||||
}
|
||||
void internalRemoveAction(Action* action);
|
||||
void internalAddAction(int priority, const FrameAction& ftl);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
// blend in from 0 to weight in duration
|
||||
class BlendIn : public Action
|
||||
{
|
||||
double _weight;
|
||||
osg::ref_ptr<Animation> _animation;
|
||||
|
||||
public:
|
||||
BlendIn(Animation* animation, double duration, double weight)
|
||||
{
|
||||
_animation = animation;
|
||||
_weight = weight;
|
||||
float d = duration * _fps;
|
||||
setNumFrames(static_cast<unsigned int>(floor(d)) + 1);
|
||||
setName("BlendIn");
|
||||
}
|
||||
double getWeight() const { return _weight;}
|
||||
virtual void evaluate(unsigned int frame)
|
||||
{
|
||||
Action::evaluate(frame);
|
||||
// frame + 1 because the start is 0 and we want to start the blend in at the first
|
||||
// frame.
|
||||
double ratio = ( (frame+1) * 1.0 / (getNumFrames()) );
|
||||
double w = _weight;
|
||||
if (frame < getNumFrames() -1 ) // the last frame we set the target weight the user asked
|
||||
w = _weight * ratio;
|
||||
_animation->setWeight(w);
|
||||
}
|
||||
};
|
||||
|
||||
// blend in from 0 to weight in duration
|
||||
class BlendOut : public Action
|
||||
{
|
||||
double _weight;
|
||||
osg::ref_ptr<Animation> _animation;
|
||||
public:
|
||||
BlendOut(Animation* animation, double duration)
|
||||
{
|
||||
_animation = animation;
|
||||
float d = duration * _fps;
|
||||
setNumFrames(static_cast<unsigned int>(floor(d) + 1));
|
||||
_weight = 1.0;
|
||||
setName("BlendOut");
|
||||
}
|
||||
double getWeight() const { return _weight;}
|
||||
virtual void evaluate(unsigned int frame)
|
||||
{
|
||||
Action::evaluate(frame);
|
||||
// frame + 1 because the start is 0 and we want to start the blend in at the first
|
||||
// frame.
|
||||
double ratio = ( (frame+1) * 1.0 / (getNumFrames()) );
|
||||
double w = 0.0;
|
||||
if (frame < getNumFrames() -1 ) // the last frame we set the target weight the user asked
|
||||
w = _weight * (1.0-ratio);
|
||||
_animation->setWeight(w);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class ActionAnimation : public Action
|
||||
{
|
||||
public:
|
||||
ActionAnimation(Animation* animation) : _animation(animation)
|
||||
{
|
||||
setDuration(animation->getDuration());
|
||||
setName(animation->getName());
|
||||
}
|
||||
virtual void evaluate(unsigned int frame)
|
||||
{
|
||||
Action::evaluate(frame);
|
||||
_animation->update(frame * 1.0/_fps);
|
||||
}
|
||||
Animation* getAnimation() { return _animation.get(); }
|
||||
protected:
|
||||
osg::ref_ptr<Animation> _animation;
|
||||
};
|
||||
|
||||
|
||||
// encapsulate animation with blend in blend out for classic usage
|
||||
class StripAnimation : public Action
|
||||
{
|
||||
protected:
|
||||
typedef std::pair<unsigned int, osg::ref_ptr<Action> > FrameAction;
|
||||
|
||||
public:
|
||||
StripAnimation(Animation* animation, double blendInDuration, double blendOutDuration, double blendInWeightTarget = 1.0 )
|
||||
{
|
||||
_blendIn = new BlendIn(animation, blendInDuration, blendInWeightTarget);
|
||||
_animation = new ActionAnimation(animation);
|
||||
unsigned int start = static_cast<unsigned int>(floor((_animation->getDuration() - blendOutDuration) * _fps));
|
||||
_blendOut = FrameAction(start, new BlendOut(animation, blendOutDuration));
|
||||
setName(animation->getName() + "_Strip");
|
||||
_blendIn->setName(_animation->getName() + "_" + _blendIn->getName());
|
||||
_blendOut.second->setName(_animation->getName() + "_" + _blendOut.second->getName());
|
||||
setDuration(animation->getDuration());
|
||||
}
|
||||
|
||||
ActionAnimation* getActionAnimation() { return _animation.get(); }
|
||||
BlendIn* getBlendIn() { return _blendIn.get(); }
|
||||
BlendOut* getBlendOut() { return dynamic_cast<BlendOut*>(_blendOut.second.get()); }
|
||||
const ActionAnimation* getActionAnimation() const { return _animation.get(); }
|
||||
const BlendIn* getBlendIn() const { return _blendIn.get(); }
|
||||
const BlendOut* getBlendOut() const { return dynamic_cast<BlendOut*>(_blendOut.second.get()); }
|
||||
|
||||
unsigned int getLoop() const { return _animation->getLoop(); }
|
||||
void setLoop(unsigned int loop)
|
||||
{
|
||||
_animation->setLoop(loop);
|
||||
if (!loop)
|
||||
setDuration(-1);
|
||||
else
|
||||
setDuration(loop * _animation->getDuration());
|
||||
|
||||
// duration changed re evaluate the blendout duration
|
||||
unsigned int start = static_cast<unsigned int>(floor((getDuration() - _blendOut.second->getDuration()) * _fps));
|
||||
_blendOut = FrameAction(start, _blendOut.second);
|
||||
}
|
||||
|
||||
virtual void evaluate(unsigned int frame)
|
||||
{
|
||||
if (frame > getNumFrames() - 1)
|
||||
return;
|
||||
|
||||
Action::evaluate(frame);
|
||||
if (frame < _blendIn->getNumFrames())
|
||||
_blendIn->evaluate(frame);
|
||||
if (frame >= _blendOut.first)
|
||||
_blendOut.second->evaluate(frame - _blendOut.first);
|
||||
_animation->evaluate(frame);
|
||||
}
|
||||
|
||||
protected:
|
||||
osg::ref_ptr<BlendIn> _blendIn;
|
||||
FrameAction _blendOut;
|
||||
osg::ref_ptr<ActionAnimation> _animation;
|
||||
};
|
||||
|
||||
|
||||
class RunAction : public Action::Callback
|
||||
{
|
||||
protected:
|
||||
osg::ref_ptr<Timeline> _tm;
|
||||
osg::ref_ptr<Action> _action;
|
||||
|
||||
public:
|
||||
RunAction(Timeline* tm, Action* a) : _tm(tm), _action(a) {}
|
||||
virtual void operator()(Action* /*action*/)
|
||||
{
|
||||
_tm->addActionAt(_tm->getCurrentFrame(), _action.get()); // warning we are trsversing the vector
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user