📄 animsand.cpp
字号:
UINT32 ulNewSD = m_pElement->m_ulSimpleDuration;
if (m_pElement->m_bAutoReverse)
{
ulNewSD *= 2;
}
// Now we can compute the remainder time
if (ulNewSD)
{
ulModTime = ulNewAD % ulNewSD;
}
// Now, our active duration an even multiple of simple duration?
if (ulModTime)
{
// Active duration is NOT an even multiple of simple duration,
// so we just evaluate the cumulative animation function
// at the end of the active duration. Make sure
// and pass the time through time manipulations.
UINT32 ulADTM = ComputeFilteredSimpleTime(m_ulActiveDuration);
cRet = CumulativeAnimationFunction(ulADTM, pUnder, pDepend);
}
else
{
// Active duration IS an even multiple of simple duration
//
// Are we cumulative or not?
if (m_pElement->m_ucAccumulate == kAccumulateNone)
{
// We are non-cumulative - simply evaluate at the
// simple duration. First pass the simple duration
// through time manipulations
UINT32 ulSD = m_pElement->m_ulSimpleDuration;
if (m_pElement->m_bAutoReverse)
{
ulSD *= 2;
}
if (m_pElement->m_dSpeed != 1.0 &&
m_pElement->m_dSpeed != 0.0)
{
double dSDSpeed = (double) ulSD / fabs(m_pElement->m_dSpeed);
ulSD = (UINT32) floor(dSDSpeed + 0.5);
}
UINT32 ulSDTM = ComputeFilteredSimpleTime(ulSD);
cRet = SimpleAnimationFunction(ulSDTM, pUnder, pDepend);
}
else
{
// We ARE cumulative
//
// Compute the multiple
UINT32 ulMult = 1;
UINT32 ulCumTime = 0;
if (m_pElement->m_ulSimpleDuration)
{
if (m_pElement->m_bAutoReverse)
{
ulMult = m_ulActiveDuration / (2 * m_pElement->m_ulSimpleDuration);
ulCumTime = 2 * m_pElement->m_ulSimpleDuration * (ulMult - 1);
}
else
{
ulMult = m_ulActiveDuration / m_pElement->m_ulSimpleDuration;
ulCumTime = m_pElement->m_ulSimpleDuration * (ulMult - 1);
}
}
// Compute the frozen value
UINT32 ulCumTimeTM = ComputeFilteredSimpleTime(ulCumTime);
CAttr cCum = CumulativeAnimationFunction(ulCumTimeTM, pUnder, pDepend);
UINT32 ulSDTM = 0;
if (m_pElement->m_bAutoReverse)
{
ulSDTM = ComputeFilteredSimpleTime(2 * m_pElement->m_ulSimpleDuration);
}
else
{
ulSDTM = ComputeFilteredSimpleTime(m_pElement->m_ulSimpleDuration);
}
cRet = SimpleAnimationFunction(ulSDTM, pUnder, pDepend);
cRet.Add(&cCum, pDepend);
}
}
// Save the last time
m_ulLastTime = ulTM;
}
}
return cRet;
}
BOOL CAnimationSandwichLayer::HigherPriority(CAnimationSandwichLayer* pLayer)
{
BOOL bRet = TRUE;
if (pLayer)
{
if (m_ulDelay > pLayer->m_ulDelay)
{
// We start later than pLayer, so we're higher priority
bRet = TRUE;
}
else if (m_ulDelay == pLayer->m_ulDelay)
{
// We start at the same time as pLayer, so the spec
// says we first have to look at sync relationships
if (m_pElement->m_BeginEventSourceID == pLayer->m_pElement->m_pNode->m_id)
{
// pLayer is our syncbase, so we are higher priority
bRet = TRUE;
}
else if (pLayer->m_pElement->m_BeginEventSourceID == m_pElement->m_pNode->m_id)
{
// We are pLayer's syncbase, so pLayer is higher priority
bRet = FALSE;
}
else
{
// There is no sync relationship between us and pLayer,
// so we have to look at lexical order. First look at
// the line the tag starts
if (m_pElement->m_pNode->m_ulTagStartLine >
pLayer->m_pElement->m_pNode->m_ulTagStartLine)
{
// We start lexically later, so we are
// higher priority
bRet = TRUE;
}
else if (m_pElement->m_pNode->m_ulTagStartLine ==
pLayer->m_pElement->m_pNode->m_ulTagStartLine)
{
// We start on the same line, so look
// at the starting column
if (m_pElement->m_pNode->m_ulTagStartColumn >
pLayer->m_pElement->m_pNode->m_ulTagStartColumn)
{
// We start lexically later, so we are
// higher priority
bRet = TRUE;
}
else if (m_pElement->m_pNode->m_ulTagStartColumn ==
pLayer->m_pElement->m_pNode->m_ulTagStartColumn)
{
// Huh? How can a different element start at
// the same line and column that we do? Probably
// bogus, so make an arbitrary choice
bRet = TRUE;
}
else
{
// We start lexically earlier, so we are NOT
// higher priority
bRet = FALSE;
}
}
else
{
// We start lexically earlier, so we are NOT
// higher priority
bRet = FALSE;
}
}
}
else
{
// pLayer starts later than us, so it's higher priority
bRet = FALSE;
}
}
return bRet;
}
void CAnimationSandwichLayer::AdjustActiveDuration(UINT32 ulTime)
{
if (ulTime >= m_ulDelay)
{
m_ulActiveDuration = ulTime - m_ulDelay;
}
}
CAttr CAnimationSandwichLayer::SimpleAnimationFunction(UINT32 ulTime,
CAttr* pUnder,
CAttr* pDepend)
{
CAttr cRet;
if (pUnder)
{
// Initialize the return to the underlying value
cRet = *pUnder;
// Do we have an indefinite simple duration?
if (m_pElement->m_bIndefiniteSimpleDuration)
{
// Our simple duration is indefinite, so interpolation
// is not defined. We should set ourselves to value(0).
//
// What kind of animation are we?
if (m_pElement->m_pNode->m_tag == SMILSet)
{
// If this is a set, then we know there is
// only one values, so we need to just
// set the value to m_ppValue[1]
if (m_pElement->m_ppValue[1])
{
cRet = *m_pElement->m_ppValue[1];
}
}
else if (m_pElement->m_ucAnimationType == kAnimTypeTo)
{
// If this is a to-animation, then value(0)
// is the underlying value.
cRet = *pUnder;
}
else
{
// Assign the value(0) if we have one
if (m_pElement->m_ppValue[0])
{
cRet = *m_pElement->m_ppValue[0];
}
}
}
else
{
// Our simple duration is not indefinite
//
// We are just defined over the simple duration
if (ulTime <= m_pElement->m_ulSimpleDuration)
{
if (m_pElement->m_pNode->m_tag == SMILSet)
{
// If this is a set, then we know there is
// only two values, so we need to just
// set the value to m_ppValue[1]
if (m_pElement->m_ppValue[1])
{
cRet = *m_pElement->m_ppValue[1];
}
}
else
{
// What is our calcmode?
if (m_pElement->m_ucCalcMode == kCalcModeDiscrete)
{
// Divide the interval into m_ulNumValues segments
UINT32 ulIndex = m_pElement->m_ulNumValues;
if (m_pElement->m_ulSimpleDuration)
{
ulIndex = m_pElement->m_ulNumValues * ulTime / m_pElement->m_ulSimpleDuration;
}
// Make sure that m_pElement->m_ulSimpleDuration maps
// to index m_ulNumValues - 1 and not m_ulNumValues
if (ulIndex >= m_pElement->m_ulNumValues)
{
ulIndex = m_pElement->m_ulNumValues - 1;
}
// If we are a "to" animation, then m_ppValue[0] is
// a placeholder for the underlying value. Therefore,
// if we are a "to" animation and have selected index 0,
// then we need to replace it by the underlying value
if (m_pElement->m_ucAnimationType == kAnimTypeTo &&
ulIndex == 0)
{
cRet = *pUnder;
}
else if (m_pElement->m_ucAnimationType == kAnimTypeFromBy &&
ulIndex == 1)
{
// On a from-by animation, you are interpolating
// between the from value and the sum of the from
// and by values. m_ppValue[0] is the from value.
// However, m_ppValue[1] is the by value, not the
// sum of the from and by values. So if we have
// chosen index 1, then we need to compute the sum
// of the from and by values
//
if (m_pElement->m_ppValue[0] &&
m_pElement->m_ppValue[1])
{
// First assign the from value
cRet = *m_pElement->m_ppValue[0];
// Then add the by value
cRet.Add(m_pElement->m_ppValue[1], pDepend);
}
}
else
{
// Simply return the proper value
if (m_pElement->m_ppValue[ulIndex])
{
cRet = *m_pElement->m_ppValue[ulIndex];
}
}
}
else if (m_pElement->m_ucCalcMode == kCalcModeLinear ||
(m_pElement->m_ucCalcMode == kCalcModePaced &&
m_pElement->m_ulNumValues == 2))
{
// Is this a "to" animation?
if (m_pElement->m_ucAnimationType == kAnimTypeTo)
{
// If we are a "to" animation, then we interpolate
// between the underlying value and the "to" value,
// which is (m_ppValue[1]).
if (m_pElement->m_ppValue[1])
{
// Do the interpolation
double t1 = 0.0;
double t2 = (double) m_pElement->m_ulSimpleDuration;
double t = ulTime;
cRet.Interp(pUnder, t1, m_pElement->m_ppValue[1], t2, t, pDepend);
}
}
else if (m_pElement->m_ucAnimationType == kAnimTypeFromBy)
{
// On a from-by animation, you are interpolating
// between the from value and the sum of the from
// and by values. m_ppValue[0] is the from value.
// However, m_ppValue[1] is the by value, not the
// sum of the from and by values. So we need to
// compute the sum of the from and by values
if (m_pElement->m_ppValue[0] &&
m_pElement->m_ppValue[1])
{
CAttr cSum = *m_pElement->m_ppValue[0];
cSum.Add(m_pElement->m_ppValue[1], pDepend);
// Then we interpolate between m_ppValue[0] (the
// "from" value) and cSum (the sum of the "from"
// and "by" values).
double t1 = 0.0;
double t2 = (double) m_pElement->m_ulSimpleDuration;
double t = (double) ulTime;
cRet.Interp(m_pElement->m_ppValue[0], t1, &cSum, t2, t, pDepend);
}
}
else
{
// Divide the interval into m_ulNumValues-1 segments
UINT32 ulIndex = m_pElement->m_ulNumValues - 1;
if (m_pElement->m_ulSimpleDuration)
{
ulIndex = (m_pElement->m_ulNumValues - 1) * ulTime / m_pElement->m_ulSimpleDuration;
}
// Now interpolate between this value and the next
if (ulIndex + 1 < m_pElement->m_ulNumValues &&
m_pElement->m_ppValue[ulIndex] &&
m_pElement->m_ppValue[ulIndex + 1])
{
// Do the interpolation
double t1 = ulIndex * m_pElement->m_ulSimpleDuration /
(m_pElement->m_ulNumValues - 1);
double t2 = (ulIndex + 1) * m_pElement->m_ulSimpleDuration /
(m_pElement->m_ulNumValues - 1);
double t = ulTime;
cRet.Interp(m_pElement->m_ppValue[ulIndex], t1,
m_pElement->m_ppValue[ulIndex + 1], t2,
t, pDepend);
}
else
{
// The only way this can happen is if
// ulTime == m_pElement->m_ulSimpleDuration, so if this
// if the case, we need to return the un-interpolated
// value of m_ppValue[m_pElement->m_ulNumValues - 1]
if (m_pElement->m_ppValue[m_pElement->m_ulNumValues - 1])
{
cRet = *m_pElement->m_ppValue[m_pElement->m_ulNumValues - 1];
}
}
}
}
else if (m_pElement->m_ucCalcMode == kCalcModePaced)
{
// If we need to recompute the paced tables,
// then do it now
if (m_bRecomputePace ||
(!m_bRecomputePace && m_bFirstTime))
{
RecomputePace(pDepend);
}
// Find out what index we're at
double t = (double) ulTime;
UINT32 i = 0;
for (i = 0; i < m_pElement->m_ulNumValues - 1; i++)
{
if (t >= m_pdPacedTime[i] && t <= m_pdPacedTime[i + 1])
{
break;
}
}
if (i + 1 < m_pElement->m_ulNumValues)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -