//----------------------------------------------------------------------------- // Purpose: Input that sets the sequence of the cycler //----------------------------------------------------------------------------- void CCycler::InputSetSequence( inputdata_t &inputdata ) { if (m_animate) { // Legacy support: Try it as a number, and support '0' const char *sChar = inputdata.value.String(); int iSeqNum = atoi( sChar ); if ( !iSeqNum && sChar[0] != '0' ) { // Treat it as a sequence name ResetSequence( LookupSequence( sChar ) ); } else { ResetSequence( iSeqNum ); } if (GetPlaybackRate() == 0.0) { ResetSequence( 0 ); } m_flCycle = 0; } }
// Handler for MEEndOfPresentation event. HRESULT CPlayer::OnPresentationEnded(IMFMediaEvent *pEvent) { HRESULT hr = S_OK; if (_isLooping) { m_state = Started; //Create variant for seeking information PROPVARIANT varStart; PropVariantInit(&varStart); varStart.vt = VT_I8; float rate = GetPlaybackRate(); if (rate > 0) varStart.hVal.QuadPart = 0; //seeking to the beginning //else // varStart.hVal.QuadPart = getDuration()*.95 * 10000000.0; //seeking to the end hr = m_pSession->Start(&GUID_NULL, &varStart); if FAILED(hr) { ofLogError("ofxWMFVideoPlayerUtils", "Error while looping"); } PropVariantClear(&varStart); } else {
bool RageSound::SetPositionFrames( int iFrames ) { LockMut( m_Mutex ); if( m_pSource == NULL ) { LOG->Warn( "RageSound::SetPositionFrames(%d): sound not loaded", iFrames ); return false; } { /* "m_iDecodePosition" records the number of frames we've output to the * speaker. If the rate isn't 1.0, this will be different from the * position in the sound data itself. For example, if we're playing * at 0.5x, and we're seeking to the 10th frame, we would have actually * played 20 frames, and it's the number of real speaker frames that * "m_iDecodePosition" represents. */ const int iScaledFrames = int( iFrames / GetPlaybackRate() ); /* If we're already there, don't do anything. */ if( m_iDecodePosition == iScaledFrames ) return true; m_iStoppedPosition = m_iDecodePosition = iScaledFrames; } /* The position we're going to seek the input stream to. We have * to do this in floating point to avoid overflow. */ int ms = int( float(iFrames) * 1000.f / samplerate() ); ms = max(ms, 0); m_DataBuffer.clear(); int ret; if( m_Param.AccurateSync ) ret = m_pSource->SetPosition_Accurate(ms); else ret = m_pSource->SetPosition_Fast(ms); if(ret == -1) { /* XXX untested */ Fail( m_pSource->GetError() ); return false; /* failed */ } if(ret == 0 && ms != 0) { /* We were told to seek somewhere, and we got 0 instead, which means * we passed EOF. This could be a truncated file or invalid data. */ LOG->Warn("SetPositionFrames: %i ms is beyond EOF in %s", ms, GetLoadedFilePath().c_str()); return false; /* failed */ } return true; }
bool C_BaseViewModel::Interpolate( float currentTime ) { CStudioHdr *pStudioHdr = GetModelPtr(); // Make sure we reset our animation information if we've switch sequences UpdateAnimationParity(); bool bret = BaseClass::Interpolate( currentTime ); // Hack to extrapolate cycle counter for view model float elapsed_time = currentTime - m_flAnimTime; C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); // Predicted viewmodels have fixed up interval if ( GetPredictable() || IsClientCreated() ) { Assert( pPlayer ); float curtime = pPlayer ? pPlayer->GetFinalPredictedTime() : gpGlobals->curtime; elapsed_time = curtime - m_flAnimTime; // Adjust for interpolated partial frame if ( !engine->IsPaused() ) { elapsed_time += ( gpGlobals->interpolation_amount * TICK_INTERVAL ); } } // Prediction errors? if ( elapsed_time < 0 ) { elapsed_time = 0; } float dt = elapsed_time * GetSequenceCycleRate( pStudioHdr, GetSequence() ) * GetPlaybackRate(); if ( dt >= 1.0f ) { if ( !IsSequenceLooping( GetSequence() ) ) { dt = 0.999f; } else { dt = fmod( dt, 1.0f ); } } SetCycle( dt ); return bret; }
float RageSound::GetPositionSeconds( bool *bApproximate, RageTimer *pTimestamp ) const { LockMut( m_Mutex ); if( pTimestamp ) { HOOKS->EnterTimeCriticalSection(); pTimestamp->Touch(); } const float fPosition = GetPositionSecondsInternal( bApproximate ) / float(samplerate()); if( pTimestamp ) HOOKS->ExitTimeCriticalSection(); return GetPlaybackRate() * fPosition; }
//----------------------------------------------------------------------------- // Purpose: how fast should I be going ideally //----------------------------------------------------------------------------- float CAI_Motor::IdealVelocity( void ) { // FIXME: this should be a per-entity setting so run speeds are not based on animation speeds return GetIdealSpeed() * GetPlaybackRate(); }
void CBaseGrenade::BounceTouch( CBaseEntity *pOther ) { if ( pOther->IsSolidFlagSet(FSOLID_TRIGGER | FSOLID_VOLUME_CONTENTS) ) return; // don't hit the guy that launched this grenade if ( pOther == GetThrower() ) return; // only do damage if we're moving fairly fast if ( (pOther->m_takedamage != DAMAGE_NO) && (m_flNextAttack < gpGlobals->curtime && GetAbsVelocity().Length() > 100)) { if (m_hThrower) { #if !defined( CLIENT_DLL ) trace_t tr; tr = CBaseEntity::GetTouchTrace( ); ClearMultiDamage( ); Vector forward; AngleVectors( GetLocalAngles(), &forward, NULL, NULL ); CTakeDamageInfo info( this, m_hThrower, 1, DMG_CLUB ); CalculateMeleeDamageForce( &info, GetAbsVelocity(), GetAbsOrigin() ); pOther->DispatchTraceAttack( info, forward, &tr ); ApplyMultiDamage(); #endif } m_flNextAttack = gpGlobals->curtime + 1.0; // debounce } Vector vecTestVelocity; // m_vecAngVelocity = Vector (300, 300, 300); // this is my heuristic for modulating the grenade velocity because grenades dropped purely vertical // or thrown very far tend to slow down too quickly for me to always catch just by testing velocity. // trimming the Z velocity a bit seems to help quite a bit. vecTestVelocity = GetAbsVelocity(); vecTestVelocity.z *= 0.45; if ( !m_bHasWarnedAI && vecTestVelocity.Length() <= 60 ) { // grenade is moving really slow. It's probably very close to where it will ultimately stop moving. // emit the danger sound. // register a radius louder than the explosion, so we make sure everyone gets out of the way #if !defined( CLIENT_DLL ) CSoundEnt::InsertSound ( SOUND_DANGER, GetAbsOrigin(), m_flDamage / 0.4, 0.3, this ); #endif m_bHasWarnedAI = true; } if (GetFlags() & FL_ONGROUND) { // add a bit of static friction // SetAbsVelocity( GetAbsVelocity() * 0.8 ); // SetSequence( random->RandomInt( 1, 1 ) ); // FIXME: missing tumble animations } else { // play bounce sound BounceSound(); } m_flPlaybackRate = GetAbsVelocity().Length() / 200.0; if (GetPlaybackRate() > 1.0) m_flPlaybackRate = 1; else if (GetPlaybackRate() < 0.5) m_flPlaybackRate = 0; }
//----------------------------------------------------------------------------- // Purpose: Render the weapon. Draw the Viewmodel if the weapon's being carried // by this player, otherwise draw the worldmodel. //----------------------------------------------------------------------------- int C_BaseViewModel::DrawModel( int flags, const RenderableInstance_t &instance ) { if ( !m_bReadyToDraw ) return 0; if ( flags & STUDIO_RENDER ) { // Determine blending amount and tell engine float blend = (float)( instance.m_nAlpha / 255.0f ); // Totally gone if ( blend <= 0.0f ) return 0; // Tell engine render->SetBlend( blend ); float color[3]; GetColorModulation( color ); render->SetColorModulation( color ); } CMatRenderContextPtr pRenderContext( materials ); if ( ShouldFlipViewModel() ) pRenderContext->CullMode( MATERIAL_CULLMODE_CW ); int ret = 0; C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); C_BaseCombatWeapon *pWeapon = GetOwningWeapon(); // If the local player's overriding the viewmodel rendering, let him do it if ( pPlayer && pPlayer->IsOverridingViewmodel() ) { ret = pPlayer->DrawOverriddenViewmodel( this, flags, instance ); } else if ( pWeapon && pWeapon->IsOverridingViewmodel() ) { ret = pWeapon->DrawOverriddenViewmodel( this, flags, instance ); } else { ret = BaseClass::DrawModel( flags, instance ); } pRenderContext->CullMode( MATERIAL_CULLMODE_CCW ); // Now that we've rendered, reset the animation restart flag if ( flags & STUDIO_RENDER ) { if ( m_nOldAnimationParity != m_nAnimationParity ) { m_nOldAnimationParity = m_nAnimationParity; } // Tell the weapon itself that we've rendered, in case it wants to do something if ( pWeapon ) { pWeapon->ViewModelDrawn( this ); } if ( vm_debug.GetBool() ) { MDLCACHE_CRITICAL_SECTION(); int line = 16; CStudioHdr *hdr = GetModelPtr(); engine->Con_NPrintf( line++, "%s: %s(%d), cycle: %.2f cyclerate: %.2f playbackrate: %.2f\n", (hdr)?hdr->pszName():"(null)", GetSequenceName( GetSequence() ), GetSequence(), GetCycle(), GetSequenceCycleRate( hdr, GetSequence() ), GetPlaybackRate() ); if ( hdr ) { for( int i=0; i < hdr->GetNumPoseParameters(); ++i ) { const mstudioposeparamdesc_t &Pose = hdr->pPoseParameter( i ); engine->Con_NPrintf( line++, "pose_param %s: %f", Pose.pszName(), GetPoseParameter( i ) ); } } // Determine blending amount and tell engine float blend = (float)( instance.m_nAlpha / 255.0f ); float color[3]; GetColorModulation( color ); engine->Con_NPrintf( line++, "blend=%f, color=%f,%f,%f", blend, color[0], color[1], color[2] ); engine->Con_NPrintf( line++, "GetRenderMode()=%d", GetRenderMode() ); engine->Con_NPrintf( line++, "m_nRenderFX=0x%8.8X", GetRenderFX() ); color24 c = GetRenderColor(); unsigned char a = GetRenderAlpha(); engine->Con_NPrintf( line++, "rendercolor=%d,%d,%d,%d", c.r, c.g, c.b, a ); engine->Con_NPrintf( line++, "origin=%f, %f, %f", GetRenderOrigin().x, GetRenderOrigin().y, GetRenderOrigin().z ); engine->Con_NPrintf( line++, "angles=%f, %f, %f", GetRenderAngles()[0], GetRenderAngles()[1], GetRenderAngles()[2] ); if ( IsEffectActive( EF_NODRAW ) ) { engine->Con_NPrintf( line++, "EF_NODRAW" ); } } } return ret; }
void CObjectTeleporter::DeterminePlaybackRate( void ) { float flPlaybackRate = GetPlaybackRate(); bool bWasBelowFullSpeed = ( flPlaybackRate < 1.0f ); if ( IsBuilding() ) { // Default half rate, author build anim as if one player is building SetPlaybackRate( GetConstructionMultiplier() * 0.5 ); } else if ( IsPlacing() ) { SetPlaybackRate( 1.0f ); } else { float flFrameTime = 0.1; // BaseObjectThink delay switch( m_iState ) { case TELEPORTER_STATE_READY: { // spin up to 1.0 from whatever we're at, at some high rate flPlaybackRate = Approach( 1.0f, flPlaybackRate, 0.5f * flFrameTime ); } break; case TELEPORTER_STATE_RECHARGING: { // Recharge - spin down to low and back up to full speed over 10 seconds // 0 -> 4, spin to low // 4 -> 6, stay at low // 6 -> 10, spin to 1.0 float flScale = g_flTeleporterRechargeTimes[GetUpgradeLevel() - 1] / g_flTeleporterRechargeTimes[0]; float flToLow = 4.0f * flScale; float flToHigh = 6.0f * flScale; float flRechargeTime = g_flTeleporterRechargeTimes[GetUpgradeLevel() - 1]; float flTimeSinceChange = gpGlobals->curtime - m_flLastStateChangeTime; float flLowSpinSpeed = 0.15f; if ( flTimeSinceChange <= flToLow ) { flPlaybackRate = RemapVal( gpGlobals->curtime, m_flLastStateChangeTime, m_flLastStateChangeTime + flToLow, 1.0f, flLowSpinSpeed ); } else if ( flTimeSinceChange > flToLow && flTimeSinceChange <= flToHigh ) { flPlaybackRate = flLowSpinSpeed; } else { flPlaybackRate = RemapVal( gpGlobals->curtime, m_flLastStateChangeTime + flToHigh, m_flLastStateChangeTime + flRechargeTime, flLowSpinSpeed, 1.0f ); } } break; default: { if ( m_flLastStateChangeTime <= 0.0f ) { flPlaybackRate = 0.0f; } else { // lost connect - spin down to 0.0 from whatever we're at, slowish rate flPlaybackRate = Approach( 0.0f, flPlaybackRate, 0.25f * flFrameTime ); } } break; } SetPlaybackRate( flPlaybackRate ); } bool bBelowFullSpeed = ( GetPlaybackRate() < 1.0f ); if ( m_iBlurBodygroup >= 0 && bBelowFullSpeed != bWasBelowFullSpeed ) { if ( bBelowFullSpeed ) { SetBodygroup( m_iBlurBodygroup, 0 ); // turn off blur bodygroup } else { SetBodygroup( m_iBlurBodygroup, 1 ); // turn on blur bodygroup } } StudioFrameAdvance(); }
//----------------------------------------------------------------------------- // Purpose: // Input : buf - //----------------------------------------------------------------------------- void CDemoActionChangePlaybackRate::SaveKeysToBuffer( int depth, CUtlBuffer& buf ) { BaseClass::SaveKeysToBuffer( depth, buf ); BufPrintf( depth, buf, "playbackrate \"%f\"\n", GetPlaybackRate() ); }
void CAI_BlendedMotor::SetMoveScriptAnim( float flNewSpeed ) { // don't bother if the npc is dead if (!GetOuter()->IsAlive()) return; // insert ideal layers // FIXME: needs full transitions, as well as starting vs stopping sequences, leaning, etc. CAI_Navigator *pNavigator = GetNavigator(); SetPlaybackRate( m_flCurrRate ); // calc weight of idle animation layer that suppresses the run animation float flWeight = 0.0; if (GetIdealSpeed() > 0.0) { flWeight = 1.0 - (flNewSpeed / (GetIdealSpeed() * GetPlaybackRate())); } if (flWeight < 0.0) { m_flCurrRate = flNewSpeed / GetIdealSpeed(); m_flCurrRate = clamp( m_flCurrRate, 0.0, 1.0 ); SetPlaybackRate( m_flCurrRate ); flWeight = 0.0; } // Msg("weight %.3f rate %.3f\n", flWeight, m_flCurrRate ); m_flCurrRate = min( m_flCurrRate + (1.0 - m_flCurrRate) * 0.8, 1.0 ); if (m_nSavedGoalActivity == ACT_INVALID) { ResetGoalSequence(); } // detect state change Activity activity = GetOuter()->NPC_TranslateActivity( m_nSavedGoalActivity ); if ( activity != m_nSavedTranslatedGoalActivity ) { m_nSavedTranslatedGoalActivity = activity; m_nInteriorSequence = ACT_INVALID; m_nGoalSequence = pNavigator->GetArrivalSequence( m_nPrimarySequence ); } if (m_bDeceleratingToGoal) { // find that sequence to play when at goal m_nGoalSequence = pNavigator->GetArrivalSequence( m_nPrimarySequence ); if (m_nGoalSequence == ACT_INVALID) { m_nGoalSequence = GetInteriorSequence( m_nPrimarySequence ); } Assert( m_nGoalSequence != ACT_INVALID ); } if (m_flSecondaryWeight == 1.0 || (m_iSecondaryLayer != -1 && m_nPrimarySequence == m_nSecondarySequence)) { // secondary layer at full strength last time, delete the primary and shift down RemoveLayer( m_iPrimaryLayer, 0.0, 0.0 ); m_iPrimaryLayer = m_iSecondaryLayer; m_nPrimarySequence = m_nSecondarySequence; m_iSecondaryLayer = -1; m_nSecondarySequence = ACT_INVALID; m_flSecondaryWeight = 0.0; } // look for transition sequence if needed if (m_nSecondarySequence == ACT_INVALID) { if (!m_bDeceleratingToGoal && m_nGoalSequence != GetInteriorSequence( m_nPrimarySequence )) { // strob interior sequence in case it changed m_nGoalSequence = GetInteriorSequence( m_nPrimarySequence ); } if (m_nGoalSequence != ACT_INVALID && m_nPrimarySequence != m_nGoalSequence) { // Msg("From %s to %s\n", GetOuter()->GetSequenceName( m_nPrimarySequence ), GetOuter()->GetSequenceName( m_nGoalSequence ) ); m_nSecondarySequence = GetOuter()->FindTransitionSequence(m_nPrimarySequence, m_nGoalSequence, NULL); if (m_nSecondarySequence == ACT_INVALID) m_nSecondarySequence = m_nGoalSequence; } } // set blending for if (m_nSecondarySequence != ACT_INVALID) { if (m_iSecondaryLayer == -1) { m_iSecondaryLayer = AddLayeredSequence( m_nSecondarySequence, 0 ); SetLayerWeight( m_iSecondaryLayer, 0.0 ); if (m_nSecondarySequence == m_nGoalSequence) { SetLayerPlaybackRate( m_iSecondaryLayer, 0.0 ); } else { SetLayerPlaybackRate( m_iSecondaryLayer, 1.0 ); } SetLayerNoRestore( m_iSecondaryLayer, true ); m_flSecondaryWeight = 0.0; } m_flSecondaryWeight = min( m_flSecondaryWeight + 0.3, 1.0 ); if (m_flSecondaryWeight < 1.0) { SetLayerWeight( m_iPrimaryLayer, (flWeight - m_flSecondaryWeight * flWeight) / (1.0f - m_flSecondaryWeight * flWeight) ); SetLayerWeight( m_iSecondaryLayer, flWeight * m_flSecondaryWeight ); } else { SetLayerWeight( m_iPrimaryLayer, 0.0f ); SetLayerWeight( m_iSecondaryLayer, flWeight ); } } else { // recreate layer if missing if (m_iPrimaryLayer == -1) { MoveContinue(); } // try to catch a stale layer if (m_iSecondaryLayer != -1) { // secondary layer at full strength last time, delete the primary and shift down RemoveLayer( m_iSecondaryLayer, 0.0, 0.0 ); m_iSecondaryLayer = -1; m_nSecondarySequence = ACT_INVALID; m_flSecondaryWeight = 0.0; } // debounce // flWeight = flWeight * 0.5 + 0.5 * GetOuter()->GetLayerWeight( m_iPrimaryLayer ); SetLayerWeight( m_iPrimaryLayer, flWeight ); } }