2012-12-01 02:03:18 +00:00
//
// KRAnimation.cpp
2021-08-16 16:35:36 -07:00
// Kraken Engine
2012-12-01 02:03:18 +00:00
//
2023-01-10 14:22:26 -08:00
// Copyright 2023 Kearwood Gilbert. All rights reserved.
2012-12-02 09:31:01 +00:00
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
2012-12-01 02:03:18 +00:00
//
# include "KRAnimation.h"
2012-12-07 01:49:17 +00:00
# include "KRAnimationManager.h"
# include "KRContext.h"
2012-12-07 03:13:10 +00:00
# include "KRNode.h"
# include "KRAnimationCurve.h"
2016-07-10 03:33:58 -07:00
# include "KREngine-common.h"
2012-12-01 02:03:18 +00:00
2023-08-05 16:37:16 -07:00
using namespace mimir ;
2022-08-08 01:07:26 -07:00
KRAnimation : : KRAnimation ( KRContext & context , std : : string name ) : KRResource ( context , name )
2012-12-01 02:03:18 +00:00
{
2022-08-08 01:07:26 -07:00
m_auto_play = false ;
m_loop = false ;
m_playing = false ;
m_local_time = 0.0f ;
m_duration = 0.0f ;
m_start_time = 0.0f ;
2012-12-01 02:03:18 +00:00
}
KRAnimation : : ~ KRAnimation ( )
{
2022-08-08 01:07:26 -07:00
for ( unordered_map < std : : string , KRAnimationLayer * > : : iterator itr = m_layers . begin ( ) ; itr ! = m_layers . end ( ) ; + + itr ) {
delete ( * itr ) . second ;
}
2012-12-01 02:03:18 +00:00
}
2022-08-08 01:07:26 -07:00
std : : string KRAnimation : : getExtension ( )
{
return " kranimation " ;
2012-12-01 02:03:18 +00:00
}
2022-08-08 01:07:26 -07:00
void KRAnimation : : addLayer ( KRAnimationLayer * layer )
2012-12-01 02:03:18 +00:00
{
2022-08-08 01:07:26 -07:00
m_layers [ layer - > getName ( ) ] = layer ;
2012-12-01 02:03:18 +00:00
}
2023-08-05 16:37:16 -07:00
bool KRAnimation : : save ( Block & data )
2022-08-08 01:07:26 -07:00
{
tinyxml2 : : XMLDocument doc ;
tinyxml2 : : XMLElement * animation_node = doc . NewElement ( " animation " ) ;
doc . InsertEndChild ( animation_node ) ;
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 < std : : string , KRAnimationLayer * > : : iterator itr = m_layers . begin ( ) ; itr ! = m_layers . end ( ) ; + + itr ) {
( * itr ) . second - > saveXML ( animation_node ) ;
}
tinyxml2 : : XMLPrinter p ;
doc . Print ( & p ) ;
data . append ( ( void * ) p . CStr ( ) , strlen ( p . CStr ( ) ) + 1 ) ;
return true ;
2012-12-01 02:03:18 +00:00
}
2023-08-05 16:37:16 -07:00
KRAnimation * KRAnimation : : Load ( KRContext & context , const std : : string & name , Block * data )
2012-12-01 02:03:18 +00:00
{
2022-08-08 01:07:26 -07:00
std : : string xml_string = data - > getString ( ) ;
2012-12-01 02:03:18 +00:00
2022-08-08 01:07:26 -07:00
tinyxml2 : : XMLDocument doc ;
doc . Parse ( xml_string . c_str ( ) ) ;
KRAnimation * new_animation = new KRAnimation ( context , name ) ;
tinyxml2 : : XMLElement * animation_node = doc . RootElement ( ) ;
if ( animation_node - > QueryFloatAttribute ( " duration " , & new_animation - > m_duration ) ! = tinyxml2 : : XML_SUCCESS ) {
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
}
if ( animation_node - > QueryBoolAttribute ( " auto_play " , & new_animation - > m_auto_play ) ! = tinyxml2 : : XML_SUCCESS ) {
new_animation - > m_auto_play = false ; // Default value
}
for ( tinyxml2 : : XMLElement * child_element = animation_node - > FirstChildElement ( ) ; child_element ! = NULL ; child_element = child_element - > NextSiblingElement ( ) ) {
if ( strcmp ( child_element - > Name ( ) , " layer " ) = = 0 ) {
KRAnimationLayer * new_layer = new KRAnimationLayer ( context ) ;
new_layer - > loadXML ( child_element ) ;
new_animation - > m_layers [ new_layer - > getName ( ) ] = new_layer ;
2012-12-07 01:49:17 +00:00
}
2022-08-08 01:07:26 -07:00
}
if ( new_animation - > m_auto_play ) {
new_animation - > m_playing = true ;
}
// KRNode *n = KRNode::LoadXML(*new_scene, scene_element->FirstChildElement());
delete data ;
return new_animation ;
2012-12-01 02:03:18 +00:00
}
2012-12-02 10:58:59 +00:00
2022-08-08 01:07:26 -07:00
unordered_map < std : : string , KRAnimationLayer * > & KRAnimation : : getLayers ( )
2012-12-02 10:58:59 +00:00
{
2022-08-08 01:07:26 -07:00
return m_layers ;
2012-12-02 10:58:59 +00:00
}
2022-08-08 01:07:26 -07:00
KRAnimationLayer * KRAnimation : : getLayer ( const char * szName )
2012-12-02 10:58:59 +00:00
{
2022-08-08 01:07:26 -07:00
return m_layers [ szName ] ;
2012-12-02 10:58:59 +00:00
}
2012-12-07 01:49:17 +00:00
void KRAnimation : : update ( float deltaTime )
2022-08-08 01:07:26 -07:00
{
if ( m_playing ) {
m_local_time + = deltaTime ;
}
if ( m_loop ) {
while ( m_local_time > m_duration ) {
m_local_time - = m_duration ;
2012-12-07 01:49:17 +00:00
}
2022-08-08 01:07:26 -07:00
} else if ( m_local_time > m_duration ) {
m_local_time = m_duration ;
m_playing = false ;
getContext ( ) . getAnimationManager ( ) - > updateActiveAnimations ( this ) ;
}
for ( unordered_map < std : : string , KRAnimationLayer * > : : iterator layer_itr = m_layers . begin ( ) ; layer_itr ! = m_layers . end ( ) ; layer_itr + + ) {
KRAnimationLayer * layer = ( * layer_itr ) . second ;
for ( std : : vector < KRAnimationAttribute * > : : iterator attribute_itr = layer - > getAttributes ( ) . begin ( ) ; attribute_itr ! = layer - > getAttributes ( ) . end ( ) ; attribute_itr + + ) {
KRAnimationAttribute * attribute = * attribute_itr ;
// TODO - Currently only a single layer supported per animation -- need to either implement combining of multiple layers or ask the FBX sdk to bake all layers into one
KRAnimationCurve * curve = attribute - > getCurve ( ) ;
KRNode * target = attribute - > getTarget ( ) ;
KRNode : : node_attribute_type attribute_type = attribute - > getTargetAttribute ( ) ;
if ( curve ! = NULL & & target ! = NULL ) {
target - > SetAttribute ( attribute_type , curve - > getValue ( m_local_time + m_start_time ) ) ;
}
2012-12-07 03:13:10 +00:00
}
2022-08-08 01:07:26 -07:00
}
2012-12-07 01:49:17 +00:00
}
void KRAnimation : : Play ( )
{
2022-08-08 01:07:26 -07:00
m_playing = true ;
getContext ( ) . getAnimationManager ( ) - > updateActiveAnimations ( this ) ;
2012-12-07 01:49:17 +00:00
}
void KRAnimation : : Stop ( )
{
2022-08-08 01:07:26 -07:00
m_playing = false ;
getContext ( ) . getAnimationManager ( ) - > updateActiveAnimations ( this ) ;
2012-12-07 01:49:17 +00:00
}
float KRAnimation : : getTime ( )
{
2022-08-08 01:07:26 -07:00
return m_local_time ;
2012-12-07 01:49:17 +00:00
}
void KRAnimation : : setTime ( float time )
{
2022-08-08 01:07:26 -07:00
m_local_time = time ;
2012-12-07 01:49:17 +00:00
}
float KRAnimation : : getDuration ( )
{
2022-08-08 01:07:26 -07:00
return m_duration ;
2012-12-07 01:49:17 +00:00
}
void KRAnimation : : setDuration ( float duration )
{
2022-08-08 01:07:26 -07:00
m_duration = duration ;
2012-12-07 01:49:17 +00:00
}
2013-08-24 16:37:07 -07:00
float KRAnimation : : getStartTime ( )
{
2022-08-08 01:07:26 -07:00
return m_start_time ;
2013-08-24 16:37:07 -07:00
}
void KRAnimation : : setStartTime ( float start_time )
{
2022-08-08 01:07:26 -07:00
m_start_time = start_time ;
2013-08-24 16:37:07 -07:00
}
2012-12-07 01:49:17 +00:00
bool KRAnimation : : isPlaying ( )
{
2022-08-08 01:07:26 -07:00
return m_playing ;
2012-12-07 01:49:17 +00:00
}
2013-05-24 12:20:47 -07:00
bool KRAnimation : : getAutoPlay ( ) const
{
2022-08-08 01:07:26 -07:00
return m_auto_play ;
2013-05-24 12:20:47 -07:00
}
void KRAnimation : : setAutoPlay ( bool auto_play )
{
2022-08-08 01:07:26 -07:00
m_auto_play = auto_play ;
2013-05-24 12:20:47 -07:00
}
bool KRAnimation : : getLooping ( ) const
{
2022-08-08 01:07:26 -07:00
return m_loop ;
2013-05-24 12:20:47 -07:00
}
void KRAnimation : : setLooping ( bool looping )
{
2022-08-08 01:07:26 -07:00
m_loop = looping ;
2013-05-24 12:20:47 -07:00
}
2013-08-24 16:37:07 -07:00
2013-12-09 15:35:07 -08:00
2022-08-08 01:07:26 -07:00
KRAnimation * KRAnimation : : split ( const std : : string & name , float start_time , float duration , bool strip_unchanging_attributes , bool clone_curves )
2013-08-24 16:37:07 -07:00
{
2022-08-08 01:07:26 -07:00
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 < std : : string , KRAnimationLayer * > : : 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 < KRAnimationAttribute * > : : iterator attribute_itr = layer - > getAttributes ( ) . begin ( ) ; attribute_itr ! = layer - > getAttributes ( ) . end ( ) ; attribute_itr + + ) {
KRAnimationAttribute * attribute = * attribute_itr ;
// Updated Dec 9, 2013 by Peter to change the way that attributes are stripped.
//
// If we have been asked to strip_unchanging_attributes then we only want to strip those attributes that don't havechanges
// in any of their components (x, y, z). This means that we have to group the attributes before we check for valueChanges().
// The attributes won't come through in order, but they do come through in group order (each group of 3 arrives as x, y, z)
//
// Since this method isn't designed to handle groups, this is a bit of a hack. We simply take whatever channel is coming
// through and then check the other associated curves.
//
int targetAttribute = attribute - > getTargetAttribute ( ) ;
if ( targetAttribute > 0 ) { // we have a valid target that fits within a group of 3
targetAttribute - - ; // this is now group relative 0,1,2 is the first group .. 3,4,5 is the second group, etc.
KRAnimationCurve * curve = attribute - > getCurve ( ) ; // this is the curve we are currently handling
int placeInGroup = targetAttribute % 3 ; // this will be 0, 1 or 2
static long placeLookup [ ] = { 1 , 2 , - 1 , 1 , - 2 , - 1 } ;
KRAnimationAttribute * attribute2 = * ( attribute_itr + placeLookup [ placeInGroup * 2 ] ) ;
KRAnimationAttribute * attribute3 = * ( attribute_itr + placeLookup [ placeInGroup * 2 + 1 ] ) ;
KRAnimationCurve * curve2 = attribute2 - > getCurve ( ) ;
KRAnimationCurve * curve3 = attribute3 - > getCurve ( ) ;
bool include_attribute = true ;
if ( strip_unchanging_attributes ) {
include_attribute = curve - > valueChanges ( start_time , duration ) |
curve2 - > valueChanges ( start_time , duration ) |
curve3 - > valueChanges ( start_time , duration ) ;
}
if ( include_attribute ) {
KRAnimationAttribute * new_attribute = new KRAnimationAttribute ( getContext ( ) ) ;
KRAnimationCurve * new_curve = curve ;
if ( clone_curves ) {
std : : string new_curve_name = name + " _curve " + std : : to_string ( + + new_curve_count ) ;
new_curve = curve - > split ( new_curve_name , start_time , duration ) ;
}
new_attribute - > setCurveName ( new_curve - > getName ( ) ) ;
new_attribute - > setTargetAttribute ( attribute - > getTargetAttribute ( ) ) ;
new_attribute - > setTargetName ( attribute - > getTargetName ( ) ) ;
new_layer - > addAttribute ( new_attribute ) ;
2013-08-24 16:37:07 -07:00
}
2022-08-08 01:07:26 -07:00
}
2013-08-24 16:37:07 -07:00
}
2022-08-08 01:07:26 -07:00
}
getContext ( ) . getAnimationManager ( ) - > addAnimation ( new_animation ) ;
return new_animation ;
2013-08-24 16:37:07 -07:00
}
void KRAnimation : : deleteCurves ( )
{
2022-08-08 01:07:26 -07:00
for ( unordered_map < std : : string , KRAnimationLayer * > : : iterator layer_itr = m_layers . begin ( ) ; layer_itr ! = m_layers . end ( ) ; layer_itr + + ) {
KRAnimationLayer * layer = ( * layer_itr ) . second ;
for ( std : : vector < KRAnimationAttribute * > : : iterator attribute_itr = layer - > getAttributes ( ) . begin ( ) ; attribute_itr ! = layer - > getAttributes ( ) . end ( ) ; attribute_itr + + ) {
KRAnimationAttribute * attribute = * attribute_itr ;
attribute - > deleteCurve ( ) ;
2013-08-24 16:37:07 -07:00
}
2022-08-08 01:07:26 -07:00
}
2013-08-24 16:37:07 -07:00
}
2013-11-16 02:34:18 -08:00
void KRAnimation : : _lockData ( )
{
2022-08-08 01:07:26 -07:00
for ( unordered_map < std : : string , KRAnimationLayer * > : : iterator layer_itr = m_layers . begin ( ) ; layer_itr ! = m_layers . end ( ) ; layer_itr + + ) {
KRAnimationLayer * layer = ( * layer_itr ) . second ;
for ( std : : vector < KRAnimationAttribute * > : : iterator attribute_itr = layer - > getAttributes ( ) . begin ( ) ; attribute_itr ! = layer - > getAttributes ( ) . end ( ) ; attribute_itr + + ) {
KRAnimationAttribute * attribute = * attribute_itr ;
KRAnimationCurve * curve = attribute - > getCurve ( ) ;
if ( curve ) {
curve - > _lockData ( ) ;
}
2013-11-16 02:34:18 -08:00
}
2022-08-08 01:07:26 -07:00
}
2013-11-16 02:34:18 -08:00
}
void KRAnimation : : _unlockData ( )
{
2022-08-08 01:07:26 -07:00
for ( unordered_map < std : : string , KRAnimationLayer * > : : iterator layer_itr = m_layers . begin ( ) ; layer_itr ! = m_layers . end ( ) ; layer_itr + + ) {
KRAnimationLayer * layer = ( * layer_itr ) . second ;
for ( std : : vector < KRAnimationAttribute * > : : iterator attribute_itr = layer - > getAttributes ( ) . begin ( ) ; attribute_itr ! = layer - > getAttributes ( ) . end ( ) ; attribute_itr + + ) {
KRAnimationAttribute * attribute = * attribute_itr ;
KRAnimationCurve * curve = attribute - > getCurve ( ) ;
if ( curve ) {
curve - > _unlockData ( ) ;
}
2013-11-16 02:34:18 -08:00
}
2022-08-08 01:07:26 -07:00
}
2013-11-16 02:34:18 -08:00
}