void VectorImage::OnSVGDocumentLoaded() { MOZ_ASSERT(mSVGDocumentWrapper->GetRootSVGElem(), "Should have parsed successfully"); MOZ_ASSERT(!mIsFullyLoaded && !mHaveAnimations, "These flags shouldn't get set until OnSVGDocumentLoaded. " "Duplicate calls to OnSVGDocumentLoaded?"); CancelAllListeners(); // XXX Flushing is wasteful if embedding frame hasn't had initial reflow. mSVGDocumentWrapper->FlushLayout(); mIsFullyLoaded = true; mHaveAnimations = mSVGDocumentWrapper->IsAnimated(); // Start listening to our image for rendering updates. mRenderingObserver = new SVGRootRenderingObserver(mSVGDocumentWrapper, this); // Tell *our* observers that we're done loading. if (mProgressTracker) { mProgressTracker->SyncNotifyProgress(FLAG_SIZE_AVAILABLE | FLAG_HAS_TRANSPARENCY | FLAG_FRAME_COMPLETE | FLAG_DECODE_COMPLETE | FLAG_ONLOAD_UNBLOCKED, GetMaxSizedIntRect()); } EvaluateAnimation(); }
void ImageResource::DecrementAnimationConsumers() { NS_ABORT_IF_FALSE(mAnimationConsumers >= 1, "Invalid no. of animation consumers!"); mAnimationConsumers--; EvaluateAnimation(); }
//****************************************************************************** NS_IMETHODIMP RasterImage::ResetAnimation() { if (mError) { return NS_ERROR_FAILURE; } mPendingAnimation = false; if (mAnimationMode == kDontAnimMode || !mAnimationState || mAnimationState->GetCurrentAnimationFrameIndex() == 0) { return NS_OK; } mAnimationFinished = false; if (mAnimating) { StopAnimation(); } MOZ_ASSERT(mAnimationState, "Should have AnimationState"); mAnimationState->ResetAnimation(); NotifyProgress(NoProgress, mAnimationState->FirstFrameRefreshArea()); // Start the animation again. It may not have been running before, if // mAnimationFinished was true before entering this function. EvaluateAnimation(); return NS_OK; }
VectorImage::RequestRefresh(const TimeStamp& aTime) { if (HadRecentRefresh(aTime)) { return; } EvaluateAnimation(); mSVGDocumentWrapper->TickRefreshDriver(); if (mHasPendingInvalidation) { SendInvalidationNotifications(); mHasPendingInvalidation = false; } }
void VectorImage::OnSVGDocumentLoaded() { MOZ_ASSERT(mSVGDocumentWrapper->GetRootSVGElem(), "Should have parsed successfully"); MOZ_ASSERT(!mIsFullyLoaded && !mHaveAnimations, "These flags shouldn't get set until OnSVGDocumentLoaded. " "Duplicate calls to OnSVGDocumentLoaded?"); CancelAllListeners(); // XXX Flushing is wasteful if embedding frame hasn't had initial reflow. mSVGDocumentWrapper->FlushLayout(); mIsFullyLoaded = true; mHaveAnimations = mSVGDocumentWrapper->IsAnimated(); // Start listening to our image for rendering updates. mRenderingObserver = new SVGRootRenderingObserver(mSVGDocumentWrapper, this); // ProgressTracker::SyncNotifyProgress may release us, so ensure we // stick around long enough to complete our work. RefPtr<VectorImage> kungFuDeathGrip(this); // Tell *our* observers that we're done loading. if (mProgressTracker) { Progress progress = FLAG_SIZE_AVAILABLE | FLAG_HAS_TRANSPARENCY | FLAG_FRAME_COMPLETE | FLAG_DECODE_COMPLETE | FLAG_ONLOAD_UNBLOCKED; if (mHaveAnimations) { progress |= FLAG_IS_ANIMATED; } // Merge in any saved progress from OnImageDataComplete. if (mLoadProgress) { progress |= *mLoadProgress; mLoadProgress = Nothing(); } mProgressTracker->SyncNotifyProgress(progress, GetMaxSizedIntRect()); } EvaluateAnimation(); }
nsresult ImageResource::SetAnimationModeInternal(uint16_t aAnimationMode) { if (mError) return NS_ERROR_FAILURE; NS_ASSERTION(aAnimationMode == kNormalAnimMode || aAnimationMode == kDontAnimMode || aAnimationMode == kLoopOnceAnimMode, "Wrong Animation Mode is being set!"); mAnimationMode = aAnimationMode; EvaluateAnimation(); return NS_OK; }
/* attribute unsigned short animationMode; */ NS_IMETHODIMP Image::SetAnimationMode(PRUint16 aAnimationMode) { if (mError) return NS_ERROR_FAILURE; NS_ASSERTION(aAnimationMode == kNormalAnimMode || aAnimationMode == kDontAnimMode || aAnimationMode == kLoopOnceAnimMode, "Wrong Animation Mode is being set!"); mAnimationMode = aAnimationMode; EvaluateAnimation(); return NS_OK; }
VectorImage::RequestRefresh(const TimeStamp& aTime) { if (HadRecentRefresh(aTime)) { return; } PendingAnimationTracker* tracker = mSVGDocumentWrapper->GetDocument()->GetPendingAnimationTracker(); if (tracker && ShouldAnimate()) { tracker->TriggerPendingAnimationsOnNextTick(aTime); } EvaluateAnimation(); mSVGDocumentWrapper->TickRefreshDriver(); if (mHasPendingInvalidation) { mHasPendingInvalidation = false; SendInvalidationNotifications(); } }
/* void onStopRequest(in nsIRequest request, in nsISupports ctxt, in nsresult status); */ NS_IMETHODIMP VectorImage::OnStopRequest(nsIRequest* aRequest, nsISupports* aCtxt, nsresult aStatus) { if (mError) return NS_ERROR_FAILURE; NS_ABORT_IF_FALSE(!mIsFullyLoaded && !mHaveAnimations, "these flags shouldn't get set until OnStopRequest. " "Duplicate calls to OnStopRequest?"); nsresult rv = mSVGDocumentWrapper->OnStopRequest(aRequest, aCtxt, aStatus); if (!mSVGDocumentWrapper->ParsedSuccessfully()) { // XXXdholbert Need to do something more here -- right now, this just // makes us draw the "object" icon, rather than the (jagged) "broken image" // icon. See bug 594505. mError = true; return rv; } mIsFullyLoaded = true; mHaveAnimations = mSVGDocumentWrapper->IsAnimated(); // Start listening to our image for rendering updates mRenderingObserver = new SVGRootRenderingObserver(mSVGDocumentWrapper, this); // Tell *our* observers that we're done loading nsCOMPtr<imgIDecoderObserver> observer = do_QueryReferent(mObserver); if (observer) { // NOTE: This signals that width/height are available. observer->OnStartContainer(nsnull, this); observer->FrameChanged(this, &nsIntRect::GetMaxSizedIntRect()); observer->OnStopFrame(nsnull, 0); observer->OnStopDecode(nsnull, NS_OK, nsnull); } EvaluateAnimation(); return rv; }
void ImageResource::IncrementAnimationConsumers() { mAnimationConsumers++; EvaluateAnimation(); }
void USkeletalMeshComponent::RefreshBoneTransforms() { SCOPE_CYCLE_COUNTER(STAT_RefreshBoneTransforms); // Can't do anything without a SkeletalMesh // Do nothing more if no bones in skeleton. if( !SkeletalMesh || SpaceBases.Num() == 0 ) { return; } AActor * Owner = GetOwner(); const FAnimUpdateRateParameters & UpdateRateParams = Owner ? Owner->AnimUpdateRateParams : FAnimUpdateRateParameters(); { FScopeLockPhysXWriter LockPhysXForWriting; // Recalculate the RequiredBones array, if necessary if( !bRequiredBonesUpToDate ) { RecalcRequiredBones(PredictedLODLevel); } // Update rate turned off, evaluate every frame. if( !bEnableUpdateRateOptimizations || (UpdateRateParams.GetEvaluationRate() <= 1) ) { // evaluate pure animations, and fill up LocalAtoms EvaluateAnimation(); // We need the mesh space bone transforms now for renderer to get delta from ref pose: FillSpaceBases(); // Invalidate cached bones. CachedLocalAtoms.Empty(); CachedSpaceBases.Empty(); } else { // figure out if our cache is invalid. const bool bInvalidCachedBones = (LocalAtoms.Num() != SkeletalMesh->RefSkeleton.GetNum()) || (LocalAtoms.Num() != CachedLocalAtoms.Num()) || (SpaceBases.Num() != CachedSpaceBases.Num()); // If cache is invalid, we need to rebuild it. And we can't interpolate. // (same path if we're not interpolating and not skipping a frame). if( bInvalidCachedBones || (!UpdateRateParams.ShouldInterpolateSkippedFrames() && !UpdateRateParams.ShouldSkipEvaluation()) ) { // evaluate pure animations, and fill up LocalAtoms EvaluateAnimation(); // Fill SpaceBases from LocalAtoms FillSpaceBases(); // Cache bones CachedLocalAtoms = LocalAtoms; CachedSpaceBases = SpaceBases; } else { // No interpolation, just copy // @todo: if we don't blend any physics, we could even skip the copy. if( !UpdateRateParams.ShouldInterpolateSkippedFrames() ) { LocalAtoms = CachedLocalAtoms; SpaceBases = CachedSpaceBases; } else { // If we are not skipping evaluation this frame, refresh cache. if( !UpdateRateParams.ShouldSkipEvaluation() ) { // Preserve LocalAtoms and SpaceBases, so we can keep interpolation. Exchange(LocalAtoms, CachedLocalAtoms); Exchange(SpaceBases, CachedSpaceBases); // evaluate pure animations, and fill up LocalAtoms EvaluateAnimation(); // Fill SpaceBases from LocalAtoms FillSpaceBases(); Exchange(LocalAtoms, CachedLocalAtoms); Exchange(SpaceBases, CachedSpaceBases); } // Interpolate { SCOPE_CYCLE_COUNTER(STAT_InterpolateSkippedFrames); const float Alpha = 0.25f + (1.f / float(FMath::Max(UpdateRateParams.GetEvaluationRate(), 2) * 2)); FAnimationRuntime::LerpBoneTransforms(LocalAtoms, CachedLocalAtoms, Alpha, RequiredBones); FAnimationRuntime::LerpBoneTransforms(SpaceBases, CachedSpaceBases, Alpha, RequiredBones); } } } } // Transforms updated, cached local bounds are now out of date. InvalidateCachedBounds(); // update physics data from animated data UpdateKinematicBonesToPhysics(false); UpdateRBJointMotors(); } // @todo anim : hack TTP 224385 ANIM: Skeletalmesh double buffer // this is problem because intermediate buffer changes physics position as well // this causes issue where a half of frame, physics position is fixed with anim pose, and the other half is real simulated position // if you enable physics in tick, since that's before physics update, you'll get animation pose dominating physics pose, which isn't what you want. (Or what you'll see) // so do not update transform if physics is on. This problem will be solved by double buffer, when we keep one buffer for intermediate, and the other buffer for result query { FScopeLockPhysXReader LockPhysXForReading; if( !IsSimulatingPhysics() ) { SCOPE_CYCLE_COUNTER(STAT_UpdateLocalToWorldAndOverlaps); // New bone positions need to be sent to render thread UpdateComponentToWorld(); // animation often change overlap. UpdateOverlaps(); } } MarkRenderDynamicDataDirty(); }