144 lines
3.2 KiB
C++
144 lines
3.2 KiB
C++
/* -----------------------------------------------------------------------------
|
|
GSFramework
|
|
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
|
----------------------------------------------------------------------------- */
|
|
|
|
|
|
#include "motion/motion_automation_source.h"
|
|
#include "motion/motion.h"
|
|
#include "automation/automation_source_group.h"
|
|
#include "automation/automation_player.h"
|
|
|
|
using namespace GS::Automation;
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
void MotionSource::Evaluate(Player &target)
|
|
{
|
|
if (motion == NULL)
|
|
return;
|
|
|
|
ListForeachPtr(MotionChannel *, channel, motion->GetChannelList())
|
|
{
|
|
if (channel->GetPointCount() == 0)
|
|
continue;
|
|
|
|
// Skip rotation channels if using quaternion.
|
|
if (motion->GetUseQuaternion())
|
|
switch (channel->type)
|
|
{
|
|
case MotionChannel::XRot:
|
|
case MotionChannel::YRot:
|
|
case MotionChannel::ZRot:
|
|
continue;
|
|
|
|
default: break;
|
|
}
|
|
|
|
// Evaluate channel.
|
|
float v;
|
|
channel->Evaluate(time, &v, loop_mode, loop_start, loop_end);
|
|
|
|
// Relative mode.
|
|
switch (channel->type)
|
|
{
|
|
case MotionChannel::XPos:
|
|
case MotionChannel::YPos:
|
|
case MotionChannel::ZPos:
|
|
{
|
|
float _v = v, s;
|
|
if (relative && target.property_provider->GetProperty(channel->type, s))
|
|
v = s + v - p_pos[channel->type - MotionChannel::XPos];
|
|
p_pos[channel->type - MotionChannel::XPos] = _v;
|
|
}
|
|
break;
|
|
|
|
case MotionChannel::XRot:
|
|
case MotionChannel::YRot:
|
|
case MotionChannel::ZRot:
|
|
{
|
|
float _v = v, s;
|
|
if (relative && target.property_provider->GetProperty(channel->type, s))
|
|
v = s + v - p_euler[channel->type - MotionChannel::XRot];
|
|
p_euler[channel->type - MotionChannel::XRot] = _v;
|
|
}
|
|
break;
|
|
|
|
default: break;
|
|
}
|
|
|
|
target.BlendAutomatedProperty(channel->type, v, GetWeight());
|
|
}
|
|
}
|
|
bool MotionSource::EvaluateRotation(GS::Quaternion &q)
|
|
{
|
|
if (!motion->GetUseQuaternion())
|
|
return false;
|
|
|
|
Quaternion s = q;
|
|
motion->GetQuaternion().Evaluate(time, q, loop_mode, loop_start, loop_end);
|
|
|
|
Quaternion _q = q;
|
|
if (relative)
|
|
q = (q * p_quat.Inverse()) * s;
|
|
p_quat = _q;
|
|
return true;
|
|
}
|
|
bool MotionSource::IsDone() const
|
|
{
|
|
if (!motion)
|
|
return true;
|
|
|
|
switch (loop_mode)
|
|
{
|
|
case Curve::Repeat:
|
|
case Curve::OffsetAndRepeat:
|
|
case Curve::Oscillate:
|
|
break;
|
|
|
|
default:
|
|
if (time_scale > 0)
|
|
{
|
|
if (time > loop_end)
|
|
return true;
|
|
}
|
|
else
|
|
if (time < loop_start)
|
|
return true;
|
|
break;
|
|
}
|
|
return false;
|
|
}
|
|
MotionSource::MotionSource(Motion *_motion, SourceGroup *_group)
|
|
{
|
|
type = TypeMotion;
|
|
motion = _motion;
|
|
|
|
loop_mode = Curve::Constant;
|
|
|
|
if (motion)
|
|
{
|
|
TimeRange range = motion->GetTimeRange();
|
|
loop_start = range.start;
|
|
loop_end = range.end;
|
|
}
|
|
else
|
|
{
|
|
loop_start = Time::Inf;
|
|
loop_end = Time::Inf;
|
|
}
|
|
|
|
// Evaluate relative position/euler.
|
|
relative = false;
|
|
|
|
motion->EvaluatePosition(loop_start, p_pos, loop_mode);
|
|
if (motion->GetUseQuaternion())
|
|
motion->GetQuaternion().Evaluate(loop_start, p_quat, loop_mode);
|
|
else motion->EvaluateRotation(loop_start, p_euler, loop_mode);
|
|
|
|
group = _group;
|
|
if (group)
|
|
group->source_list.Add(this, true, false);
|
|
}
|
|
//------------------------------------------------------------------------------
|