/* ----------------------------------------------------------------------------- GSFramework Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. ----------------------------------------------------------------------------- */ #ifndef __PLATFORM_IOS__ #include #endif #include "automation/automation_player.h" #include "automation/automation_source.h" #include "platform_config.h" using namespace GS::Automation; //------------------------------------------------------------------------------ Motion *Player::GetMotion(const char *id) const { ListForeachPtr(Motion *, i, motions) if (!String::Compare(i->name, id)) return i; return NULL; } Motion *Player::GetMotionFromIndex(uint index) const { return motions.ObjectAt(index); } bool Player::AddMotion(Motion *motion) { return asbool(motions.Add(motion)); } void Player::RemoveMotion(Motion *motion) { motions.Remove(motion); } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ Source *Player::StartAutomation(Source *source, float _blend, AddSourceMode mode, float _weight) { if (!source) return NULL; // Source blend. switch (mode) { case SourceSet: // Dispose of all current sources. ListForeachPtr(Source *, s, sources) s->Dispose(_blend); break; default: break; } // Blend in source. source->SetWeight(_weight, _blend); sources.Add(source); switch (source->GetType()) { case Source::TypeMotion: source->relative = flags.IsSet(FlagRelativeMotion); break; default: break; } return source; } void Player::Evaluate(const GS::Time &dt_time) { if (!sources.GetCount() || property_provider.IsNull()) return; // Allocate weight table from stack. weight_table = (float *)alloca(sizeof(float) * MotionChannel::Last); for (int n = 0; n < MotionChannel::Last; ++n) weight_table[n] = 0; // Update sources. ListForeachPtr(Source *, s, sources) { s->Update(dt_time); if (s->CanDispose()) sources.Remove(s); } // Mix rotation. float w = 0; Quaternion q, source_q = property_provider->GetRotation(); ListForeachPtr(Source *, s, sources) if (s->GetWeight() > 0.01) if (s->EvaluateRotation(source_q)) { if (w > 0.01) q = Quaternion::Slerp(w / (w + s->GetWeight()), source_q, q); else q = source_q; w += s->GetWeight(); } if (w > 0) property_provider->SetRotation(q); // Mix sources. ListForeachPtr(Source *, s, sources) if (s->GetWeight()) s->Evaluate(*this); // Drop weight table. weight_table = NULL; } void Player::BlendAutomatedProperty(MotionChannel::Type type, float _v, float _w) { if (!_w || !weight_table) return; float v, *w = &weight_table[(uint)type]; if (property_provider->GetProperty(type, v)) { v = (v * *w + _v * _w) / (*w + _w); *w += _w; property_provider->SetProperty(type, v); } } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ bool Player::IsAutomated() const { return asbool(sources.GetCount()); } bool Player::IsAutomationDone() const { ListForeachPtr(Source *, s, GetSourceList()) if (!s->IsDone()) return false; return true; } bool Player::GetAutomationActive() const { return active; } void Player::SetAutomationActive(bool _active) { active = _active; } void Player::DisposeAutomationSources() { sources.Clear(); } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ Player::Player() { active = true; weight_table = NULL; } Player::~Player() { DisposeAutomationSources(); } //------------------------------------------------------------------------------