diff --git a/KREngine/kraken/KRAnimation.cpp b/KREngine/kraken/KRAnimation.cpp index 47ea76b..1be1203 100644 --- a/KREngine/kraken/KRAnimation.cpp +++ b/KREngine/kraken/KRAnimation.cpp @@ -28,7 +28,8 @@ // authors and should not be interpreted as representing official policies, either expressed // or implied, of Kearwood Gilbert. // - +#include +#include #include "KRAnimation.h" #include "KRAnimationManager.h" #include "KRContext.h" @@ -44,6 +45,7 @@ KRAnimation::KRAnimation(KRContext &context, std::string name) : KRResource(cont m_playing = false; m_local_time = 0.0f; m_duration = 0.0f; + m_start_time = 0.0f; } KRAnimation::~KRAnimation() { @@ -68,6 +70,7 @@ bool KRAnimation::save(KRDataBlock &data) { animation_node->SetAttribute("loop", m_loop ? "true" : "false"); animation_node->SetAttribute("auto_play", m_auto_play ? "true" : "false"); animation_node->SetAttribute("duration", m_duration); + animation_node->SetAttribute("start_time", m_start_time); for(unordered_map::iterator itr = m_layers.begin(); itr != m_layers.end(); ++itr){ (*itr).second->saveXML(animation_node); @@ -93,6 +96,10 @@ KRAnimation *KRAnimation::Load(KRContext &context, const std::string &name, KRDa new_animation->m_duration = 0.0f; // Default value } + if(animation_node->QueryFloatAttribute("start_time", &new_animation->m_start_time) != tinyxml2::XML_SUCCESS) { + new_animation->m_start_time = 0.0f; // Default value + } + if(animation_node->QueryBoolAttribute("loop", &new_animation->m_loop) != tinyxml2::XML_SUCCESS) { new_animation->m_loop = false; // Default value } @@ -157,9 +164,9 @@ void KRAnimation::update(float deltaTime) KRNode::node_attribute_type attribute_type = attribute->getTargetAttribute(); if(curve != NULL && target != NULL) { - int frame_number = (int)(m_local_time * curve->getFrameRate()); + int frame_number = (int)((m_local_time + m_start_time) * curve->getFrameRate()); if(frame_number < curve->getFrameStart()) { - target->SetAttribute(attribute_type, curve->getValue(0)); + target->SetAttribute(attribute_type, curve->getValue(m_start_time)); } else if(frame_number - curve->getFrameStart() >= curve->getFrameCount()) { target->SetAttribute(attribute_type, curve->getValue(curve->getFrameCount() - 1)); } else { @@ -203,6 +210,16 @@ void KRAnimation::setDuration(float duration) m_duration = duration; } +float KRAnimation::getStartTime() +{ + return m_start_time; +} + +void KRAnimation::setStartTime(float start_time) +{ + m_start_time = start_time; +} + bool KRAnimation::isPlaying() { return m_playing; @@ -227,3 +244,62 @@ void KRAnimation::setLooping(bool looping) { m_loop = looping; } + +KRAnimation *KRAnimation::split(const std::string &name, float start_time, float duration, bool strip_unchanging_attributes, bool clone_curves) +{ + KRAnimation *new_animation = new KRAnimation(getContext(), name); + new_animation->setStartTime(start_time); + new_animation->setDuration(duration); + new_animation->m_loop = m_loop; + new_animation->m_auto_play = m_auto_play; + int new_curve_count = 0; + for(unordered_map::iterator layer_itr = m_layers.begin(); layer_itr != m_layers.end(); layer_itr++) { + KRAnimationLayer *layer = (*layer_itr).second; + KRAnimationLayer *new_layer = new KRAnimationLayer(getContext()); + new_layer->setName(layer->getName()); + new_layer->setRotationAccumulationMode(layer->getRotationAccumulationMode()); + new_layer->setScaleAccumulationMode(layer->getScaleAccumulationMode()); + new_layer->setWeight(layer->getWeight()); + new_animation->m_layers[new_layer->getName()] = new_layer; + for(std::vector::iterator attribute_itr = layer->getAttributes().begin(); attribute_itr != layer->getAttributes().end(); attribute_itr++) { + KRAnimationAttribute *attribute = *attribute_itr; + KRAnimationCurve *curve = attribute->getCurve(); + if(curve != NULL) { + bool include_attribute = true; + if(strip_unchanging_attributes) { + if(!curve->valueChanges(start_time, duration)) { + include_attribute = false; + } + } + + if(include_attribute) { + KRAnimationAttribute *new_attribute = new KRAnimationAttribute(getContext()); + KRAnimationCurve *new_curve = curve; + if(clone_curves) { + std::string new_curve_name = name + "_curve" + boost::lexical_cast(++new_curve_count); + new_curve = curve->split(new_curve_name, start_time, duration); + } + + new_attribute->setCurveName(new_curve->getName()); + new_attribute->setTargetName(attribute->getTargetName()); + new_layer->addAttribute(new_attribute); + } + } + } + } + + getContext().getAnimationManager()->addAnimation(new_animation); + return new_animation; +} + +void KRAnimation::deleteCurves() +{ + for(unordered_map::iterator layer_itr = m_layers.begin(); layer_itr != m_layers.end(); layer_itr++) { + KRAnimationLayer *layer = (*layer_itr).second; + for(std::vector::iterator attribute_itr = layer->getAttributes().begin(); attribute_itr != layer->getAttributes().end(); attribute_itr++) { + KRAnimationAttribute *attribute = *attribute_itr; + attribute->deleteCurve(); + } + } +} + diff --git a/KREngine/kraken/KRAnimation.h b/KREngine/kraken/KRAnimation.h index 38166a6..a052177 100644 --- a/KREngine/kraken/KRAnimation.h +++ b/KREngine/kraken/KRAnimation.h @@ -64,7 +64,13 @@ public: void setTime(float time); float getDuration(); void setDuration(float duration); + float getStartTime(); + void setStartTime(float start_time); bool isPlaying(); + + KRAnimation *split(const std::string &name, float start_time, float duration, bool strip_unchanging_attributes = true, bool clone_curves = true); + void deleteCurves(); + private: unordered_map m_layers; bool m_auto_play; @@ -72,6 +78,7 @@ private: bool m_playing; float m_local_time; float m_duration; + float m_start_time; }; diff --git a/KREngine/kraken/KRAnimationAttribute.cpp b/KREngine/kraken/KRAnimationAttribute.cpp index 48d3943..9133f6a 100644 --- a/KREngine/kraken/KRAnimationAttribute.cpp +++ b/KREngine/kraken/KRAnimationAttribute.cpp @@ -152,6 +152,8 @@ void KRAnimationAttribute::loadXML(tinyxml2::XMLElement *e) m_curve = NULL; m_curve_name = e->Attribute("curve"); m_target_name = e->Attribute("target"); + + m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_NONE; const char *szAttribute = e->Attribute("attribute"); @@ -267,4 +269,12 @@ KRAnimationCurve *KRAnimationAttribute::getCurve() return m_curve; } +void KRAnimationAttribute::deleteCurve() +{ + KRAnimationCurve *curve = getCurve(); + if(curve) { + getContext().getAnimationCurveManager()->deleteAnimationCurve(curve); + m_curve = NULL; + } +} diff --git a/KREngine/kraken/KRAnimationAttribute.h b/KREngine/kraken/KRAnimationAttribute.h index 7ddcfb8..6a4f695 100644 --- a/KREngine/kraken/KRAnimationAttribute.h +++ b/KREngine/kraken/KRAnimationAttribute.h @@ -58,6 +58,8 @@ public: KRNode *getTarget(); KRAnimationCurve *getCurve(); + void deleteCurve(); + private: std::string m_target_name; std::string m_curve_name; diff --git a/KREngine/kraken/KRAnimationCurve.cpp b/KREngine/kraken/KRAnimationCurve.cpp index a1abbd7..b85ad15 100644 --- a/KREngine/kraken/KRAnimationCurve.cpp +++ b/KREngine/kraken/KRAnimationCurve.cpp @@ -29,6 +29,7 @@ // or implied, of Kearwood Gilbert. // +#include "KRContext.h" #include "KRAnimationCurve.h" #include "KRDataBlock.h" @@ -48,7 +49,6 @@ KRAnimationCurve::~KRAnimationCurve() m_pData->unload(); delete m_pData; } - bool KRAnimationCurve::load(KRDataBlock *data) { m_pData->unload(); @@ -152,3 +152,44 @@ float KRAnimationCurve::getValue(float local_time) return getValue((int)(local_time * getFrameRate())); } +bool KRAnimationCurve::valueChanges(float start_time, float duration) +{ + return valueChanges((int)(start_time * getFrameRate()), (int)(duration * getFrameRate())); +} + +bool KRAnimationCurve::valueChanges(int start_frame, int frame_count) +{ + + float first_value = getValue(start_frame); + + // Range of frames is not inclusive of last frame + for(int frame_number = start_frame + 1; frame_number < start_frame + frame_count; frame_number++) { + if(getValue(frame_number) != first_value) { + return true; + } + } + + return false; +} + +KRAnimationCurve *KRAnimationCurve::split(const std::string &name, float start_time, float duration) +{ + return split(name, (int)(start_time * getFrameRate()), (int)(duration * getFrameRate())); +} + +KRAnimationCurve *KRAnimationCurve::split(const std::string &name, int start_frame, int frame_count) +{ + KRAnimationCurve *new_curve = new KRAnimationCurve(getContext(), name); + + new_curve->setFrameRate(getFrameRate()); + new_curve->setFrameStart(start_frame); + new_curve->setFrameCount(frame_count); + + // Range of frames is not inclusive of last frame + for(int frame_number = start_frame; frame_number < start_frame + frame_count; frame_number++) { + new_curve->setValue(frame_number, getValue(frame_number)); // TODO - MEMCPY here? + } + + getContext().getAnimationCurveManager()->addAnimationCurve(new_curve); + return new_curve; +} diff --git a/KREngine/kraken/KRAnimationCurve.h b/KREngine/kraken/KRAnimationCurve.h index 3b4f334..ff5309c 100644 --- a/KREngine/kraken/KRAnimationCurve.h +++ b/KREngine/kraken/KRAnimationCurve.h @@ -61,6 +61,11 @@ public: static KRAnimationCurve *Load(KRContext &context, const std::string &name, KRDataBlock *data); + bool valueChanges(float start_time, float duration); + bool valueChanges(int start_frame, int frame_count); + + KRAnimationCurve *split(const std::string &name, float start_time, float duration); + KRAnimationCurve *split(const std::string &name, int start_frame, int frame_count); private: KRDataBlock *m_pData; diff --git a/KREngine/kraken/KRAnimationCurveManager.cpp b/KREngine/kraken/KRAnimationCurveManager.cpp index 017b13a..548d378 100644 --- a/KREngine/kraken/KRAnimationCurveManager.cpp +++ b/KREngine/kraken/KRAnimationCurveManager.cpp @@ -43,6 +43,11 @@ KRAnimationCurveManager::~KRAnimationCurveManager() { } } +void KRAnimationCurveManager::deleteAnimationCurve(KRAnimationCurve *curve) { + m_animationCurves.erase(curve->getName()); + delete curve; +} + KRAnimationCurve *KRAnimationCurveManager::loadAnimationCurve(const std::string &name, KRDataBlock *data) { KRAnimationCurve *pAnimationCurve = KRAnimationCurve::Load(*m_pContext, name, data); m_animationCurves[name] = pAnimationCurve; diff --git a/KREngine/kraken/KRAnimationCurveManager.h b/KREngine/kraken/KRAnimationCurveManager.h index b2a007c..4d59be2 100644 --- a/KREngine/kraken/KRAnimationCurveManager.h +++ b/KREngine/kraken/KRAnimationCurveManager.h @@ -50,6 +50,8 @@ public: void addAnimationCurve(KRAnimationCurve *new_animation_curve); unordered_map &getAnimationCurves(); + void deleteAnimationCurve(KRAnimationCurve *curve); + private: unordered_map m_animationCurves; }; diff --git a/KREngine/kraken/KRAnimationManager.cpp b/KREngine/kraken/KRAnimationManager.cpp index e55c166..76224e7 100644 --- a/KREngine/kraken/KRAnimationManager.cpp +++ b/KREngine/kraken/KRAnimationManager.cpp @@ -100,3 +100,12 @@ void KRAnimationManager::updateActiveAnimations(KRAnimation *animation) m_animationsToUpdate.insert(animation); } +void KRAnimationManager::deleteAnimation(KRAnimation *animation, bool delete_curves) +{ + if(delete_curves) + { + animation->deleteCurves(); + } + m_animations.erase(animation->getName()); + delete animation; +} diff --git a/KREngine/kraken/KRAnimationManager.h b/KREngine/kraken/KRAnimationManager.h index 6456d65..34a06f0 100644 --- a/KREngine/kraken/KRAnimationManager.h +++ b/KREngine/kraken/KRAnimationManager.h @@ -49,6 +49,7 @@ public: KRAnimation *getAnimation(const char *szName); void addAnimation(KRAnimation *new_animation); unordered_map &getAnimations(); + void deleteAnimation(KRAnimation *animation, bool delete_curves); void startFrame(float deltaTime); void endFrame(float deltaTime);