Files
BlitzNext/Runtime/blitz3d/animator.cpp
T
Michael Fabian 'Xaymar' Dirks 2196cb8419 runtime: Formatting
2019-01-18 17:04:17 +01:00

246 lines
4.8 KiB
C++

#include "animator.hpp"
#include "object.hpp"
#include "std.hpp"
Animator::Animator(Animator* t) : _seqs(t->_seqs)
{
_objs.resize(t->_objs.size());
_anims.resize(t->_anims.size());
for (int k = 0; k < t->_objs.size(); ++k) {
_objs[k] = t->_objs[k]->getLastCopy();
_anims[k].keys = t->_anims[k].keys;
}
reset();
}
Animator::Animator(Object* obj, int frames)
{
addObjs(obj);
_anims.resize(_objs.size());
addSeq(frames);
reset();
}
Animator::Animator(const vector<Object*>& objs, int frames) : _objs(objs)
{
_anims.resize(_objs.size());
addSeq(frames);
reset();
}
void Animator::reset()
{
_seq = _mode = _seq_len = _time = _speed = _trans_time = _trans_speed = 0;
}
void Animator::addObjs(Object* obj)
{
_objs.push_back(obj);
for (Entity* e = obj->GetChildren(); e; e = e->GetSuccessor()) {
addObjs(e->getObject());
}
}
void Animator::addSeq(int frames)
{
Seq seq;
seq.frames = frames;
_seqs.push_back(seq);
for (int k = 0; k < _objs.size(); ++k) {
Object* obj = _objs[k];
_anims[k].keys.push_back(obj->getAnimation());
obj->setAnimation(Animation());
}
}
void Animator::addSeqs(Animator* t)
{
for (int n = 0; n < t->_seqs.size(); ++n) {
_seqs.push_back(t->_seqs[n]);
for (int k = 0; k < _objs.size(); ++k) {
int j;
for (j = 0; j < t->_objs.size(); ++j) {
if (_objs[k]->getName() == t->_objs[j]->getName())
break;
}
if (j == t->_objs.size()) {
_anims[k].keys.push_back(Animation());
continue;
}
_anims[k].keys.push_back(t->_anims[j].keys[n]);
}
}
}
void Animator::extractSeq(int first, int last, int seq)
{
Seq sq;
sq.frames = last - first;
_seqs.push_back(sq);
for (int k = 0; k < _objs.size(); ++k) {
Animation& keys = _anims[k].keys[seq];
_anims[k].keys.push_back(Animation(keys, first, last));
}
}
void Animator::updateAnim()
{
for (int k = 0; k < _objs.size(); ++k) {
Object* obj = _objs[k];
const Animation& keys = _anims[k].keys[_seq];
if (keys.numPositionKeys()) {
obj->SetLocalPosition(keys.getPosition(_time));
}
if (keys.numScaleKeys()) {
obj->SetLocalScale(keys.getScale(_time));
}
if (keys.numRotationKeys()) {
obj->SetLocalRotation(keys.getRotation(_time));
}
}
}
void Animator::updateTrans()
{
for (int k = 0; k < _objs.size(); ++k) {
Object* obj = _objs[k];
const Anim& anim = _anims[k];
if (anim.pos)
obj->SetLocalPosition((anim.dest_pos - anim.src_pos) * _trans_time + anim.src_pos);
if (anim.scl)
obj->SetLocalScale((anim.dest_scl - anim.src_scl) * _trans_time + anim.src_scl);
if (anim.rot)
obj->SetLocalRotation(anim.src_rot.slerpTo(anim.dest_rot, _trans_time));
}
}
void Animator::beginTrans()
{
for (int k = 0; k < _objs.size(); ++k) {
Object* obj = _objs[k];
Anim& anim = _anims[k];
const Animation& keys = _anims[k].keys[_seq];
if (anim.pos = !!keys.numPositionKeys()) {
anim.src_pos = obj->GetLocalPosition();
anim.dest_pos = keys.getPosition(_time);
}
if (anim.scl = !!keys.numScaleKeys()) {
anim.src_scl = obj->GetLocalScale();
anim.dest_scl = keys.getScale(_time);
}
if (anim.rot = !!keys.numRotationKeys()) {
anim.src_rot = obj->GetLocalRotation();
anim.dest_rot = keys.getRotation(_time);
}
}
}
void Animator::setAnimTime(float time, int seq)
{
if (seq < 0 || seq > _seqs.size())
return;
_mode = 0;
_speed = 0;
_seq = seq;
_seq_len = _seqs[_seq].frames;
//Ok, mod the anim time!
_time = fmod(time, _seq_len);
//if( time<0 || time>_seq_len ) time=fmod( time,_seq_len );
//_time=time;
if (_time < 0)
_time += +_seq_len;
updateAnim();
}
void Animator::animate(int mode, float speed, int seq, float trans)
{
if (!mode && !speed) {
_mode = 0;
return;
}
if (seq < 0 || seq >= _seqs.size())
return;
_seq = seq;
_mode = mode;
_seq_len = _seqs[_seq].frames;
_speed = speed;
_time = _speed >= 0 ? 0 : _seq_len;
if (trans <= 0) {
updateAnim();
if (!_speed)
_mode = 0;
return;
}
_mode |= 0x8000;
_trans_time = 0;
_trans_speed = 1 / trans;
beginTrans();
}
void Animator::update(float elapsed)
{
if (!_mode)
return;
if (_mode & 0x8000) {
_trans_time += _trans_speed * elapsed;
if (_trans_time < 1) {
updateTrans();
return;
}
_mode &= 0x7fff;
if (!_mode || !_speed) {
updateAnim();
_mode = 0;
return;
}
}
//do anim...
_time += _speed * elapsed;
switch (_mode) {
case ANIM_MODE_LOOP:
_time = fmod(_time, _seq_len);
if (_time < 0)
_time += _seq_len;
break;
case ANIM_MODE_PINGPONG:
_time = fmod(_time, _seq_len * 2);
if (_time < 0)
_time += _seq_len * 2;
if (_time >= _seq_len) {
_time = _seq_len - (_time - _seq_len);
_speed = -_speed;
}
break;
case ANIM_MODE_ONESHOT:
if (_time < 0) {
_time = 0;
_mode = 0;
} else if (_time >= _seq_len) {
_time = _seq_len;
_mode = 0;
}
break;
}
updateAnim();
}