#include "Base.h" #include "AnimationChannel.h" #include "Transform.h" namespace gameplay { AnimationChannel::AnimationChannel(void) : _targetAttrib(0) { } AnimationChannel::~AnimationChannel(void) { } unsigned int AnimationChannel::getTypeId(void) const { return ANIMATIONCHANNEL_ID; } const char* AnimationChannel::getElementName(void) const { return "AnimationChannel"; } void AnimationChannel::writeBinary(FILE* file) { Object::writeBinary(file); write(_targetId, file); write(_targetAttrib, file); write((unsigned int)_keytimes.size(), file); for (std::vector::const_iterator i = _keytimes.begin(); i != _keytimes.end(); ++i) { write((unsigned int)*i, file); } write(_keyValues, file); write(_tangentsIn, file); write(_tangentsOut, file); write(_interpolations, file); } void AnimationChannel::writeText(FILE* file) { fprintElementStart(file); fprintfElement(file, "targetId", _targetId); fprintf(file, "<%s>%u %s\n", "targetAttrib", _targetAttrib, Transform::getPropertyString(_targetAttrib), "targetAttrib"); fprintfElement(file, "%f ", "keytimes", _keytimes); fprintfElement(file, "%f ", "values", _keyValues); fprintfElement(file, "%f ", "tangentsIn", _tangentsIn); fprintfElement(file, "%f ", "tangentsOut", _tangentsOut); fprintfElement(file, "%u ", "interpolations", _interpolations); fprintElementEnd(file); } void AnimationChannel::setInterpolation(unsigned int interpolation) { _interpolations.clear(); _interpolations.push_back(interpolation); } const std::string& AnimationChannel::getTargetId() const { return _targetId; } unsigned int AnimationChannel::getTargetAttribute() const { return _targetAttrib; } std::vector& AnimationChannel::getKeyValues() { return _keyValues; } std::vector& AnimationChannel::getKeyTimes() { return _keytimes; } std::vector& AnimationChannel::getTangentsIn() { return _tangentsIn; } std::vector& AnimationChannel::getTangentsOut() { return _tangentsOut; } std::vector& AnimationChannel::getInterpolationTypes() { return _interpolations; } void AnimationChannel::setTargetId(const std::string& str) { _targetId = str; } void AnimationChannel::setTargetAttribute(unsigned int attrib) { _targetAttrib = attrib; } void AnimationChannel::setKeyTimes(const std::vector& values) { _keytimes = values; } void AnimationChannel::setKeyValues(const std::vector& values) { _keyValues = values; } void AnimationChannel::setTangentsIn(const std::vector& values) { _tangentsIn = values; } void AnimationChannel::setTangentsOut(const std::vector& values) { _tangentsOut = values; } void AnimationChannel::setInterpolations(const std::vector& values) { _interpolations = values; } void AnimationChannel::removeDuplicates() { LOG(3, " Removing duplicates for channel with target attribute: %u.\n", _targetAttrib); int startCount = _keytimes.size(); size_t propSize = Transform::getPropertySize(_targetAttrib); if (propSize > 1 && !_interpolations.empty() && _interpolations[0] == LINEAR) { size_t prevIndex = 0; std::vector::iterator prevStart = _keyValues.begin(); std::vector::iterator prevEnd = prevStart + propSize - 1; size_t i = 1; for (i = 1; i < _keytimes.size(); ++i) { std::vector::iterator start = _keyValues.begin() + i * propSize; std::vector::iterator end = start + propSize - 1; if (!equal(prevStart, prevEnd, start) || i == _keytimes.size() - 1) { if (i - prevIndex > 2) { deleteRange(prevIndex+1, i, propSize); i = prevIndex; prevStart = _keyValues.begin() + i * propSize; prevEnd = prevStart + propSize - 1; } else { prevStart = start; prevEnd = end; prevIndex = i; } } } if (i - 1 - prevIndex >= 2) { deleteRange(prevIndex+1, i, propSize); } } LOG(3, " Removed %d duplicate keyframes from channel.\n", startCount- _keytimes.size()); } unsigned int AnimationChannel::getInterpolationType(const char* str) { unsigned int value = 0; switch (str[0]) { case 'L': if (strcmp(str, "LINEAR") == 0) { value = AnimationChannel::LINEAR; } break; case 'B': if (strcmp(str, "BEZIER") == 0) { value = AnimationChannel::BEZIER; } else if (strcmp(str, "BSPLINE") == 0) { value = AnimationChannel::BSPLINE; } break; case 'C': if (strcmp(str, "CARDINAL") == 0) { value = AnimationChannel::CARDINAL; } break; case 'H': if (strcmp(str, "HERMITE") == 0) { value = AnimationChannel::HERMITE; } break; case 'S': if (strcmp(str, "STEP") == 0) { value = AnimationChannel::STEP; } break; default: break; } return value; } void AnimationChannel::deleteRange(size_t begin, size_t end, size_t propSize) { assert(end > begin); // delete range LOG(4, " delete %lu to %lu\n", begin, end - 1); std::vector::iterator a = _keyValues.begin() + begin * propSize; std::vector::iterator b = _keyValues.begin() + end * propSize; _keyValues.erase(a, b); a = _keytimes.begin() + begin; b = _keytimes.begin() + end; _keytimes.erase(a, b); if (_interpolations.size() > 1) { std::vector::iterator a = _interpolations.begin() + begin; std::vector::iterator b = _interpolations.begin() + end * propSize; _interpolations.erase(a, b); } // TODO: also remove key frames from _tangentsIn and _tangentsOut once other curve types are supported. } }