diff options
author | AlTheKiller <AlTheKiller@svn> | 2009-09-23 01:49:50 +0000 |
---|---|---|
committer | AlTheKiller <AlTheKiller@svn> | 2009-09-23 01:49:50 +0000 |
commit | 45285e8a9300cd754a760560640b75b09f98035e (patch) | |
tree | ad9f093885ad5c98e9dd4156674e7691c22ed0a2 /guilib/VisibleEffect.cpp |
step 3/4: Move linuxport to trunk. How'd I get roped into this?
git-svn-id: https://xbmc.svn.sourceforge.net/svnroot/xbmc/trunk@23097 568bbfeb-2a22-0410-94d2-cc84cf5bfa90
Diffstat (limited to 'guilib/VisibleEffect.cpp')
-rw-r--r-- | guilib/VisibleEffect.cpp | 703 |
1 files changed, 703 insertions, 0 deletions
diff --git a/guilib/VisibleEffect.cpp b/guilib/VisibleEffect.cpp new file mode 100644 index 0000000000..df48066142 --- /dev/null +++ b/guilib/VisibleEffect.cpp @@ -0,0 +1,703 @@ +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "VisibleEffect.h" +#include "utils/GUIInfoManager.h" +#include "utils/log.h" +#include "SkinInfo.h" // for the effect time adjustments +#include "StringUtils.h" +#include "GUIImage.h" // for FRECT +#include "Tween.h" +#include "tinyXML/tinyxml.h" + +using namespace std; + +CAnimEffect::CAnimEffect(const TiXmlElement *node, EFFECT_TYPE effect) +{ + m_effect = effect; + // defaults + m_delay = m_length = 0; + m_pTweener = NULL; + // time and delay + + float temp; + if (g_SkinInfo.ResolveConstant(node->Attribute("time"), temp)) m_length = (unsigned int)(temp * g_SkinInfo.GetEffectsSlowdown()); + if (g_SkinInfo.ResolveConstant(node->Attribute("delay"), temp)) m_delay = (unsigned int)(temp * g_SkinInfo.GetEffectsSlowdown()); + + const char *tween = node->Attribute("tween"); + if (tween) + { + if (strcmpi(tween, "linear")==0) + m_pTweener = new LinearTweener(); + else if (strcmpi(tween, "quadratic")==0) + m_pTweener = new QuadTweener(); + else if (strcmpi(tween, "cubic")==0) + m_pTweener = new CubicTweener(); + else if (strcmpi(tween, "sine")==0) + m_pTweener = new SineTweener(); + else if (strcmpi(tween, "back")==0) + m_pTweener = new BackTweener(); + else if (strcmpi(tween, "circle")==0) + m_pTweener = new CircleTweener(); + else if (strcmpi(tween, "bounce")==0) + m_pTweener = new BounceTweener(); + else if (strcmpi(tween, "elastic")==0) + m_pTweener = new ElasticTweener(); + + const char *easing = node->Attribute("easing"); + if (m_pTweener && easing) + { + if (strcmpi(easing, "in")==0) + m_pTweener->SetEasing(EASE_IN); + else if (strcmpi(easing, "out")==0) + m_pTweener->SetEasing(EASE_OUT); + else if (strcmpi(easing, "inout")==0) + m_pTweener->SetEasing(EASE_INOUT); + } + } + + float accel; + g_SkinInfo.ResolveConstant(node->Attribute("acceleration"), accel); + + if (!m_pTweener) + { // no tweener is specified - use a linear tweener + // or quadratic if we have acceleration + if (accel) + { + m_pTweener = new QuadTweener(accel); + m_pTweener->SetEasing(EASE_IN); + } + else + m_pTweener = new LinearTweener(); + } +} + +CAnimEffect::CAnimEffect(unsigned int delay, unsigned int length, EFFECT_TYPE effect) +{ + m_delay = delay; + m_length = length; + m_effect = effect; + m_pTweener = new LinearTweener(); +} + +CAnimEffect::~CAnimEffect() +{ + if (m_pTweener) + m_pTweener->Free(); +} + +CAnimEffect::CAnimEffect(const CAnimEffect &src) +{ + m_pTweener = NULL; + *this = src; +} + +const CAnimEffect &CAnimEffect::operator=(const CAnimEffect &src) +{ + if (&src == this) return *this; + + m_matrix = src.m_matrix; + m_effect = src.m_effect; + m_length = src.m_length; + m_delay = src.m_delay; + + if (m_pTweener) + m_pTweener->Free(); + m_pTweener = src.m_pTweener; + if (m_pTweener) + m_pTweener->IncRef(); + return *this; +} + +void CAnimEffect::Calculate(unsigned int time, const CPoint ¢er) +{ + assert(m_delay + m_length); + // calculate offset and tweening + float offset = 0.0f; // delayed forward, or finished reverse + if (time >= m_delay && time < m_delay + m_length) + offset = (float)(time - m_delay) / m_length; + else if (time >= m_delay + m_length) + offset = 1.0f; + if (m_pTweener) + offset = m_pTweener->Tween(offset, 0.0f, 1.0f, 1.0f); + // and apply the effect + ApplyEffect(offset, center); +} + +void CAnimEffect::ApplyState(ANIMATION_STATE state, const CPoint ¢er) +{ + float offset = (state == ANIM_STATE_APPLIED) ? 1.0f : 0.0f; + ApplyEffect(offset, center); +} + +CFadeEffect::CFadeEffect(const TiXmlElement *node, bool reverseDefaults) : CAnimEffect(node, EFFECT_TYPE_FADE) +{ + if (reverseDefaults) + { // out effect defaults + m_startAlpha = 100.0f; + m_endAlpha = 0; + } + else + { // in effect defaults + m_startAlpha = 0; + m_endAlpha = 100.0f; + } + if (node->Attribute("start")) g_SkinInfo.ResolveConstant(node->Attribute("start"), m_startAlpha); + if (node->Attribute("end")) g_SkinInfo.ResolveConstant(node->Attribute("end"), m_endAlpha); + if (m_startAlpha > 100.0f) m_startAlpha = 100.0f; + if (m_endAlpha > 100.0f) m_endAlpha = 100.0f; + if (m_startAlpha < 0) m_startAlpha = 0; + if (m_endAlpha < 0) m_endAlpha = 0; +} + +CFadeEffect::CFadeEffect(float start, float end, unsigned int delay, unsigned int length) : CAnimEffect(delay, length, EFFECT_TYPE_FADE) +{ + m_startAlpha = start; + m_endAlpha = end; +} + +void CFadeEffect::ApplyEffect(float offset, const CPoint ¢er) +{ + m_matrix.SetFader(((m_endAlpha - m_startAlpha) * offset + m_startAlpha) * 0.01f); +} + +CSlideEffect::CSlideEffect(const TiXmlElement *node) : CAnimEffect(node, EFFECT_TYPE_SLIDE) +{ + m_startX = m_endX = 0; + m_startY = m_endY = 0; + const char *startPos = node->Attribute("start"); + if (startPos) + { + vector<CStdString> commaSeparated; + StringUtils::SplitString(startPos, ",", commaSeparated); + if (commaSeparated.size() > 1) + g_SkinInfo.ResolveConstant(commaSeparated[1], m_startY); + g_SkinInfo.ResolveConstant(commaSeparated[0], m_startX); + } + const char *endPos = node->Attribute("end"); + if (endPos) + { + vector<CStdString> commaSeparated; + StringUtils::SplitString(endPos, ",", commaSeparated); + if (commaSeparated.size() > 1) + g_SkinInfo.ResolveConstant(commaSeparated[1], m_endY); + g_SkinInfo.ResolveConstant(commaSeparated[0], m_endX); + } +} + +void CSlideEffect::ApplyEffect(float offset, const CPoint ¢er) +{ + m_matrix.SetTranslation((m_endX - m_startX)*offset + m_startX, (m_endY - m_startY)*offset + m_startY, 0); +} + +CRotateEffect::CRotateEffect(const TiXmlElement *node, EFFECT_TYPE effect) : CAnimEffect(node, effect) +{ + m_startAngle = m_endAngle = 0; + m_autoCenter = false; + if (node->Attribute("start")) g_SkinInfo.ResolveConstant(node->Attribute("start"), m_startAngle); + if (node->Attribute("end")) g_SkinInfo.ResolveConstant(node->Attribute("end"), m_endAngle); + + // convert to a negative to account for our reversed Y axis (Needed for X and Z ???) + m_startAngle *= -1; + m_endAngle *= -1; + + const char *centerPos = node->Attribute("center"); + if (centerPos) + { + if (strcmpi(centerPos, "auto") == 0) + m_autoCenter = true; + else + { + vector<CStdString> commaSeparated; + StringUtils::SplitString(centerPos, ",", commaSeparated); + if (commaSeparated.size() > 1) + g_SkinInfo.ResolveConstant(commaSeparated[1], m_center.y); + g_SkinInfo.ResolveConstant(commaSeparated[0], m_center.x); + } + } +} + +void CRotateEffect::ApplyEffect(float offset, const CPoint ¢er) +{ + static const float degree_to_radian = 0.01745329252f; + if (m_autoCenter) + m_center = center; + if (m_effect == EFFECT_TYPE_ROTATE_X) + m_matrix.SetXRotation(((m_endAngle - m_startAngle)*offset + m_startAngle) * degree_to_radian, m_center.x, m_center.y, 1.0f); + else if (m_effect == EFFECT_TYPE_ROTATE_Y) + m_matrix.SetYRotation(((m_endAngle - m_startAngle)*offset + m_startAngle) * degree_to_radian, m_center.x, m_center.y, 1.0f); + else if (m_effect == EFFECT_TYPE_ROTATE_Z) // note coordinate aspect ratio is not generally square in the XY plane, so correct for it. + m_matrix.SetZRotation(((m_endAngle - m_startAngle)*offset + m_startAngle) * degree_to_radian, m_center.x, m_center.y, g_graphicsContext.GetScalingPixelRatio()); +} + +CZoomEffect::CZoomEffect(const TiXmlElement *node, const FRECT &rect) : CAnimEffect(node, EFFECT_TYPE_ZOOM) +{ + // effect defaults + m_startX = m_startY = 100; + m_endX = m_endY = 100; + m_center = CPoint(0,0); + m_autoCenter = false; + + float startPosX = rect.left; + float startPosY = rect.top; + float endPosX = rect.left; + float endPosY = rect.top; + + float width = (rect.right) ? rect.right : 0.001f; + float height = (rect.bottom) ? rect.bottom : 0.001f; + + const char *start = node->Attribute("start"); + if (start) + { + CStdStringArray params; + StringUtils::SplitString(start, ",", params); + if (params.size() == 1) + { + g_SkinInfo.ResolveConstant(params[0], m_startX); + m_startY = m_startX; + } + else if (params.size() == 2) + { + g_SkinInfo.ResolveConstant(params[0], m_startX); + g_SkinInfo.ResolveConstant(params[1], m_startY); + } + else if (params.size() == 4) + { // format is start="x,y,width,height" + // use width and height from our rect to calculate our sizing + g_SkinInfo.ResolveConstant(params[0], startPosX); + g_SkinInfo.ResolveConstant(params[1], startPosY); + g_SkinInfo.ResolveConstant(params[2], m_startX); + g_SkinInfo.ResolveConstant(params[3], m_startY); + m_startX *= 100.0f / width; + m_startY *= 100.0f / height; + } + } + const char *end = node->Attribute("end"); + if (end) + { + CStdStringArray params; + StringUtils::SplitString(end, ",", params); + if (params.size() == 1) + { + g_SkinInfo.ResolveConstant(params[0], m_endX); + m_endY = m_endX; + } + else if (params.size() == 2) + { + g_SkinInfo.ResolveConstant(params[0], m_endX); + g_SkinInfo.ResolveConstant(params[1], m_endY); + } + else if (params.size() == 4) + { // format is start="x,y,width,height" + // use width and height from our rect to calculate our sizing + g_SkinInfo.ResolveConstant(params[0], endPosX); + g_SkinInfo.ResolveConstant(params[1], endPosY); + g_SkinInfo.ResolveConstant(params[2], m_endX); + g_SkinInfo.ResolveConstant(params[3], m_endY); + m_endX *= 100.0f / width; + m_endY *= 100.0f / height; + } + } + const char *centerPos = node->Attribute("center"); + if (centerPos) + { + if (strcmpi(centerPos, "auto") == 0) + m_autoCenter = true; + else + { + vector<CStdString> commaSeparated; + StringUtils::SplitString(centerPos, ",", commaSeparated); + if (commaSeparated.size() > 1) + g_SkinInfo.ResolveConstant(commaSeparated[1], m_center.y); + g_SkinInfo.ResolveConstant(commaSeparated[0], m_center.x); + } + } + else + { // no center specified + // calculate the center position... + if (m_startX) + { + float scale = m_endX / m_startX; + if (scale != 1) + m_center.x = (endPosX - scale*startPosX) / (1 - scale); + } + if (m_startY) + { + float scale = m_endY / m_startY; + if (scale != 1) + m_center.y = (endPosY - scale*startPosY) / (1 - scale); + } + } +} + +void CZoomEffect::ApplyEffect(float offset, const CPoint ¢er) +{ + if (m_autoCenter) + m_center = center; + float scaleX = ((m_endX - m_startX)*offset + m_startX) * 0.01f; + float scaleY = ((m_endY - m_startY)*offset + m_startY) * 0.01f; + m_matrix.SetScaler(scaleX, scaleY, m_center.x, m_center.y); +} + +CAnimation::CAnimation() +{ + m_type = ANIM_TYPE_NONE; + m_reversible = true; + m_condition = 0; + m_repeatAnim = ANIM_REPEAT_NONE; + m_currentState = ANIM_STATE_NONE; + m_currentProcess = ANIM_PROCESS_NONE; + m_queuedProcess = ANIM_PROCESS_NONE; + m_lastCondition = false; + m_length = 0; + m_delay = 0; + m_start = 0; + m_amount = 0; +} + +CAnimation::CAnimation(const CAnimation &src) +{ + *this = src; +} + +CAnimation::~CAnimation() +{ + for (unsigned int i = 0; i < m_effects.size(); i++) + delete m_effects[i]; + m_effects.clear(); +} + +const CAnimation &CAnimation::operator =(const CAnimation &src) +{ + if (this == &src) return *this; // same + m_type = src.m_type; + m_reversible = src.m_reversible; + m_condition = src.m_condition; + m_repeatAnim = src.m_repeatAnim; + m_lastCondition = src.m_lastCondition; + m_queuedProcess = src.m_queuedProcess; + m_currentProcess = src.m_currentProcess; + m_currentState = src.m_currentState; + m_start = src.m_start; + m_length = src.m_length; + m_delay = src.m_delay; + m_amount = src.m_amount; + // clear all our effects + for (unsigned int i = 0; i < m_effects.size(); i++) + delete m_effects[i]; + m_effects.clear(); + // and assign the others across + for (unsigned int i = 0; i < src.m_effects.size(); i++) + { + CAnimEffect *newEffect = NULL; + if (src.m_effects[i]->GetType() == CAnimEffect::EFFECT_TYPE_FADE) + newEffect = new CFadeEffect(*(CFadeEffect *)src.m_effects[i]); + else if (src.m_effects[i]->GetType() == CAnimEffect::EFFECT_TYPE_ZOOM) + newEffect = new CZoomEffect(*(CZoomEffect *)src.m_effects[i]); + else if (src.m_effects[i]->GetType() == CAnimEffect::EFFECT_TYPE_SLIDE) + newEffect = new CSlideEffect(*(CSlideEffect *)src.m_effects[i]); + else if (src.m_effects[i]->GetType() == CAnimEffect::EFFECT_TYPE_ROTATE_X || + src.m_effects[i]->GetType() == CAnimEffect::EFFECT_TYPE_ROTATE_Y || + src.m_effects[i]->GetType() == CAnimEffect::EFFECT_TYPE_ROTATE_Z) + newEffect = new CRotateEffect(*(CRotateEffect *)src.m_effects[i]); + if (newEffect) + m_effects.push_back(newEffect); + } + return *this; +} + +void CAnimation::Animate(unsigned int time, bool startAnim) +{ + // First start any queued animations + if (m_queuedProcess == ANIM_PROCESS_NORMAL) + { + if (m_currentProcess == ANIM_PROCESS_REVERSE) + m_start = time - m_amount; // reverse direction of animation + else + m_start = time; + m_currentProcess = ANIM_PROCESS_NORMAL; + } + else if (m_queuedProcess == ANIM_PROCESS_REVERSE) + { + if (m_currentProcess == ANIM_PROCESS_NORMAL) + m_start = time - (m_length - m_amount); // reverse direction of animation + else if (m_currentProcess == ANIM_PROCESS_NONE) + m_start = time; + m_currentProcess = ANIM_PROCESS_REVERSE; + } + // reset the queued state once we've rendered to ensure allocation has occured + if (startAnim || m_queuedProcess == ANIM_PROCESS_REVERSE) + m_queuedProcess = ANIM_PROCESS_NONE; + + // Update our animation process + if (m_currentProcess == ANIM_PROCESS_NORMAL) + { + if (time - m_start < m_delay) + { + m_amount = 0; + m_currentState = ANIM_STATE_DELAYED; + } + else if (time - m_start < m_length + m_delay) + { + m_amount = time - m_start - m_delay; + m_currentState = ANIM_STATE_IN_PROCESS; + } + else + { + m_amount = m_length; + if (m_repeatAnim == ANIM_REPEAT_PULSE && m_lastCondition) + { // pulsed anims auto-reverse + m_currentProcess = ANIM_PROCESS_REVERSE; + m_start = time; + } + else if (m_repeatAnim == ANIM_REPEAT_LOOP && m_lastCondition) + { // looped anims start over + m_amount = 0; + m_start = time; + } + else + m_currentState = ANIM_STATE_APPLIED; + } + } + else if (m_currentProcess == ANIM_PROCESS_REVERSE) + { + if (time - m_start < m_length) + { + m_amount = m_length - (time - m_start); + m_currentState = ANIM_STATE_IN_PROCESS; + } + else + { + m_amount = 0; + if (m_repeatAnim == ANIM_REPEAT_PULSE && m_lastCondition) + { // pulsed anims auto-reverse + m_currentProcess = ANIM_PROCESS_NORMAL; + m_start = time; + } + else + m_currentState = ANIM_STATE_APPLIED; + } + } +} + +void CAnimation::ResetAnimation() +{ + m_queuedProcess = ANIM_PROCESS_NONE; + m_currentProcess = ANIM_PROCESS_NONE; + m_currentState = ANIM_STATE_NONE; +} + +void CAnimation::ApplyAnimation() +{ + m_queuedProcess = ANIM_PROCESS_NONE; + if (m_repeatAnim == ANIM_REPEAT_PULSE) + { // pulsed anims auto-reverse + m_amount = m_length; + m_currentProcess = ANIM_PROCESS_REVERSE; + m_currentState = ANIM_STATE_IN_PROCESS; + } + else if (m_repeatAnim == ANIM_REPEAT_LOOP) + { // looped anims start over + m_amount = 0; + m_currentProcess = ANIM_PROCESS_NORMAL; + m_currentState = ANIM_STATE_IN_PROCESS; + } + else + { // set normal process, so that Calculate() knows that we're finishing for zero length effects + // it will be reset in RenderAnimation() + m_currentProcess = ANIM_PROCESS_NORMAL; + m_currentState = ANIM_STATE_APPLIED; + m_amount = m_length; + } + Calculate(CPoint()); +} + +void CAnimation::Calculate(const CPoint ¢er) +{ + for (unsigned int i = 0; i < m_effects.size(); i++) + { + CAnimEffect *effect = m_effects[i]; + if (effect->GetLength()) + effect->Calculate(m_delay + m_amount, center); + else + { // effect has length zero, so either apply complete + if (m_currentProcess == ANIM_PROCESS_NORMAL) + effect->ApplyState(ANIM_STATE_APPLIED, center); + else + effect->ApplyState(ANIM_STATE_NONE, center); + } + } +} + +void CAnimation::RenderAnimation(TransformMatrix &matrix, const CPoint ¢er) +{ + if (m_currentProcess != ANIM_PROCESS_NONE) + Calculate(center); + // If we have finished an animation, reset the animation state + // We do this here (rather than in Animate()) as we need the + // currentProcess information in the UpdateStates() function of the + // window and control classes. + if (m_currentState == ANIM_STATE_APPLIED) + { + m_currentProcess = ANIM_PROCESS_NONE; + m_queuedProcess = ANIM_PROCESS_NONE; + } + if (m_currentState != ANIM_STATE_NONE) + { + for (unsigned int i = 0; i < m_effects.size(); i++) + matrix *= m_effects[i]->GetTransform(); + } +} + +void CAnimation::QueueAnimation(ANIMATION_PROCESS process) +{ + m_queuedProcess = process; +} + +CAnimation *CAnimation::CreateFader(float start, float end, unsigned int delay, unsigned int length) +{ + CAnimation *anim = new CAnimation(); + if (anim) + { + CFadeEffect *effect = new CFadeEffect(start, end, delay, length); + if (effect) + anim->AddEffect(effect); + } + return anim; +} + +void CAnimation::UpdateCondition(int contextWindow, const CGUIListItem *item) +{ + bool condition = g_infoManager.GetBool(m_condition, contextWindow, item); + if (condition && !m_lastCondition) + QueueAnimation(ANIM_PROCESS_NORMAL); + else if (!condition && m_lastCondition) + { + if (m_reversible) + QueueAnimation(ANIM_PROCESS_REVERSE); + else + ResetAnimation(); + } + m_lastCondition = condition; +} + +void CAnimation::SetInitialCondition(int contextWindow) +{ + m_lastCondition = g_infoManager.GetBool(m_condition, contextWindow); + if (m_lastCondition) + ApplyAnimation(); + else + ResetAnimation(); +} + +void CAnimation::Create(const TiXmlElement *node, const FRECT &rect) +{ + if (!node || !node->FirstChild()) + return; + + // conditions and reversibility + const char *condition = node->Attribute("condition"); + if (condition) + m_condition = g_infoManager.TranslateString(condition); + const char *reverse = node->Attribute("reversible"); + if (reverse && strcmpi(reverse, "false") == 0) + m_reversible = false; + + const TiXmlElement *effect = node->FirstChildElement("effect"); + + CStdString type = node->FirstChild()->Value(); + m_type = ANIM_TYPE_CONDITIONAL; + if (effect) // new layout + type = node->Attribute("type"); + + if (type.Left(7).Equals("visible")) m_type = ANIM_TYPE_VISIBLE; + else if (type.Equals("hidden")) m_type = ANIM_TYPE_HIDDEN; + else if (type.Equals("focus")) m_type = ANIM_TYPE_FOCUS; + else if (type.Equals("unfocus")) m_type = ANIM_TYPE_UNFOCUS; + else if (type.Equals("windowopen")) m_type = ANIM_TYPE_WINDOW_OPEN; + else if (type.Equals("windowclose")) m_type = ANIM_TYPE_WINDOW_CLOSE; + // sanity check + if (m_type == ANIM_TYPE_CONDITIONAL) + { + if (!m_condition) + { + CLog::Log(LOGERROR, "Control has invalid animation type (no condition or no type)"); + return; + } + + // pulsed or loop animations + const char *pulse = node->Attribute("pulse"); + if (pulse && strcmpi(pulse, "true") == 0) + m_repeatAnim = ANIM_REPEAT_PULSE; + const char *loop = node->Attribute("loop"); + if (loop && strcmpi(loop, "true") == 0) + m_repeatAnim = ANIM_REPEAT_LOOP; + } + + m_delay = 0xffffffff; + if (!effect) + { // old layout: + // <animation effect="fade" start="0" end="100" delay="10" time="2000" condition="blahdiblah" reversible="false">focus</animation> + CStdString type = node->Attribute("effect"); + AddEffect(type, node, rect); + } + while (effect) + { // new layout: + // <animation type="focus" condition="blahdiblah" reversible="false"> + // <effect type="fade" start="0" end="100" delay="10" time="2000" /> + // ... + // </animation> + CStdString type = effect->Attribute("type"); + AddEffect(type, effect, rect); + effect = effect->NextSiblingElement("effect"); + } +} + +void CAnimation::AddEffect(const CStdString &type, const TiXmlElement *node, const FRECT &rect) +{ + CAnimEffect *effect = NULL; + if (type.Equals("fade")) + effect = new CFadeEffect(node, m_type < 0); + else if (type.Equals("slide")) + effect = new CSlideEffect(node); + else if (type.Equals("rotate")) + effect = new CRotateEffect(node, CAnimEffect::EFFECT_TYPE_ROTATE_Z); + else if (type.Equals("rotatey")) + effect = new CRotateEffect(node, CAnimEffect::EFFECT_TYPE_ROTATE_Y); + else if (type.Equals("rotatex")) + effect = new CRotateEffect(node, CAnimEffect::EFFECT_TYPE_ROTATE_X); + else if (type.Equals("zoom")) + effect = new CZoomEffect(node, rect); + + if (effect) + AddEffect(effect); +} + +void CAnimation::AddEffect(CAnimEffect *effect) +{ + m_effects.push_back(effect); + // our delay is the minimum of all the effect delays + if (effect->GetDelay() < m_delay) + m_delay = effect->GetDelay(); + // our length is the maximum of all the effect lengths + if (effect->GetLength() > m_delay + m_length) + m_length = effect->GetLength() - m_delay; +} |