📄 animsand.cpp
字号:
{
HX_ASSERT(FALSE && "Illegal input parameters in ComputeBezierOutputTime()");
}
return dRet;
}
double CAnimationSandwichLayer::SolveForBezierT(double x, double x1,
double x2, double tol)
{
double dRet = 0.0;
if (x >= 0.0 && x <= 1.0 &&
x1 >= 0.0 && x1 <= 1.0 &&
x2 >= 0.0 && x2 <= 1.0 &&
tol > 0.0 && tol <= 1.0)
{
double tL = 0.0;
double xL = 0.0;
double tR = 1.0;
double xR = 1.0;
double tM = 0.5;
double xM = ComputeBezier(tM, x1, x2);
UINT32 i = 0;
while (fabs(xM - x) > tol &&
i < BEZIER_MAX_ITERATIONS)
{
// Is our computed mid-point smaller or
// larger than our desired value?
if (xM > x)
{
// Take the left-hand interval
tR = tM;
}
else
{
// Take the right-hand interval
tL = tM;
}
// Compute new mid-point
tM = (tL + tR) / 2.0;
// Compute new value
xM = ComputeBezier(tM, x1, x2);
// Increment the iteration count
++i;
}
// Set the return value
dRet = tM;
// Check if we blew our max iteration count
if (i >= BEZIER_MAX_ITERATIONS)
{
HX_ASSERT(FALSE && "SolveForBezierT(): Could not get within tolerance in max iterations");
}
}
else
{
HX_ASSERT(FALSE && "Illegal input parameters in SolveForBezierT()");
}
return dRet;
}
double CAnimationSandwichLayer::ComputeBezier(double t, double a1, double a2)
{
double dRet = 0.0;
if (t >= 0.0 && t <= 1.0 &&
a1 >= 0.0 && a1 <= 1.0 &&
a2 >= 0.0 && a2 <= 1.0)
{
double t2 = t * t;
double t3 = t2 * t;
double ti = 1.0 - t;
double ti2 = ti * ti;
dRet = 3.0 * t * ti2 * a1 +
3.0 * t2 * ti * a2 +
t3;
}
else
{
HX_ASSERT(FALSE && "Illegal input parameters in ComputeBezier()");
}
return dRet;
}
#endif // #if defined(XXXMEH_SPLINE_ANIMATION)
CAnimationSandwich::CAnimationSandwich(const char* pszTargetElementID,
SMILNodeTag eTargetElementTag,
UINT32 ulAttrName)
{
MLOG_LEAKCHECK("CON CAnimationSandwich this=0x%08x\n", this);
m_pTargetElementID = new CHXString(pszTargetElementID);
m_eTargetElementTag = eTargetElementTag;
m_ulAttrName = ulAttrName;
m_pLayerList = NULL;
}
CAnimationSandwich::~CAnimationSandwich()
{
MLOG_LEAKCHECK("DES CAnimationSandwich this=0x%08x\n", this);
ClearAllLayers();
HX_DELETE(m_pTargetElementID);
HX_DELETE(m_pLayerList);
}
void CAnimationSandwich::ClearAllLayers()
{
if (m_pLayerList)
{
LISTPOSITION pos = m_pLayerList->GetHeadPosition();
while (pos)
{
CAnimationSandwichLayer* pLayer = (CAnimationSandwichLayer*) m_pLayerList->GetNext(pos);
HX_DELETE(pLayer);
}
m_pLayerList->RemoveAll();
}
}
const char* CAnimationSandwich::GetTargetElementID() const
{
const char* pRet = NULL;
if (m_pTargetElementID)
{
pRet = (const char*) *m_pTargetElementID;
}
return pRet;
}
HX_RESULT CAnimationSandwich::AddLayer(CAnimationSandwichLayer* pLayer)
{
HX_RESULT retVal = HXR_OK;
if (pLayer)
{
if (!m_pLayerList)
{
m_pLayerList = new CHXSimpleList();
}
if (m_pLayerList)
{
BOOL bAdded = FALSE;
LISTPOSITION pos = m_pLayerList->GetHeadPosition();
while (pos)
{
CAnimationSandwichLayer* pListLayer = (CAnimationSandwichLayer*) m_pLayerList->GetAt(pos);
if (pListLayer->HigherPriority(pLayer))
{
// The current layer in the list is higher priority
// than the layer we want to add, so we must insert
// ourselves BEFORE this layer
m_pLayerList->InsertBefore(pos, (void*) pLayer);
// Set the flag
bAdded = TRUE;
// Now jump out of the loop
break;
}
m_pLayerList->GetNext(pos);
}
// If we didn't add ourselves, then that
// means we are the highest priority, so
// add ourselves to the tail of the list
if (!bAdded)
{
m_pLayerList->AddTail((void*) pLayer);
}
}
else
{
retVal = HXR_OUTOFMEMORY;
}
}
return retVal;
}
void CAnimationSandwich::RemoveLayer(const char* pszAnimID)
{
if (pszAnimID && m_pLayerList)
{
LISTPOSITION pos = m_pLayerList->GetHeadPosition();
while (pos)
{
CAnimationSandwichLayer* pLayer =
(CAnimationSandwichLayer*) m_pLayerList->GetAt(pos);
if (pLayer &&
pLayer->GetAnimationElementID() &&
!strcmp(pszAnimID, pLayer->GetAnimationElementID()))
{
// We need to remove this layer
//
// First remove it from the list
pos = m_pLayerList->RemoveAt(pos);
// Next delete the object itself
HX_DELETE(pLayer);
}
else
{
m_pLayerList->GetNext(pos);
}
}
}
}
void CAnimationSandwich::FreezeLayers(const char* pszAnimID, UINT32 ulCurTime)
{
if (pszAnimID && m_pLayerList)
{
LISTPOSITION pos = m_pLayerList->GetHeadPosition();
while (pos)
{
CAnimationSandwichLayer* pLayer =
(CAnimationSandwichLayer*) m_pLayerList->GetNext(pos);
if (pLayer &&
pLayer->GetAnimationElementID() &&
!strcmp(pszAnimID, pLayer->GetAnimationElementID()) &&
pLayer->IsActive(ulCurTime))
{
// We need to freeze this layer. We do this
// by adjusting the layer's m_ulActiveDuration
// such that pLayer->m_ulDelay + pLayer->m_ulActiveDuration
// is equal to the current time.
pLayer->AdjustActiveDuration(ulCurTime);
}
}
}
}
CAttr CAnimationSandwich::GetValue(UINT32 ulTime, CAttr* pUnder, CAttr* pDepend)
{
CAttr cRet;
if (pUnder)
{
// Initialize the running value
CAttr cUnder(*pUnder);
// Now run through the layers
if (m_pLayerList)
{
LISTPOSITION pos = m_pLayerList->GetHeadPosition();
while (pos)
{
CAnimationSandwichLayer* pLayer =
(CAnimationSandwichLayer*) m_pLayerList->GetNext(pos);
if (pLayer &&
(pLayer->IsActive(ulTime) ||
pLayer->IsFrozen(ulTime)))
{
// Evaluate this layer
CAttr cRes = pLayer->AnimationEffectFunction(ulTime, &cUnder, pDepend);
// Now we either have to replace OR add
if (pLayer->IsAdditive() &&
!pLayer->IsToAnimation())
{
cUnder.Add(&cRes, pDepend);
}
else
{
cUnder = cRes;
}
}
}
}
// Now set the return value
cRet = cUnder;
}
return cRet;
}
UINT32 CAnimationSandwich::GetNumLayers() const
{
UINT32 ulRet = 0;
if (m_pLayerList)
{
ulRet = m_pLayerList->GetCount();
}
return ulRet;
}
void CAnimationSandwich::AdjustLayers(UINT32 ulTime)
{
if (m_pLayerList)
{
LISTPOSITION pos = m_pLayerList->GetHeadPosition();
while (pos)
{
CAnimationSandwichLayer* pLayer = (CAnimationSandwichLayer*) m_pLayerList->GetAt(pos);
if (!pLayer->IsActive(ulTime) &&
!pLayer->IsFrozen(ulTime))
{
// We need to remove this layer
//
// First remove it from the list
pos = m_pLayerList->RemoveAt(pos);
// Next delete the object itself
HX_DELETE(pLayer);
}
else
{
m_pLayerList->GetNext(pos);
}
}
}
}
BOOL CAnimationSandwich::MatchingSandwich(CSmilAnimateElement* pAnim)
{
BOOL bRet = FALSE;
if (pAnim &&
pAnim->m_pTargetElementID &&
m_pTargetElementID &&
*pAnim->m_pTargetElementID == *m_pTargetElementID)
{
// We know that this animate element has the
// same target element ID as we do. Now we
// need to check if it has the same attributeName.
// If the animate element is an <animateMotion>, then
// our sandwich could be either left or top. If the
// animate element is not <animateMotion>, then the
// attributeName has to match exactly.
if (pAnim->m_pNode &&
pAnim->m_pNode->m_tag == SMILAnimateMotion)
{
if (m_ulAttrName == kAttrNameLeft ||
m_ulAttrName == kAttrNameTop)
{
bRet = TRUE;
}
}
else
{
UINT32 ulAttrName = pAnim->m_ucAttributeName;
if (ulAttrName == m_ulAttrName)
{
bRet = TRUE;
}
}
}
return bRet;
}
BOOL CAnimationSandwich::AtLeastOneActiveLayer(UINT32 ulTime)
{
BOOL bRet = FALSE;
if (m_pLayerList &&
m_pLayerList->GetCount() > 0)
{
LISTPOSITION pos = m_pLayerList->GetHeadPosition();
while (pos)
{
CAnimationSandwichLayer* pLayer =
(CAnimationSandwichLayer*) m_pLayerList->GetNext(pos);
if (pLayer && pLayer->IsActive(ulTime))
{
bRet = TRUE;
break;
}
}
}
return bRet;
}
CSmilAnimateInfo::CSmilAnimateInfo()
{
m_pSandwich = NULL;
m_pUnder = NULL;
m_pDepend = NULL;
}
CSmilAnimateInfo::~CSmilAnimateInfo()
{
HX_DELETE(m_pSandwich);
HX_DELETE(m_pUnder);
HX_DELETE(m_pDepend);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -