void BeginnerHelper::DrawPrimitives() { // If not initialized, don't bother with this if(!m_bInitialized) return; ActorFrame::DrawPrimitives(); m_sFlash.Draw(); bool DrawCelShaded = PREFSMAN->m_bCelShadeModels; if(DrawCelShaded) m_pDancePad->DrawCelShaded(); else { DISPLAY->SetLighting( true ); DISPLAY->SetLightDirectional( 0, RageColor(0.5,0.5,0.5,1), RageColor(1,1,1,1), RageColor(0,0,0,1), RageVector3(0, 0, 1) ); m_pDancePad->Draw(); DISPLAY->ClearZBuffer(); // So character doesn't step "into" the dance pad. DISPLAY->SetLightOff(0); DISPLAY->SetLighting(false); } // Draw StepCircles for(int scd=0; scd<NUM_PLAYERS; scd++) for(int scde=0; scde<4; scde++) m_sStepCircle[scd][scde].Draw(); if(DrawCelShaded) FOREACH_PlayerNumber(pn) // Draw each dancer if(GAMESTATE->IsHumanPlayer(pn)) m_pDancer[pn]->DrawCelShaded(); else { DISPLAY->SetLighting( true ); DISPLAY->SetLightDirectional( 0, RageColor(0.5,0.5,0.5,1), RageColor(1,1,1,1), RageColor(0,0,0,1), RageVector3(0, 0, 1) ); FOREACH_PlayerNumber(pn) // Draw each dancer if(GAMESTATE->IsHumanPlayer(pn)) m_pDancer[pn]->Draw(); DISPLAY->SetLightOff(0); DISPLAY->SetLighting(false); } }
void Actor::TweenState::Init() { pos = RageVector3( 0, 0, 0 ); rotation = RageVector3( 0, 0, 0 ); quat = RageVector4( 0, 0, 0, 1 ); scale = RageVector3( 1, 1, 1 ); crop = RectF( 0,0,0,0 ); fade = RectF( 0,0,0,0 ); fadecolor = RageColor( 1, 1, 1, 0 ); for(int i=0; i<4; i++) diffuse[i] = RageColor( 1, 1, 1, 1 ); glow = RageColor( 1, 1, 1, 0 ); glowmode = GLOW_WHITEN; }
void NoteDisplay::DrawHoldHead( const TapNote& tn, int iCol, int iRow, bool bIsBeingHeld, float fYHead, float fPercentFadeToFail, float fColorScale, bool bGlow, float fYStartOffset, float fYEndOffset ) { // // Draw the head // Actor* pActor = GetHoldHeadActor( NoteRowToBeat(iRow), tn.subType == TapNote::hold_head_roll, bIsBeingHeld ); pActor->SetZoom( ArrowEffects::GetZoom( m_pPlayerState ) ); // draw with normal Sprite const float fY = fYHead; const float fYOffset = ArrowEffects::GetYOffsetFromYPos( m_pPlayerState, iCol, fY, m_fYReverseOffsetPixels ); if( fYOffset < fYStartOffset || fYOffset > fYEndOffset ) return; // TRICKY: skew the rotation by a few pixels so this lines up with the start of the twirly hold. const float fRotationY = ArrowEffects::GetRotationY( m_pPlayerState, fYOffset+16 ); const float fX = ArrowEffects::GetXPos( m_pPlayerState, iCol, fYOffset ); const float fZ = ArrowEffects::GetZPos( m_pPlayerState, iCol, fYOffset ); const float fAlpha = ArrowEffects::GetAlpha( m_pPlayerState, iCol, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels ); const float fGlow = ArrowEffects::GetGlow( m_pPlayerState, iCol, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels ); const RageColor colorDiffuse= RageColor(fColorScale,fColorScale,fColorScale,fAlpha); const RageColor colorGlow = RageColor(1,1,1,fGlow); pActor->SetRotationY( fRotationY ); pActor->SetRotationZ( 0 ); pActor->SetXY( fX, fY ); pActor->SetZ( fZ ); if( bGlow ) { pActor->SetDiffuse( RageColor(1,1,1,0) ); pActor->SetGlow( colorGlow ); } else { pActor->SetDiffuse( colorDiffuse ); pActor->SetGlow( RageColor(0,0,0,0) ); } if( cache->m_bHoldHeadUseLighting ) { DISPLAY->SetLighting( true ); DISPLAY->SetLightDirectional( 0, RageColor(1,1,1,1), RageColor(1,1,1,1), RageColor(1,1,1,1), RageVector3(1, 0, +1) ); } pActor->Draw(); if( cache->m_bHoldHeadUseLighting ) { DISPLAY->SetLightOff( 0 ); DISPLAY->SetLighting( false ); } }
void NoteDisplay::DrawHoldTail( const TapNote& tn, int iCol, int iRow, bool bIsBeingHeld, float fYTail, float fPercentFadeToFail, float fColorScale, bool bGlow, float fYStartOffset, float fYEndOffset ) { // // Draw the tail // Actor* pSprTail = GetHoldTailActor( NoteRowToBeat(iRow), tn.subType == TapNote::hold_head_roll, bIsBeingHeld ); pSprTail->SetZoom( ArrowEffects::GetZoom( m_pPlayerState ) ); const float fY = fYTail; const float fYOffset = ArrowEffects::GetYOffsetFromYPos( m_pPlayerState, iCol, fY, m_fYReverseOffsetPixels ); if( fYOffset < fYStartOffset || fYOffset > fYEndOffset ) return; const float fRotationY = ArrowEffects::GetRotationY( m_pPlayerState, fYOffset ); const float fX = ArrowEffects::GetXPos( m_pPlayerState, iCol, fYOffset ); const float fZ = ArrowEffects::GetZPos( m_pPlayerState, iCol, fYOffset ); const float fAlpha = ArrowEffects::GetAlpha( m_pPlayerState, iCol, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels ); const float fGlow = ArrowEffects::GetGlow( m_pPlayerState, iCol, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels ); const RageColor colorDiffuse= RageColor(fColorScale,fColorScale,fColorScale,fAlpha); const RageColor colorGlow = RageColor(1,1,1,fGlow); pSprTail->SetRotationY( fRotationY ); pSprTail->SetXY( fX, fY ); pSprTail->SetZ( fZ ); if( bGlow ) { pSprTail->SetDiffuse( RageColor(1,1,1,0) ); pSprTail->SetGlow( colorGlow ); } else { pSprTail->SetDiffuse( colorDiffuse ); pSprTail->SetGlow( RageColor(0,0,0,0) ); } if( cache->m_bHoldTailUseLighting ) { DISPLAY->SetLighting( true ); DISPLAY->SetLightDirectional( 0, RageColor(1,1,1,1), RageColor(1,1,1,1), RageColor(1,1,1,1), RageVector3(1, 0, +1) ); } pSprTail->Draw(); if( cache->m_bHoldTailUseLighting ) { DISPLAY->SetLightOff( 0 ); DISPLAY->SetLighting( false ); } }
/* This is Reset instead of Init since many derived classes have Init() functions * that shouldn't change the position of the actor. */ void Actor::Reset() { m_Tweens.clear(); m_pTempState = NULL; m_baseRotation = RageVector3( 0, 0, 0 ); m_baseScale = RageVector3( 1, 1, 1 ); m_fBaseAlpha = 1; m_start.Init(); m_current.Init(); m_HorizAlign = align_center; m_VertAlign = align_middle; m_Effect = no_effect; m_fSecsIntoEffect = 0; m_fEffectDelta = 0; m_fEffectPeriodSeconds = 1; m_fEffectDelay = 0; m_fEffectOffset = 0; m_EffectClock = CLOCK_TIMER; m_vEffectMagnitude = RageVector3(0,0,10); m_effectColor1 = RageColor(1,1,1,1); m_effectColor2 = RageColor(1,1,1,1); m_bVisible = true; m_fShadowLength = 0; m_bIsAnimating = true; m_fHibernateSecondsLeft = 0; m_iDrawOrder = 0; m_bTextureWrapping = false; m_BlendMode = BLEND_NORMAL; m_fZBias = 0; m_bClearZBuffer = false; m_ZTestMode = ZTEST_OFF; m_bZWrite = false; m_CullMode = CULL_NONE; UnsubcribeAndClearCommands(); }
ScreenEz2SelectPlayer::ScreenEz2SelectPlayer( CString sName ) : ScreenWithMenuElements( sName ) { // Unjoin the players, then let them join back in on this screen // GAMESTATE->m_bPlayersCanJoin = true; FOREACH_PlayerNumber( p ) GAMESTATE->m_bSideIsJoined[p] = false; LOG->Trace( "ScreenEz2SelectPlayer::ScreenEz2SelectPlayer()" ); m_Background.LoadFromAniDir( THEME->GetPathToB("ScreenEz2SelectPlayer background") ); this->AddChild( &m_Background ); // animated background =) FOREACH_PlayerNumber( p ) { m_sprJoinFrame[p].Load( THEME->GetPathToG("ScreenEz2SelectPlayer join frame 1x2") ); m_sprJoinFrame[p].StopAnimating(); m_sprJoinFrame[p].SetState( p ); m_sprJoinFrame[p].SetXY( JOIN_FRAME_X(p), JOIN_FRAME_Y(p) ); this->AddChild( &m_sprJoinFrame[p] ); if( GAMESTATE->m_bSideIsJoined[p] ) m_sprJoinFrame[p].SetZoomY( 0 ); m_sprJoinMessage[p].Load( THEME->GetPathToG("ScreenEz2SelectPlayer join message 2x2") ); m_sprJoinMessage[p].StopAnimating(); m_sprJoinMessage[p].SetState( p ); m_sprJoinMessage[p].SetXY( JOIN_MESSAGE_X(p), JOIN_MESSAGE_Y(p) ); if( BOUNCE_JOIN_MESSAGE ) m_sprJoinMessage[p].SetEffectBounce( 0.5f, RageVector3(0,10,0) ); this->AddChild( &m_sprJoinMessage[p] ); if( GAMESTATE->m_bSideIsJoined[p] ) { m_sprJoinMessage[p].SetState( p+NUM_PLAYERS ); if( FOLD_ON_JOIN ) { m_sprJoinMessage[p].SetZoomY( 0 ); m_sprJoinFrame[p].SetZoomY( 0 ); } } } SOUND->PlayOnceFromDir( ANNOUNCER->GetPathTo("select player intro") ); SOUND->PlayMusic( THEME->GetPathToS("ScreenSelectPlayer music") ); TweenOnScreen(); }
ActorFrame::ActorFrame() { m_bPropagateCommands = false; m_bDeleteChildren = false; m_bDrawByZPosition = false; m_DrawFunction.SetFromNil(); m_UpdateFunction.SetFromNil(); m_fUpdateRate = 1; m_fFOV = -1; m_fVanishX = SCREEN_CENTER_X; m_fVanishY = SCREEN_CENTER_Y; m_bOverrideLighting = false; m_bLighting = false; m_ambientColor = RageColor(1,1,1,1); m_diffuseColor = RageColor(1,1,1,1); m_specularColor = RageColor(1,1,1,1); m_lightDirection = RageVector3(0,0,1); }
void NoteDisplay::DrawActor( Actor* pActor, int iCol, float fBeat, float fPercentFadeToFail, float fLife, float fReverseOffsetPixels, bool bUseLighting ) { const float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, iCol, fBeat ); const float fYPos = ArrowEffects::GetYPos( m_pPlayerState, iCol, fYOffset, fReverseOffsetPixels ); const float fRotationX = ArrowEffects::GetRotationX( m_pPlayerState, fYOffset ); const float fRotationY = ArrowEffects::GetRotationY( m_pPlayerState, fYOffset ); const float fRotationZ = ArrowEffects::GetRotationZ( m_pPlayerState, fBeat ); const float fXPos = ArrowEffects::GetXPos( m_pPlayerState, iCol, fYOffset ); const float fZPos = ArrowEffects::GetZPos( m_pPlayerState, iCol, fYOffset ); const float fAlpha = ArrowEffects::GetAlpha( m_pPlayerState, iCol, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels ); const float fGlow = ArrowEffects::GetGlow( m_pPlayerState, iCol, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels ); const float fColorScale = ArrowEffects::GetBrightness( m_pPlayerState, fBeat ) * SCALE(fLife,0,1,0.2f,1); const float fZoom = ArrowEffects::GetZoom( m_pPlayerState ); RageColor diffuse = RageColor(fColorScale,fColorScale,fColorScale,fAlpha); RageColor glow = RageColor(1,1,1,fGlow); pActor->SetRotationX( fRotationX ); pActor->SetRotationY( fRotationY ); pActor->SetRotationZ( fRotationZ ); pActor->SetXY( fXPos, fYPos ); pActor->SetZ( fZPos ); pActor->SetDiffuse( diffuse ); pActor->SetGlow( glow ); pActor->SetZoom( fZoom ); if( bUseLighting ) { DISPLAY->SetLighting( true ); DISPLAY->SetLightDirectional( 0, RageColor(1,1,1,1), RageColor(1,1,1,1), RageColor(1,1,1,1), RageVector3(1, 0, +1) ); } pActor->Draw(); if( bUseLighting ) { DISPLAY->SetLightOff( 0 ); DISPLAY->SetLighting( false ); } }
RageMatrix RageLookAt( float eyex, float eyey, float eyez, float centerx, float centery, float centerz, float upx, float upy, float upz ) { RageVector3 Z(eyex - centerx, eyey - centery, eyez - centerz); RageVec3Normalize(&Z, &Z); RageVector3 Y(upx, upy, upz); RageVector3 X( Y[1] * Z[2] - Y[2] * Z[1], -Y[0] * Z[2] + Y[2] * Z[0], Y[0] * Z[1] - Y[1] * Z[0]); Y = RageVector3( Z[1] * X[2] - Z[2] * X[1], -Z[0] * X[2] + Z[2] * X[0], Z[0] * X[1] - Z[1] * X[0] ); RageVec3Normalize(&X, &X); RageVec3Normalize(&Y, &Y); RageMatrix mat( X[0], Y[0], Z[0], 0, X[1], Y[1], Z[1], 0, X[2], Y[2], Z[2], 0, 0, 0, 0, 1 ); RageMatrix mat2; RageMatrixTranslation(&mat2, -eyex, -eyey, -eyez); RageMatrix ret; RageMatrixMultiply(&ret, &mat, &mat2); return ret; }
void Sprite::DrawTexture( const TweenState *state ) { Actor::SetGlobalRenderStates(); // set Actor-specified render states // bail if cropped all the way if( state->crop.left + state->crop.right >= 1 || state->crop.top + state->crop.bottom >= 1 ) return; // use m_temp_* variables to draw the object RectF quadVerticies; switch( m_HorizAlign ) { case align_left: quadVerticies.left = 0; quadVerticies.right = m_size.x; break; case align_center: quadVerticies.left = -m_size.x/2; quadVerticies.right = m_size.x/2; break; case align_right: quadVerticies.left = -m_size.x; quadVerticies.right = 0; break; default: ASSERT( false ); } switch( m_VertAlign ) { case align_top: quadVerticies.top = 0; quadVerticies.bottom = m_size.y; break; case align_middle: quadVerticies.top = -m_size.y/2; quadVerticies.bottom = m_size.y/2; break; case align_bottom: quadVerticies.top = -m_size.y; quadVerticies.bottom = 0; break; default: ASSERT(0); } /* Don't draw anything outside of the texture's image area. Texels outside * of the image area aren't guaranteed to be initialized. */ /* HACK: Clamp the crop values. It would be more accurate to clip the * vertices to that the diffuse value is adjusted. */ RectF crop = state->crop; CLAMP( crop.left, 0, 1 ); CLAMP( crop.right, 0, 1 ); CLAMP( crop.top, 0, 1 ); CLAMP( crop.bottom, 0, 1 ); RectF croppedQuadVerticies = quadVerticies; #define IF_CROP_POS(side,opp_side) \ if(state->crop.side!=0) \ croppedQuadVerticies.side = \ SCALE( crop.side, 0.f, 1.f, quadVerticies.side, quadVerticies.opp_side ); IF_CROP_POS( left, right ); IF_CROP_POS( top, bottom ); IF_CROP_POS( right, left ); IF_CROP_POS( bottom, top ); static RageSpriteVertex v[4]; v[0].p = RageVector3( croppedQuadVerticies.left, croppedQuadVerticies.top, 0 ); // top left v[1].p = RageVector3( croppedQuadVerticies.left, croppedQuadVerticies.bottom, 0 ); // bottom left v[2].p = RageVector3( croppedQuadVerticies.right, croppedQuadVerticies.bottom, 0 ); // bottom right v[3].p = RageVector3( croppedQuadVerticies.right, croppedQuadVerticies.top, 0 ); // top right DISPLAY->ClearAllTextures(); DISPLAY->SetTexture( 0, m_pTexture ); // Must call this after setting the texture or else texture // parameters have no effect. Actor::SetTextureRenderStates(); // set Actor-specified render states if( m_pTexture ) { float f[8]; GetActiveTextureCoords(f); TexCoordsFromArray(v, f); RageVector2 texCoords[4] = { RageVector2( f[0], f[1] ), // top left RageVector2( f[2], f[3] ), // bottom left RageVector2( f[4], f[5] ), // bottom right RageVector2( f[6], f[7] ) // top right }; if( crop.left!=0 ) { v[0].t.x = SCALE( crop.left, 0.f, 1.f, texCoords[0].x, texCoords[3].x ); v[1].t.x = SCALE( crop.left, 0.f, 1.f, texCoords[1].x, texCoords[2].x ); } if( crop.right!=0 ) { v[2].t.x = SCALE( crop.right, 0.f, 1.f, texCoords[2].x, texCoords[1].x ); v[3].t.x = SCALE( crop.right, 0.f, 1.f, texCoords[3].x, texCoords[0].x ); } if( crop.top!=0 ) { v[0].t.y = SCALE( crop.top, 0.f, 1.f, texCoords[0].y, texCoords[1].y ); v[3].t.y = SCALE( crop.top, 0.f, 1.f, texCoords[3].y, texCoords[2].y ); } if( crop.bottom!=0 ) { v[1].t.y = SCALE( crop.bottom, 0.f, 1.f, texCoords[1].y, texCoords[0].y ); v[2].t.y = SCALE( crop.bottom, 0.f, 1.f, texCoords[2].y, texCoords[3].y ); } } else { // Just make sure we don't throw NaN/INF at the renderer: for( unsigned i = 0; i < 4; ++i ) v[i].t.x = v[i].t.y = 0; } /* Draw if we're not fully transparent */ if( state->diffuse[0].a > 0 || state->diffuse[1].a > 0 || state->diffuse[2].a > 0 || state->diffuse[3].a > 0 ) { DISPLAY->SetTextureModeModulate(); ////////////////////// // render the shadow ////////////////////// if( m_fShadowLength != 0 ) { DISPLAY->PushMatrix(); DISPLAY->TranslateWorld( m_fShadowLength, m_fShadowLength, 0 ); // shift by 5 units v[0].c = v[1].c = v[2].c = v[3].c = RageColor(0,0,0,0.5f*state->diffuse[0].a); // semi-transparent black DISPLAY->DrawQuad( v ); DISPLAY->PopMatrix(); } ////////////////////// // render the diffuse pass ////////////////////// v[0].c = state->diffuse[0]; // top left v[1].c = state->diffuse[2]; // bottom left v[2].c = state->diffuse[3]; // bottom right v[3].c = state->diffuse[1]; // top right DISPLAY->DrawQuad( v ); } ////////////////////// // render the glow pass ////////////////////// if( state->glow.a > 0.0001f ) { DISPLAY->SetTextureModeGlow(); v[0].c = v[1].c = v[2].c = v[3].c = state->glow; DISPLAY->DrawQuad( v ); } }
void RageVec3ClearBounds( RageVector3 &mins, RageVector3 &maxs ) { mins = RageVector3( FLT_MAX, FLT_MAX, FLT_MAX ); maxs = mins * -1; }
void RageVec3TransformCoord( RageVector3* pOut, const RageVector3* pV, const RageMatrix* pM ) { RageVector4 temp( pV->x, pV->y, pV->z, 1.0f ); // translate RageVec4TransformCoord( &temp, &temp, pM ); *pOut = RageVector3( temp.x/temp.w, temp.y/temp.w, temp.z/temp.w ); }
void BGAnimationLayer::LoadFromNode( const XNode* pNode ) { { bool bCond; if( pNode->GetAttrValue("Condition", bCond) && !bCond ) return; } bool bStretch = false; { RString type = "sprite"; pNode->GetAttrValue( "Type", type ); type.MakeLower(); /* The preferred way of stretching a sprite to fit the screen is "Type=sprite" * and "stretch=1". "type=1" is for backwards-compatibility. */ pNode->GetAttrValue( "Stretch", bStretch ); // Check for string match first, then do integer match. // "if(StringType(type)==0)" was matching against all string matches. // -Chris if( type.EqualsNoCase("sprite") ) { m_Type = TYPE_SPRITE; } else if( type.EqualsNoCase("particles") ) { m_Type = TYPE_PARTICLES; } else if( type.EqualsNoCase("tiles") ) { m_Type = TYPE_TILES; } else if( StringToInt(type) == 1 ) { m_Type = TYPE_SPRITE; bStretch = true; } else if( StringToInt(type) == 2 ) { m_Type = TYPE_PARTICLES; } else if( StringToInt(type) == 3 ) { m_Type = TYPE_TILES; } else { m_Type = TYPE_SPRITE; } } pNode->GetAttrValue( "FOV", m_fFOV ); pNode->GetAttrValue( "Lighting", m_bLighting ); pNode->GetAttrValue( "TexCoordVelocityX", m_fTexCoordVelocityX ); pNode->GetAttrValue( "TexCoordVelocityY", m_fTexCoordVelocityY ); // compat: pNode->GetAttrValue( "StretchTexCoordVelocityX", m_fTexCoordVelocityX ); pNode->GetAttrValue( "StretchTexCoordVelocityY", m_fTexCoordVelocityY ); // particle and tile stuff float fZoomMin = 1; float fZoomMax = 1; pNode->GetAttrValue( "ZoomMin", fZoomMin ); pNode->GetAttrValue( "ZoomMax", fZoomMax ); float fVelocityXMin = 10, fVelocityXMax = 10; float fVelocityYMin = 0, fVelocityYMax = 0; float fVelocityZMin = 0, fVelocityZMax = 0; float fOverrideSpeed = 0; // 0 means don't override speed pNode->GetAttrValue( "VelocityXMin", fVelocityXMin ); pNode->GetAttrValue( "VelocityXMax", fVelocityXMax ); pNode->GetAttrValue( "VelocityYMin", fVelocityYMin ); pNode->GetAttrValue( "VelocityYMax", fVelocityYMax ); pNode->GetAttrValue( "VelocityZMin", fVelocityZMin ); pNode->GetAttrValue( "VelocityZMax", fVelocityZMax ); pNode->GetAttrValue( "OverrideSpeed", fOverrideSpeed ); int iNumParticles = 10; pNode->GetAttrValue( "NumParticles", iNumParticles ); pNode->GetAttrValue( "ParticlesBounce", m_bParticlesBounce ); pNode->GetAttrValue( "TilesStartX", m_fTilesStartX ); pNode->GetAttrValue( "TilesStartY", m_fTilesStartY ); pNode->GetAttrValue( "TilesSpacingX", m_fTilesSpacingX ); pNode->GetAttrValue( "TilesSpacingY", m_fTilesSpacingY ); pNode->GetAttrValue( "TileVelocityX", m_fTileVelocityX ); pNode->GetAttrValue( "TileVelocityY", m_fTileVelocityY ); switch( m_Type ) { case TYPE_SPRITE: { Actor* pActor = ActorUtil::LoadFromNode( pNode, this ); this->AddChild( pActor ); if( bStretch ) pActor->StretchTo( FullScreenRectF ); } break; case TYPE_PARTICLES: { RString sFile; ActorUtil::GetAttrPath( pNode, "File", sFile ); FixSlashesInPlace( sFile ); CollapsePath( sFile ); for( int i=0; i<iNumParticles; i++ ) { Actor* pActor = ActorUtil::MakeActor( sFile, this ); if( pActor == NULL ) continue; this->AddChild( pActor ); pActor->SetXY( randomf(float(FullScreenRectF.left),float(FullScreenRectF.right)), randomf(float(FullScreenRectF.top),float(FullScreenRectF.bottom)) ); pActor->SetZoom( randomf(fZoomMin,fZoomMax) ); m_vParticleVelocity.push_back( RageVector3( randomf(fVelocityXMin,fVelocityXMax), randomf(fVelocityYMin,fVelocityYMax), randomf(fVelocityZMin,fVelocityZMax) ) ); if( fOverrideSpeed != 0 ) { RageVec3Normalize( &m_vParticleVelocity[i], &m_vParticleVelocity[i] ); m_vParticleVelocity[i] *= fOverrideSpeed; } } } break; case TYPE_TILES: { RString sFile; ActorUtil::GetAttrPath( pNode, "File", sFile ); FixSlashesInPlace( sFile ); CollapsePath( sFile ); AutoActor s; s.Load( sFile ); if( m_fTilesSpacingX == -1 ) m_fTilesSpacingX = s->GetUnzoomedWidth(); if( m_fTilesSpacingY == -1 ) m_fTilesSpacingY = s->GetUnzoomedHeight(); m_iNumTilesWide = 2+(int)(SCREEN_WIDTH /m_fTilesSpacingX); m_iNumTilesHigh = 2+(int)(SCREEN_HEIGHT/m_fTilesSpacingY); unsigned NumSprites = m_iNumTilesWide * m_iNumTilesHigh; for( unsigned i=0; i<NumSprites; i++ ) { Actor* pSprite = ActorUtil::MakeActor( sFile, this ); if( pSprite == NULL ) continue; this->AddChild( pSprite ); pSprite->SetTextureWrapping( true ); // gets rid of some "cracks" pSprite->SetZoom( randomf(fZoomMin,fZoomMax) ); } } break; default: FAIL_M(ssprintf("Unrecognized layer type: %i", m_Type)); } bool bStartOnRandomFrame = false; pNode->GetAttrValue( "StartOnRandomFrame", bStartOnRandomFrame ); if( bStartOnRandomFrame ) { for( unsigned i=0; i<m_SubActors.size(); i++ ) m_SubActors[i]->SetState( RandomInt(m_SubActors[i]->GetNumStates()) ); } }
void BGAnimationLayer::LoadFromAniLayerFile( const RString& sPath ) { /* Generic BGAs are new. Animation directories with no INI are old and obsolete. * Don't combine them. */ RString lcPath = sPath; lcPath.MakeLower(); if( lcPath.find("usesongbg") != RString::npos ) { const Song* pSong = GAMESTATE->m_pCurSong; RString sSongBGPath; if( pSong && pSong->HasBackground() ) sSongBGPath = pSong->GetBackgroundPath(); else sSongBGPath = THEME->GetPathG("Common","fallback background"); Sprite* pSprite = new Sprite; pSprite->Load( Sprite::SongBGTexture(sSongBGPath) ); pSprite->StretchTo( FullScreenRectF ); this->AddChild( pSprite ); return; // this will ignore other effects in the file name } enum Effect { EFFECT_CENTER, EFFECT_STRETCH_STILL, EFFECT_STRETCH_SCROLL_LEFT, EFFECT_STRETCH_SCROLL_RIGHT, EFFECT_STRETCH_SCROLL_UP, EFFECT_STRETCH_SCROLL_DOWN, EFFECT_STRETCH_WATER, EFFECT_STRETCH_BUBBLE, EFFECT_STRETCH_TWIST, EFFECT_STRETCH_SPIN, EFFECT_PARTICLES_SPIRAL_OUT, EFFECT_PARTICLES_SPIRAL_IN, EFFECT_PARTICLES_FLOAT_UP, EFFECT_PARTICLES_FLOAT_DOWN, EFFECT_PARTICLES_FLOAT_LEFT, EFFECT_PARTICLES_FLOAT_RIGHT, EFFECT_PARTICLES_BOUNCE, EFFECT_TILE_STILL, EFFECT_TILE_SCROLL_LEFT, EFFECT_TILE_SCROLL_RIGHT, EFFECT_TILE_SCROLL_UP, EFFECT_TILE_SCROLL_DOWN, EFFECT_TILE_FLIP_X, EFFECT_TILE_FLIP_Y, EFFECT_TILE_PULSE, NUM_EFFECTS, // leave this at the end EFFECT_INVALID }; const RString EFFECT_STRING[NUM_EFFECTS] = { "center", "stretchstill", "stretchscrollleft", "stretchscrollright", "stretchscrollup", "stretchscrolldown", "stretchwater", "stretchbubble", "stretchtwist", "stretchspin", "particlesspiralout", "particlesspiralin", "particlesfloatup", "particlesfloatdown", "particlesfloatleft", "particlesfloatright", "particlesbounce", "tilestill", "tilescrollleft", "tilescrollright", "tilescrollup", "tilescrolldown", "tileflipx", "tileflipy", "tilepulse", }; Effect effect = EFFECT_CENTER; for( int i=0; i<NUM_EFFECTS; i++ ) if( lcPath.find(EFFECT_STRING[i]) != string::npos ) effect = (Effect)i; switch( effect ) { case EFFECT_CENTER: { m_Type = TYPE_SPRITE; Sprite* pSprite = new Sprite; this->AddChild( pSprite ); pSprite->Load( sPath ); pSprite->SetXY( SCREEN_CENTER_X, SCREEN_CENTER_Y ); } break; case EFFECT_STRETCH_STILL: case EFFECT_STRETCH_SCROLL_LEFT: case EFFECT_STRETCH_SCROLL_RIGHT: case EFFECT_STRETCH_SCROLL_UP: case EFFECT_STRETCH_SCROLL_DOWN: case EFFECT_STRETCH_WATER: case EFFECT_STRETCH_BUBBLE: case EFFECT_STRETCH_TWIST: { m_Type = TYPE_SPRITE; Sprite* pSprite = new Sprite; this->AddChild( pSprite ); RageTextureID ID(sPath); ID.bStretch = true; pSprite->Load( Sprite::SongBGTexture(ID) ); pSprite->StretchTo( FullScreenRectF ); pSprite->SetCustomTextureRect( RectF(0,0,1,1) ); switch( effect ) { case EFFECT_STRETCH_SCROLL_LEFT: m_fTexCoordVelocityX = +0.5f; m_fTexCoordVelocityY = 0; break; case EFFECT_STRETCH_SCROLL_RIGHT: m_fTexCoordVelocityX = -0.5f; m_fTexCoordVelocityY = 0; break; case EFFECT_STRETCH_SCROLL_UP: m_fTexCoordVelocityX = 0; m_fTexCoordVelocityY = +0.5f; break; case EFFECT_STRETCH_SCROLL_DOWN: m_fTexCoordVelocityX = 0; m_fTexCoordVelocityY = -0.5f; break; default: break; } } break; case EFFECT_STRETCH_SPIN: { m_Type = TYPE_SPRITE; Sprite* pSprite = new Sprite; this->AddChild( pSprite ); pSprite->Load( Sprite::SongBGTexture(sPath) ); const RectF StretchedFullScreenRectF( FullScreenRectF.left-200, FullScreenRectF.top-200, FullScreenRectF.right+200, FullScreenRectF.bottom+200 ); pSprite->ScaleToCover( StretchedFullScreenRectF ); pSprite->SetEffectSpin( RageVector3(0,0,60) ); } break; case EFFECT_PARTICLES_SPIRAL_OUT: case EFFECT_PARTICLES_SPIRAL_IN: case EFFECT_PARTICLES_FLOAT_UP: case EFFECT_PARTICLES_FLOAT_DOWN: case EFFECT_PARTICLES_FLOAT_LEFT: case EFFECT_PARTICLES_FLOAT_RIGHT: case EFFECT_PARTICLES_BOUNCE: { m_Type = TYPE_PARTICLES; Sprite s; s.Load( sPath ); int iSpriteArea = int( s.GetUnzoomedWidth()*s.GetUnzoomedHeight() ); const int iMaxArea = int(SCREEN_WIDTH*SCREEN_HEIGHT); int iNumParticles = iMaxArea / iSpriteArea; iNumParticles = min( iNumParticles, MAX_SPRITES ); for( int i=0; i<iNumParticles; i++ ) { Sprite* pSprite = new Sprite; this->AddChild( pSprite ); pSprite->Load( sPath ); pSprite->SetZoom( 0.7f + 0.6f*i/(float)iNumParticles ); switch( effect ) { case EFFECT_PARTICLES_BOUNCE: pSprite->SetX( randomf( GetGuardRailLeft(pSprite), GetGuardRailRight(pSprite) ) ); pSprite->SetY( randomf( GetGuardRailTop(pSprite), GetGuardRailBottom(pSprite) ) ); break; default: pSprite->SetX( randomf( GetOffScreenLeft(pSprite), GetOffScreenRight(pSprite) ) ); pSprite->SetY( randomf( GetOffScreenTop(pSprite), GetOffScreenBottom(pSprite) ) ); break; } switch( effect ) { case EFFECT_PARTICLES_FLOAT_UP: case EFFECT_PARTICLES_SPIRAL_OUT: m_vParticleVelocity.push_back( RageVector3( 0, -PARTICLE_SPEED*pSprite->GetZoom(), 0 ) ); break; case EFFECT_PARTICLES_FLOAT_DOWN: case EFFECT_PARTICLES_SPIRAL_IN: m_vParticleVelocity.push_back( RageVector3( 0, PARTICLE_SPEED*pSprite->GetZoom(), 0 ) ); break; case EFFECT_PARTICLES_FLOAT_LEFT: m_vParticleVelocity.push_back( RageVector3( -PARTICLE_SPEED*pSprite->GetZoom(), 0, 0 ) ); break; case EFFECT_PARTICLES_FLOAT_RIGHT: m_vParticleVelocity.push_back( RageVector3( +PARTICLE_SPEED*pSprite->GetZoom(), 0, 0 ) ); break; case EFFECT_PARTICLES_BOUNCE: m_bParticlesBounce = true; pSprite->SetZoom( 1 ); m_vParticleVelocity.push_back( RageVector3( randomf(), randomf(), 0 ) ); RageVec3Normalize( &m_vParticleVelocity[i], &m_vParticleVelocity[i] ); m_vParticleVelocity[i].x *= PARTICLE_SPEED; m_vParticleVelocity[i].y *= PARTICLE_SPEED; break; default: FAIL_M(ssprintf("Unrecognized layer effect: %i", effect)); } } } break; case EFFECT_TILE_STILL: case EFFECT_TILE_SCROLL_LEFT: case EFFECT_TILE_SCROLL_RIGHT: case EFFECT_TILE_SCROLL_UP: case EFFECT_TILE_SCROLL_DOWN: case EFFECT_TILE_FLIP_X: case EFFECT_TILE_FLIP_Y: case EFFECT_TILE_PULSE: { m_Type = TYPE_TILES; RageTextureID ID(sPath); ID.bStretch = true; Sprite s; s.Load( ID ); m_iNumTilesWide = 2+int(SCREEN_WIDTH /s.GetUnzoomedWidth()); m_iNumTilesWide = min( m_iNumTilesWide, MAX_TILES_WIDE ); m_iNumTilesHigh = 2+int(SCREEN_HEIGHT/s.GetUnzoomedHeight()); m_iNumTilesHigh = min( m_iNumTilesHigh, MAX_TILES_HIGH ); m_fTilesStartX = s.GetUnzoomedWidth() / 2; m_fTilesStartY = s.GetUnzoomedHeight() / 2; m_fTilesSpacingX = s.GetUnzoomedWidth(); m_fTilesSpacingY = s.GetUnzoomedHeight(); for( int x=0; x<m_iNumTilesWide; x++ ) { for( int y=0; y<m_iNumTilesHigh; y++ ) { Sprite* pSprite = new Sprite; this->AddChild( pSprite ); pSprite->Load( ID ); pSprite->SetTextureWrapping( true ); // gets rid of some "cracks" switch( effect ) { case EFFECT_TILE_STILL: break; case EFFECT_TILE_SCROLL_LEFT: m_fTileVelocityX = -PARTICLE_SPEED; break; case EFFECT_TILE_SCROLL_RIGHT: m_fTileVelocityX = +PARTICLE_SPEED; break; case EFFECT_TILE_SCROLL_UP: m_fTileVelocityY = -PARTICLE_SPEED; break; case EFFECT_TILE_SCROLL_DOWN: m_fTileVelocityY = +PARTICLE_SPEED; break; case EFFECT_TILE_FLIP_X: pSprite->SetEffectSpin( RageVector3(180,0,0) ); break; case EFFECT_TILE_FLIP_Y: pSprite->SetEffectSpin( RageVector3(0,180,0) ); break; case EFFECT_TILE_PULSE: pSprite->SetEffectPulse( 1, 0.3f, 1.f ); break; default: FAIL_M(ssprintf("Not a tile effect: %i", effect)); } } } } break; default: FAIL_M(ssprintf("Unrecognized layer effect: %i", effect)); } RString sHint = sPath; sHint.MakeLower(); if( sHint.find("cyclecolor") != RString::npos ) for( unsigned i=0; i<m_SubActors.size(); i++ ) m_SubActors[i]->SetEffectRainbow( 5 ); if( sHint.find("cyclealpha") != RString::npos ) for( unsigned i=0; i<m_SubActors.size(); i++ ) m_SubActors[i]->SetEffectDiffuseShift( 2, RageColor(1,1,1,1), RageColor(1,1,1,0) ); if( sHint.find("startonrandomframe") != RString::npos ) for( unsigned i=0; i<m_SubActors.size(); i++ ) m_SubActors[i]->SetState( RandomInt(m_SubActors[i]->GetNumStates()) ); if( sHint.find("dontanimate") != RString::npos ) for( unsigned i=0; i<m_SubActors.size(); i++ ) m_SubActors[i]->StopAnimating(); if( sHint.find("add") != RString::npos ) for( unsigned i=0; i<m_SubActors.size(); i++ ) m_SubActors[i]->SetBlendMode( BLEND_ADD ); }
// Draw Dancers if( DrawCelShaded ) { FOREACH_PlayerNumber( pn ) if( GAMESTATE->IsHumanPlayer(pn) ) m_pDancer[pn]->DrawCelShaded(); } else { DISPLAY->SetLighting( true ); DISPLAY->SetLightDirectional( 0, RageColor(0.5f,0.5f,0.5f,1), RageColor(1,1,1,1), RageColor(0,0,0,1), RageVector3(0, 0, 1) ); FOREACH_PlayerNumber( pn ) if( GAMESTATE->IsHumanPlayer(pn) ) m_pDancer[pn]->Draw(); DISPLAY->SetLightOff( 0 ); DISPLAY->SetLighting( false ); } } void BeginnerHelper::Step( PlayerNumber pn, int CSTEP ) { m_pDancer[pn]->StopTweening(); m_pDancer[pn]->SetRotationY( 0 ); // Make sure we're not still inside of a JUMPUD tween.
ScreenCredits::ScreenCredits( CString sName ) : ScreenAttract( sName ) { vector<Song*> arraySongs; SONGMAN->GetSongs( arraySongs ); SongUtil::SortSongPointerArrayByTitle( arraySongs ); // FIXME: Redo this screen with a BGA m_ScrollerBackgrounds.SetName( "Backgrounds" ); m_ScrollerBackgrounds.Load( BACKGROUNDS_SCROLL_SECONDS_PER_ITEM, 4, RageVector3(0, 0, 0), RageVector3(0, 0, 0), RageVector3(BACKGROUNDS_SPACING_X, BACKGROUNDS_SPACING_Y, 0), RageVector3(0, 0, 0) ); SET_XY( m_ScrollerBackgrounds ); this->AddChild( &m_ScrollerBackgrounds ); m_ScrollerFrames.SetName( "Backgrounds" ); m_ScrollerFrames.Load( BACKGROUNDS_SCROLL_SECONDS_PER_ITEM, 4, RageVector3(0, 0, 0), RageVector3(0, 0, 0), RageVector3(BACKGROUNDS_SPACING_X, BACKGROUNDS_SPACING_Y, 0), RageVector3(0, 0, 0) ); SET_XY( m_ScrollerFrames ); this->AddChild( &m_ScrollerFrames ); float fTime = 0; { for( int i=0; i<NUM_BACKGROUNDS; i++ ) { Song* pSong = NULL; for( int j=0; j<50; j++ ) { pSong = arraySongs[ rand()%arraySongs.size() ]; if( pSong->HasBackground() ) break; } Sprite* pBackground = new Sprite; pBackground->LoadBG( pSong->HasBackground() ? pSong->GetBackgroundPath() : THEME->GetPathToG("Common fallback background") ); pBackground->ScaleToClipped( BACKGROUNDS_WIDTH, BACKGROUNDS_HEIGHT ); m_ScrollerBackgrounds.AddChild( pBackground ); Sprite* pFrame = new Sprite; pFrame->Load( THEME->GetPathToG("ScreenCredits background frame") ); m_ScrollerFrames.AddChild( pFrame ); } const int iFirst = -2, iLast = NUM_BACKGROUNDS+2; m_ScrollerBackgrounds.SetCurrentAndDestinationItem( iFirst ); m_ScrollerBackgrounds.SetDestinationItem( iLast ); m_ScrollerFrames.SetCurrentAndDestinationItem( iFirst ); m_ScrollerFrames.SetDestinationItem( iLast ); fTime = max( fTime, BACKGROUNDS_SCROLL_SECONDS_PER_ITEM*(iLast-iFirst) ); } m_ScrollerTexts.SetName( "Texts" ); m_ScrollerTexts.Load( TEXTS_SCROLL_SECONDS_PER_ITEM, 40, RageVector3(0, 0, 0), RageVector3(0, 0, 0), RageVector3(TEXTS_SPACING_X, TEXTS_SPACING_Y, 0), RageVector3(0, 0, 0) ); SET_XY( m_ScrollerTexts ); this->AddChild( &m_ScrollerTexts ); { for( unsigned i=0; i<ARRAYSIZE(CREDIT_LINES); i++ ) { BitmapText* pText = new BitmapText; pText->LoadFromFont( THEME->GetPathToF("ScreenCredits titles") ); pText->SetText( CREDIT_LINES[i].text ); switch( CREDIT_LINES[i].colorIndex ) { case 1: pText->SetDiffuse( TEXTS_COLOR_INTRO ); break; case 2: pText->SetDiffuse( TEXTS_COLOR_HEADER ); break; case 0: pText->SetDiffuse( TEXTS_COLOR_NORMAL ); break; default: ASSERT(0); } pText->SetZoom( TEXTS_ZOOM ); m_ScrollerTexts.AddChild( pText ); } const int iFirst = -10, iLast = ARRAYSIZE(CREDIT_LINES)+10; m_ScrollerTexts.SetCurrentAndDestinationItem( iFirst ); m_ScrollerTexts.SetDestinationItem( iLast ); fTime = max( fTime, TEXTS_SCROLL_SECONDS_PER_ITEM*(iLast-iFirst) ); } m_Overlay.LoadFromAniDir( THEME->GetPathToB("ScreenCredits overlay") ); this->AddChild( &m_Overlay ); this->MoveToTail( &m_In ); // put it in the back so it covers up the stuff we just added this->MoveToTail( &m_Out ); // put it in the back so it covers up the stuff we just added this->ClearMessageQueue( SM_BeginFadingOut ); // ignore ScreenAttract's SecsToShow LOG->Trace("XXXXXXXXX %f", fTime); this->PostScreenMessage( SM_BeginFadingOut, fTime ); // this->PostScreenMessage( SM_BeginFadingOut, m_Background.GetLengthSeconds() ); SOUND->PlayOnceFromDir( ANNOUNCER->GetPathTo("credits") ); }
void RageVec3TransformNormal( RageVector3* pOut, const RageVector3* pV, const RageMatrix* pM ) { RageVector4 temp( pV->x, pV->y, pV->z, 0.0f ); // don't translate RageVec4TransformCoord( &temp, &temp, pM ); *pOut = RageVector3( temp.x, temp.y, temp.z ); }
void NoteDisplay::DrawHoldBottomCap( const TapNote& tn, int iCol, int iRow, bool bIsBeingHeld, float fYHead, float fYTail, int fYStep, float fPercentFadeToFail, float fColorScale, bool bGlow, float fYStartOffset, float fYEndOffset ) { // // Draw the bottom cap (always wavy) // StripBuffer queue; Sprite* pBottomCap = GetHoldBottomCapSprite( NoteRowToBeat(iRow), tn.subType == TapNote::hold_head_roll, bIsBeingHeld ); pBottomCap->SetZoom( ArrowEffects::GetZoom( m_pPlayerState ) ); // draw manually in small segments RageTexture* pTexture = pBottomCap->GetTexture(); const RectF *pRect = pBottomCap->GetCurrentTextureCoordRect(); DISPLAY->ClearAllTextures(); DISPLAY->SetTexture( 0, pTexture ); DISPLAY->SetBlendMode( BLEND_NORMAL ); DISPLAY->SetCullMode( CULL_NONE ); DISPLAY->SetTextureWrapping(false); const float fFrameWidth = pBottomCap->GetZoomedWidth(); const float fFrameHeight = pBottomCap->GetZoomedHeight(); const float fYCapTop = fYTail+cache->m_iStopDrawingHoldBodyOffsetFromTail; const float fYCapBottom = fYTail+cache->m_iStopDrawingHoldBodyOffsetFromTail+fFrameHeight; bool bReverse = m_pPlayerState->m_CurrentPlayerOptions.GetReversePercentForColumn(iCol) > 0.5f; if( bGlow ) fColorScale = 1; float fDrawYCapTop; float fDrawYCapBottom; { float fYStartPos = ArrowEffects::GetYPos( m_pPlayerState, iCol, fYStartOffset, m_fYReverseOffsetPixels ); float fYEndPos = ArrowEffects::GetYPos( m_pPlayerState, iCol, fYEndOffset, m_fYReverseOffsetPixels ); fDrawYCapTop = max( fYCapTop, bReverse ? fYEndPos : fYStartPos ); fDrawYCapBottom = min( fYCapBottom, bReverse ? fYStartPos : fYEndPos ); } bool bAllAreTransparent = true; bool bLast = false; // don't draw any part of the tail that is before the middle of the head float fY=max( fDrawYCapTop, fYHead ); for( ; !bLast; fY += fYStep ) { if( fY >= fDrawYCapBottom ) { fY = fDrawYCapBottom; bLast = true; } const float fYOffset = ArrowEffects::GetYOffsetFromYPos( m_pPlayerState, iCol, fY, m_fYReverseOffsetPixels ); const float fX = ArrowEffects::GetXPos( m_pPlayerState, iCol, fYOffset ); const float fZ = ArrowEffects::GetZPos( m_pPlayerState, iCol, fYOffset ); // XXX: Actor rotations use degrees, RageFastCos/Sin use radians. Convert here. const float fRotationY = ArrowEffects::GetRotationY( m_pPlayerState, fYOffset ) * PI/180; // if we're rotating, we need to modify the X and Z coords for the outer edges. const float fRotOffsetX = fFrameWidth/2 * RageFastCos(fRotationY); const float fRotOffsetZ = fFrameWidth/2 * RageFastSin(fRotationY); const float fXLeft = fX - fRotOffsetX; const float fXRight = fX + fRotOffsetX; const float fZLeft = fZ - fRotOffsetZ; const float fZRight = fZ + fRotOffsetZ; const float fTopDistFromTail = fY - fYCapTop; const float fTexCoordTop = SCALE( fTopDistFromTail, 0, fFrameHeight, pRect->top, pRect->bottom ); const float fTexCoordLeft = pRect->left; const float fTexCoordRight = pRect->right; const float fAlpha = ArrowGetAlphaOrGlow( bGlow, m_pPlayerState, iCol, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels ); const RageColor color = RageColor(fColorScale,fColorScale,fColorScale,fAlpha); if( fAlpha > 0 ) bAllAreTransparent = false; queue.v[0].p = RageVector3(fXLeft, fY, fZLeft); queue.v[0].c = color; queue.v[0].t = RageVector2(fTexCoordLeft, fTexCoordTop); queue.v[1].p = RageVector3(fXRight, fY, fZRight); queue.v[1].c = color; queue.v[1].t = RageVector2(fTexCoordRight, fTexCoordTop); queue.v+=2; if( queue.Free() < 2 ) { /* The queue is full. Render it, clear the buffer, and move back a step to * start off the quad strip again. */ if( !bAllAreTransparent ) queue.Draw(); queue.Init(); bAllAreTransparent = true; fY -= fYStep; } } if( !bAllAreTransparent ) queue.Draw(); }
void RageVec3ClearBounds( RageVector3 &mins, RageVector3 &maxs ) { mins = RageVector3( 999999, 999999, 999999 ); maxs = mins * -1; }
bool msAnimation::LoadMilkshapeAsciiBones( CString sAniName, CString sPath ) { FixSlashesInPlace(sPath); const CString sDir = Dirname( sPath ); RageFile f; if ( !f.Open(sPath) ) RageException::Throw( "Model:: Could not open \"%s\": %s", sPath.c_str(), f.GetError().c_str() ); CString sLine; int iLineNum = 0; msAnimation &Animation = *this; bool bLoaded = false; while( f.GetLine( sLine ) > 0 ) { iLineNum++; if (!strncmp (sLine, "//", 2)) continue; // // bones // int nNumBones = 0; if( sscanf (sLine, "Bones: %d", &nNumBones) != 1 ) continue; char szName[MS_MAX_NAME]; Animation.Bones.resize( nNumBones ); for( int i = 0; i < nNumBones; i++ ) { msBone& Bone = Animation.Bones[i]; // name if( f.GetLine( sLine ) <= 0 ) THROW; if (sscanf (sLine, "\"%[^\"]\"", szName) != 1) THROW; strcpy( Bone.szName, szName ); // parent if( f.GetLine( sLine ) <= 0 ) THROW; strcpy (szName, ""); sscanf (sLine, "\"%[^\"]\"", szName); strcpy( Bone.szParentName, szName ); // flags, position, rotation RageVector3 Position, Rotation; if( f.GetLine( sLine ) <= 0 ) THROW; int nFlags; if (sscanf (sLine, "%d %f %f %f %f %f %f", &nFlags, &Position[0], &Position[1], &Position[2], &Rotation[0], &Rotation[1], &Rotation[2]) != 7) { THROW; } Rotation = RadianToDegree(Rotation); Bone.nFlags = nFlags; memcpy( &Bone.Position, &Position, sizeof(Bone.Position) ); memcpy( &Bone.Rotation, &Rotation, sizeof(Bone.Rotation) ); // position key count if( f.GetLine( sLine ) <= 0 ) THROW; int nNumPositionKeys = 0; if (sscanf (sLine, "%d", &nNumPositionKeys) != 1) THROW; Bone.PositionKeys.resize( nNumPositionKeys ); for( int j = 0; j < nNumPositionKeys; ++j ) { if( f.GetLine( sLine ) <= 0 ) THROW; float fTime; if (sscanf (sLine, "%f %f %f %f", &fTime, &Position[0], &Position[1], &Position[2]) != 4) THROW; msPositionKey key; key.fTime = fTime; key.Position = RageVector3( Position[0], Position[1], Position[2] ); Bone.PositionKeys[j] = key; } // rotation key count if( f.GetLine( sLine ) <= 0 ) THROW; int nNumRotationKeys = 0; if (sscanf (sLine, "%d", &nNumRotationKeys) != 1) THROW; Bone.RotationKeys.resize( nNumRotationKeys ); for( int j = 0; j < nNumRotationKeys; ++j ) { if( f.GetLine( sLine ) <= 0 ) THROW; float fTime; if (sscanf (sLine, "%f %f %f %f", &fTime, &Rotation[0], &Rotation[1], &Rotation[2]) != 4) THROW; Rotation = RadianToDegree(Rotation); msRotationKey key; key.fTime = fTime; key.Rotation = RageVector3( Rotation[0], Rotation[1], Rotation[2] ); Bone.RotationKeys[j] = key; } } // Ignore "Frames:" in file. Calculate it ourself Animation.nTotalFrames = 0; for( int i = 0; i < (int)Animation.Bones.size(); i++ ) { msBone& Bone = Animation.Bones[i]; for( unsigned j = 0; j < Bone.PositionKeys.size(); ++j ) Animation.nTotalFrames = max( Animation.nTotalFrames, (int)Bone.PositionKeys[j].fTime ); for( unsigned j = 0; j < Bone.RotationKeys.size(); ++j ) Animation.nTotalFrames = max( Animation.nTotalFrames, (int)Bone.RotationKeys[j].fTime ); } } return bLoaded; }
void BGAnimation::LoadFromAniDir( CString sAniDir ) { Unload(); if( sAniDir.empty() ) return; if( sAniDir.Right(1) != "/" ) sAniDir += "/"; ASSERT_M( IsADirectory(sAniDir), sAniDir + " isn't a directory" ); CString sPathToIni = sAniDir + "BGAnimation.ini"; if( DoesFileExist(sPathToIni) ) { // This is a new style BGAnimation (using .ini) AddLayersFromAniDir( sAniDir, m_SubActors, m_bGeneric ); // TODO: Check for circular load IniFile ini; ini.ReadFile( sPathToIni ); if( !ini.GetValue( "BGAnimation", "LengthSeconds", m_fLengthSeconds ) ) { /* XXX: if m_bGeneric, simply constructing the BG layer won't run "On", * so at this point GetMaxTweenTimeLeft is probably 0 */ m_fLengthSeconds = this->GetTweenTimeLeft(); } bool bUseScroller; if( ini.GetValue( "BGAnimation", "UseScroller", bUseScroller ) && bUseScroller ) { // TODO: Move this into ActorScroller #define REQUIRED_GET_VALUE( szName, valueOut ) \ if( !ini.GetValue( "Scroller", szName, valueOut ) ) \ Dialog::OK( ssprintf("File '%s' is missing the value Scroller::%s", sPathToIni.c_str(), szName) ); float fSecondsPerItem = 1; int iNumItemsToDraw = 7; RageVector3 vRotationDegrees = RageVector3(0,0,0); RageVector3 vTranslateTerm0 = RageVector3(0,0,0); RageVector3 vTranslateTerm1 = RageVector3(0,0,0); RageVector3 vTranslateTerm2 = RageVector3(0,0,0); float fItemPaddingStart = 0; float fItemPaddingEnd = 0; REQUIRED_GET_VALUE( "SecondsPerItem", fSecondsPerItem ); REQUIRED_GET_VALUE( "NumItemsToDraw", iNumItemsToDraw ); REQUIRED_GET_VALUE( "RotationDegreesX", vRotationDegrees[0] ); REQUIRED_GET_VALUE( "RotationDegreesY", vRotationDegrees[1] ); REQUIRED_GET_VALUE( "RotationDegreesZ", vRotationDegrees[2] ); REQUIRED_GET_VALUE( "TranslateTerm0X", vTranslateTerm0[0] ); REQUIRED_GET_VALUE( "TranslateTerm0Y", vTranslateTerm0[1] ); REQUIRED_GET_VALUE( "TranslateTerm0Z", vTranslateTerm0[2] ); REQUIRED_GET_VALUE( "TranslateTerm1X", vTranslateTerm1[0] ); REQUIRED_GET_VALUE( "TranslateTerm1Y", vTranslateTerm1[1] ); REQUIRED_GET_VALUE( "TranslateTerm1Z", vTranslateTerm1[2] ); REQUIRED_GET_VALUE( "TranslateTerm2X", vTranslateTerm2[0] ); REQUIRED_GET_VALUE( "TranslateTerm2Y", vTranslateTerm2[1] ); REQUIRED_GET_VALUE( "TranslateTerm2Z", vTranslateTerm2[2] ); REQUIRED_GET_VALUE( "ItemPaddingStart", fItemPaddingStart ); REQUIRED_GET_VALUE( "ItemPaddingEnd", fItemPaddingEnd ); #undef REQUIRED_GET_VALUE ActorScroller::Load( fSecondsPerItem, iNumItemsToDraw, vRotationDegrees, vTranslateTerm0, vTranslateTerm1, vTranslateTerm2 ); ActorScroller::SetCurrentAndDestinationItem( int(-fItemPaddingStart) ); ActorScroller::SetDestinationItem( int(m_SubActors.size()-1+fItemPaddingEnd) ); } CString InitCommand; if( ini.GetValue( "BGAnimation", "InitCommand", InitCommand ) ) { /* There's an InitCommand. Run it now. This can be used to eg. change Z to * modify draw order between BGAs in a Foreground. Most things should be done * in metrics.ini commands, not here. */ this->Command( InitCommand ); } } else { // This is an old style BGAnimation (not using .ini) // loading a directory of layers CStringArray asImagePaths; ASSERT( sAniDir != "" ); GetDirListing( sAniDir+"*.png", asImagePaths, false, true ); GetDirListing( sAniDir+"*.jpg", asImagePaths, false, true ); GetDirListing( sAniDir+"*.gif", asImagePaths, false, true ); GetDirListing( sAniDir+"*.avi", asImagePaths, false, true ); GetDirListing( sAniDir+"*.mpg", asImagePaths, false, true ); GetDirListing( sAniDir+"*.mpeg", asImagePaths, false, true ); GetDirListing( sAniDir+"*.sprite", asImagePaths, false, true ); SortCStringArray( asImagePaths ); for( unsigned i=0; i<asImagePaths.size(); i++ ) { const CString sPath = asImagePaths[i]; if( Basename(sPath).Left(1) == "_" ) continue; // don't directly load files starting with an underscore BGAnimationLayer* pLayer = new BGAnimationLayer( m_bGeneric ); pLayer->LoadFromAniLayerFile( asImagePaths[i] ); AddChild( pLayer ); } } }
void NoteDisplay::DrawHoldBody( const TapNote& tn, int iCol, int iRow, bool bIsBeingHeld, float fYHead, float fYTail, int fYStep, float fPercentFadeToFail, float fColorScale, bool bGlow, float fYStartOffset, float fYEndOffset ) { // // Draw the body (always wavy) // StripBuffer queue; Sprite* pSprBody = GetHoldBodySprite( NoteRowToBeat(iRow), tn.subType == TapNote::hold_head_roll, bIsBeingHeld ); pSprBody->SetZoom( ArrowEffects::GetZoom( m_pPlayerState ) ); // draw manually in small segments RageTexture* pTexture = pSprBody->GetTexture(); const RectF *pRect = pSprBody->GetCurrentTextureCoordRect(); DISPLAY->ClearAllTextures(); DISPLAY->SetTexture( 0, pTexture ); DISPLAY->SetBlendMode( BLEND_NORMAL ); DISPLAY->SetCullMode( CULL_NONE ); DISPLAY->SetTextureWrapping( true ); const float fFrameWidth = pSprBody->GetZoomedWidth(); const float fFrameHeight = pSprBody->GetZoomedHeight(); const float fYBodyTop = fYHead + cache->m_iStartDrawingHoldBodyOffsetFromHead; const float fYBodyBottom = fYTail + cache->m_iStopDrawingHoldBodyOffsetFromTail; const bool bReverse = m_pPlayerState->m_CurrentPlayerOptions.GetReversePercentForColumn(iCol) > 0.5f; bool bAnchorToBottom = bReverse && cache->m_bFlipHeadAndTailWhenReverse; if( bGlow ) fColorScale = 1; /* Only draw the section that's within the range specified. If a hold note is * very long, don't process or draw the part outside of the range. Don't change * fYBodyTop or fYBodyBottom; they need to be left alone to calculate texture * coordinates. */ float fDrawYBodyTop; float fDrawYBodyBottom; { float fYStartPos = ArrowEffects::GetYPos( m_pPlayerState, iCol, fYStartOffset, m_fYReverseOffsetPixels ); float fYEndPos = ArrowEffects::GetYPos( m_pPlayerState, iCol, fYEndOffset, m_fYReverseOffsetPixels ); fDrawYBodyTop = max( fYBodyTop, bReverse ? fYEndPos : fYStartPos ); fDrawYBodyBottom = min( fYBodyBottom, bReverse ? fYStartPos : fYEndPos ); } // top to bottom bool bAllAreTransparent = true; bool bLast = false; float fVertTexCoordOffset = 0; for( float fY = fDrawYBodyTop; !bLast; fY += fYStep ) { if( fY >= fDrawYBodyBottom ) { fY = fDrawYBodyBottom; bLast = true; } const float fYOffset = ArrowEffects::GetYOffsetFromYPos( m_pPlayerState, iCol, fY, m_fYReverseOffsetPixels ); const float fX = ArrowEffects::GetXPos( m_pPlayerState, iCol, fYOffset ); const float fZ = ArrowEffects::GetZPos( m_pPlayerState, iCol, fYOffset ); // XXX: Actor rotations use degrees, RageFastCos/Sin use radians. Convert here. const float fRotationY = ArrowEffects::GetRotationY( m_pPlayerState, fYOffset ) * PI/180; // if we're rotating, we need to modify the X and Z coords for the outer edges. const float fRotOffsetX = fFrameWidth/2 * RageFastCos(fRotationY); const float fRotOffsetZ = fFrameWidth/2 * RageFastSin(fRotationY); const float fXLeft = fX - fRotOffsetX; const float fXRight = fX + fRotOffsetX; const float fZLeft = fZ - fRotOffsetZ; const float fZRight = fZ + fRotOffsetZ; const float fDistFromBodyBottom = fYBodyBottom - fY; const float fDistFromBodyTop = fY - fYBodyTop; float fTexCoordTop = SCALE( bAnchorToBottom ? fDistFromBodyTop : fDistFromBodyBottom, 0, fFrameHeight, pRect->bottom, pRect->top ); /* For very large hold notes, shift the texture coordinates to be near 0, so we * don't send very large values to the renderer. */ if( fY == fDrawYBodyTop ) // first fVertTexCoordOffset = floorf( fTexCoordTop ); fTexCoordTop -= fVertTexCoordOffset; const float fTexCoordLeft = pRect->left; const float fTexCoordRight = pRect->right; const float fAlpha = ArrowGetAlphaOrGlow( bGlow, m_pPlayerState, iCol, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels ); const RageColor color = RageColor(fColorScale,fColorScale,fColorScale,fAlpha); if( fAlpha > 0 ) bAllAreTransparent = false; queue.v[0].p = RageVector3(fXLeft, fY, fZLeft); queue.v[0].c = color; queue.v[0].t = RageVector2(fTexCoordLeft, fTexCoordTop); queue.v[1].p = RageVector3(fXRight, fY, fZRight); queue.v[1].c = color; queue.v[1].t = RageVector2(fTexCoordRight, fTexCoordTop); queue.v+=2; if( queue.Free() < 2 ) { /* The queue is full. Render it, clear the buffer, and move back a step to * start off the quad strip again. */ if( !bAllAreTransparent ) queue.Draw(); queue.Init(); bAllAreTransparent = true; fY -= fYStep; } } if( !bAllAreTransparent ) queue.Draw(); }
void Actor::HandleCommand( const ParsedCommand &command ) { HandleParams; const CString& sName = sParam(0); // Commands that go in the tweening queue: if ( sName=="sleep" ) Sleep( fParam(1) ); else if( sName=="linear" ) BeginTweening( fParam(1), TWEEN_LINEAR ); else if( sName=="accelerate" ) BeginTweening( fParam(1), TWEEN_ACCELERATE ); else if( sName=="decelerate" ) BeginTweening( fParam(1), TWEEN_DECELERATE ); else if( sName=="bouncebegin" ) BeginTweening( fParam(1), TWEEN_BOUNCE_BEGIN ); else if( sName=="bounceend" ) BeginTweening( fParam(1), TWEEN_BOUNCE_END ); else if( sName=="spring" ) BeginTweening( fParam(1), TWEEN_SPRING ); else if( sName=="stoptweening" ) { StopTweening(); BeginTweening( 0.0001f, TWEEN_LINEAR ); } // Why BeginT again? -Chris else if( sName=="finishtweening" ) FinishTweening(); else if( sName=="hurrytweening" ) HurryTweening( fParam(1) ); else if( sName=="x" ) SetX( fParam(1) ); else if( sName=="y" ) SetY( fParam(1) ); else if( sName=="z" ) SetZ( fParam(1) ); else if( sName=="addx" ) SetX( GetDestX()+fParam(1) ); else if( sName=="addy" ) SetY( GetDestY()+fParam(1) ); else if( sName=="addz" ) SetZ( GetDestZ()+fParam(1) ); else if( sName=="zoom" ) SetZoom( fParam(1) ); else if( sName=="zoomx" ) SetZoomX( fParam(1) ); else if( sName=="zoomy" ) SetZoomY( fParam(1) ); else if( sName=="zoomz" ) SetZoomZ( fParam(1) ); else if( sName=="zoomtowidth" ) ZoomToWidth( fParam(1) ); else if( sName=="zoomtoheight" ) ZoomToHeight( fParam(1) ); else if( sName=="stretchto" ) StretchTo( RectF( fParam(1), fParam(2), fParam(3), fParam(4) ) ); else if( sName=="cropleft" ) SetCropLeft( fParam(1) ); else if( sName=="croptop" ) SetCropTop( fParam(1) ); else if( sName=="cropright" ) SetCropRight( fParam(1) ); else if( sName=="cropbottom" ) SetCropBottom( fParam(1) ); else if( sName=="fadeleft" ) SetFadeLeft( fParam(1) ); else if( sName=="fadetop" ) SetFadeTop( fParam(1) ); else if( sName=="faderight" ) SetFadeRight( fParam(1) ); else if( sName=="fadebottom" ) SetFadeBottom( fParam(1) ); else if( sName=="fadecolor" ) SetFadeDiffuseColor( cParam(1) ); else if( sName=="diffuse" ) SetDiffuse( cParam(1) ); else if( sName=="diffuseleftedge" ) SetDiffuseLeftEdge( cParam(1) ); else if( sName=="diffuserightedge" ) SetDiffuseRightEdge( cParam(1) ); else if( sName=="diffusetopedge" ) SetDiffuseTopEdge( cParam(1) ); else if( sName=="diffusebottomedge" ) SetDiffuseBottomEdge( cParam(1) ); /* Add left/right/top/bottom for alpha if needed. */ else if( sName=="diffusealpha" ) SetDiffuseAlpha( fParam(1) ); else if( sName=="diffusecolor" ) SetDiffuseColor( cParam(1) ); else if( sName=="glow" ) SetGlow( cParam(1) ); else if( sName=="glowmode" ) { if(!sParam(1).CompareNoCase("whiten")) SetGlowMode( GLOW_WHITEN ); else if(!sParam(1).CompareNoCase("brighten")) SetGlowMode( GLOW_BRIGHTEN ); else ASSERT(0); } else if( sName=="rotationx" ) SetRotationX( fParam(1) ); else if( sName=="rotationy" ) SetRotationY( fParam(1) ); else if( sName=="rotationz" ) SetRotationZ( fParam(1) ); else if( sName=="heading" ) AddRotationH( fParam(1) ); else if( sName=="pitch" ) AddRotationP( fParam(1) ); else if( sName=="roll" ) AddRotationR( fParam(1) ); else if( sName=="shadowlength" ) SetShadowLength( fParam(1) ); else if( sName=="horizalign" ) SetHorizAlign( sParam(1) ); else if( sName=="vertalign" ) SetVertAlign( sParam(1) ); else if( sName=="diffuseblink" ) SetEffectDiffuseBlink(); else if( sName=="diffuseshift" ) SetEffectDiffuseShift(); else if( sName=="glowblink" ) SetEffectGlowBlink(); else if( sName=="glowshift" ) SetEffectGlowShift(); else if( sName=="rainbow" ) SetEffectRainbow(); else if( sName=="wag" ) SetEffectWag(); else if( sName=="bounce" ) SetEffectBounce(); else if( sName=="bob" ) SetEffectBob(); else if( sName=="pulse" ) SetEffectPulse(); else if( sName=="spin" ) SetEffectSpin(); else if( sName=="vibrate" ) SetEffectVibrate(); else if( sName=="stopeffect" ) SetEffectNone(); else if( sName=="effectcolor1" ) SetEffectColor1( cParam(1) ); else if( sName=="effectcolor2" ) SetEffectColor2( cParam(1) ); else if( sName=="effectperiod" ) SetEffectPeriod( fParam(1) ); else if( sName=="effectoffset" ) SetEffectOffset( fParam(1) ); else if( sName=="effectdelay" ) SetEffectDelay( fParam(1) ); else if( sName=="effectclock" ) SetEffectClock( sParam(1) ); else if( sName=="effectmagnitude" ) SetEffectMagnitude( RageVector3(fParam(1),fParam(2),fParam(3)) ); else if( sName=="scaletocover" ) { RectI R(iParam(1), iParam(2), iParam(3), iParam(4)); ScaleToCover(R); } else if( sName=="scaletofit" ) { RectI R(iParam(1), iParam(2), iParam(3), iParam(4)); ScaleToFitInside(R); } // Commands that take effect immediately (ignoring the tweening queue): else if( sName=="animate" ) EnableAnimation( bParam(1) ); else if( sName=="setstate" ) SetState( iParam(1) ); else if( sName=="texturewrapping" ) SetTextureWrapping( bParam(1) ); else if( sName=="additiveblend" ) SetBlendMode( bParam(1) ? BLEND_ADD : BLEND_NORMAL ); else if( sName=="blend" ) SetBlendMode( sParam(1) ); else if( sName=="zbuffer" ) SetUseZBuffer( bParam(1) ); else if( sName=="ztest" ) SetZTestMode( bParam(1)?ZTEST_WRITE_ON_PASS:ZTEST_OFF ); else if( sName=="ztestmode" ) SetZTestMode( sParam(1) ); else if( sName=="zwrite" ) SetZWrite( bParam(1) ); else if( sName=="clearzbuffer" ) SetClearZBuffer( bParam(1) ); else if( sName=="backfacecull" ) SetCullMode( bParam(1) ? CULL_BACK : CULL_NONE ); else if( sName=="cullmode" ) SetCullMode( sParam(1) ); else if( sName=="hidden" ) SetHidden( bParam(1) ); else if( sName=="hibernate" ) SetHibernate( fParam(1) ); else if( sName=="draworder" ) SetDrawOrder( iParam(1) ); else if( sName=="playcommand" ) PlayCommand( sParam(1) ); else if( sName=="queuecommand" ) { ParsedCommand newcommand = command; newcommand.vTokens.erase( newcommand.vTokens.begin() ); QueueCommand( newcommand ); return; // don't do parameter number checking } /* These are commands intended for a Sprite commands, but they will get * sent to all sub-actors (which aren't necessarily Sprites) on * GainFocus and LoseFocus. So, don't run CheckHandledParams * on these commands. */ else if( sName=="customtexturerect" || sName=="texcoordvelocity" || sName=="scaletoclipped" || sName=="stretchtexcoords" || sName=="position" || sName=="loop" || sName=="play" || sName=="pause" || sName=="rate" ) return; else { CString sError = ssprintf( "Actor::HandleCommand: Unrecognized command name '%s'.", sName.c_str() ); LOG->Warn( sError ); Dialog::OK( sError ); } CheckHandledParams; }
void Sprite::DrawTexture( const TweenState *state ) { Actor::SetGlobalRenderStates(); // set Actor-specified render states RectF crop = state->crop; // bail if cropped all the way if( crop.left + crop.right >= 1 || crop.top + crop.bottom >= 1 ) return; // use m_temp_* variables to draw the object RectF quadVerticies; quadVerticies.left = -m_size.x/2.0f; quadVerticies.right = +m_size.x/2.0f; quadVerticies.top = -m_size.y/2.0f; quadVerticies.bottom = +m_size.y/2.0f; /* Don't draw anything outside of the texture's image area. Texels outside * of the image area aren't guaranteed to be initialized. */ /* HACK: Clamp the crop values. It would be more accurate to clip the * vertices so that the diffuse value is adjusted. */ CLAMP( crop.left, 0, 1 ); CLAMP( crop.right, 0, 1 ); CLAMP( crop.top, 0, 1 ); CLAMP( crop.bottom, 0, 1 ); RectF croppedQuadVerticies = quadVerticies; #define IF_CROP_POS(side,opp_side) \ if(state->crop.side!=0) \ croppedQuadVerticies.side = \ SCALE( crop.side, 0.f, 1.f, quadVerticies.side, quadVerticies.opp_side ) IF_CROP_POS( left, right ); IF_CROP_POS( top, bottom ); IF_CROP_POS( right, left ); IF_CROP_POS( bottom, top ); static RageSpriteVertex v[4]; v[0].p = RageVector3( croppedQuadVerticies.left, croppedQuadVerticies.top, 0 ); // top left v[1].p = RageVector3( croppedQuadVerticies.left, croppedQuadVerticies.bottom, 0 ); // bottom left v[2].p = RageVector3( croppedQuadVerticies.right, croppedQuadVerticies.bottom, 0 ); // bottom right v[3].p = RageVector3( croppedQuadVerticies.right, croppedQuadVerticies.top, 0 ); // top right if( m_bUsingCustomPosCoords ) { for( int i=0; i < 4; ++i) { v[i].p.x+= m_CustomPosCoords[i*2]; v[i].p.y+= m_CustomPosCoords[(i*2)+1]; } } DISPLAY->ClearAllTextures(); DISPLAY->SetTexture( TextureUnit_1, m_pTexture? m_pTexture->GetTexHandle():0 ); // Must call this after setting the texture or else texture // parameters have no effect. Actor::SetTextureRenderStates(); // set Actor-specified render states DISPLAY->SetEffectMode( m_EffectMode ); if( m_pTexture ) { float f[8]; GetActiveTextureCoords( f ); if( state->crop.left || state->crop.right || state->crop.top || state->crop.bottom ) { RageVector2 texCoords[4] = { RageVector2( f[0], f[1] ), // top left RageVector2( f[2], f[3] ), // bottom left RageVector2( f[4], f[5] ), // bottom right RageVector2( f[6], f[7] ) // top right }; for( int i = 0; i < 4; ++i ) { RageSpriteVertex *pVert = &v[i]; float fTopX = SCALE( pVert->p.x, quadVerticies.left, quadVerticies.right, texCoords[0].x, texCoords[3].x ); float fBottomX = SCALE( pVert->p.x, quadVerticies.left, quadVerticies.right, texCoords[1].x, texCoords[2].x ); pVert->t.x = SCALE( pVert->p.y, quadVerticies.top, quadVerticies.bottom, fTopX, fBottomX ); float fLeftY = SCALE( pVert->p.y, quadVerticies.top, quadVerticies.bottom, texCoords[0].y, texCoords[1].y ); float fRightY = SCALE( pVert->p.y, quadVerticies.top, quadVerticies.bottom, texCoords[3].y, texCoords[2].y ); pVert->t.y = SCALE( pVert->p.x, quadVerticies.left, quadVerticies.right, fLeftY, fRightY ); } } else { v[0].t = RageVector2( f[0], f[1] ); // top left v[1].t = RageVector2( f[2], f[3] ); // bottom left v[2].t = RageVector2( f[4], f[5] ); // bottom right v[3].t = RageVector2( f[6], f[7] ); // top right } } else { // Just make sure we don't throw NaN/INF at the renderer: for( unsigned i = 0; i < 4; ++i ) v[i].t.x = v[i].t.y = 0; } // Draw if we're not fully transparent if( state->diffuse[0].a > 0 || state->diffuse[1].a > 0 || state->diffuse[2].a > 0 || state->diffuse[3].a > 0 ) { DISPLAY->SetTextureMode( TextureUnit_1, TextureMode_Modulate ); // render the shadow if( m_fShadowLengthX != 0 || m_fShadowLengthY != 0 ) { DISPLAY->PushMatrix(); DISPLAY->TranslateWorld( m_fShadowLengthX, m_fShadowLengthY, 0 ); // shift by 5 units RageColor c = m_ShadowColor; c.a *= state->diffuse[0].a; v[0].c = v[1].c = v[2].c = v[3].c = c; // semi-transparent black DISPLAY->DrawQuad( v ); DISPLAY->PopMatrix(); } // render the diffuse pass v[0].c = state->diffuse[0]; // top left v[1].c = state->diffuse[2]; // bottom left v[2].c = state->diffuse[3]; // bottom right v[3].c = state->diffuse[1]; // top right DISPLAY->DrawQuad( v ); } // render the glow pass if( state->glow.a > 0.0001f ) { DISPLAY->SetTextureMode( TextureUnit_1, TextureMode_Glow ); v[0].c = v[1].c = v[2].c = v[3].c = state->glow; DISPLAY->DrawQuad( v ); } DISPLAY->SetEffectMode( EffectMode_Normal ); }
void GrooveRadar::GrooveRadarValueMap::DrawPrimitives() { ActorFrame::DrawPrimitives(); // draw radar filling const float fRadius = GetUnzoomedWidth()/2.0f*1.1f; DISPLAY->ClearAllTextures(); DISPLAY->SetTextureMode( TextureUnit_1, TextureMode_Modulate ); RageSpriteVertex v[12]; // needed to draw 5 fan primitives and 10 strip primitives // xxx: We could either make the values invisible or draw a dot // (simulating real DDR). TODO: Make that choice up to the themer. -aj if( !m_bValuesVisible ) return; // use a fan to draw the volume RageColor color = this->m_pTempState->diffuse[0]; color.a = 0.5f; v[0].p = RageVector3( 0, 0, 0 ); RageColor midcolor = color; midcolor.a = RADAR_CENTER_ALPHA; v[0].c = midcolor; v[1].c = color; for( int i=0; i<NUM_SHOWN_RADAR_CATEGORIES+1; i++ ) // do one extra to close the fan { const int c = i%NUM_SHOWN_RADAR_CATEGORIES; const float fDistFromCenter = ( m_fValuesOld[c] * (1-m_PercentTowardNew) + m_fValuesNew[c] * m_PercentTowardNew + 0.07f ) * fRadius; const float fRotation = RADAR_VALUE_ROTATION(i); const float fX = RageFastCos(fRotation) * fDistFromCenter; const float fY = -RageFastSin(fRotation) * fDistFromCenter; v[1+i].p = RageVector3( fX, fY, 0 ); v[1+i].c = v[1].c; } DISPLAY->DrawFan( v, NUM_SHOWN_RADAR_CATEGORIES+2 ); // use a line loop to draw the thick line for( int i=0; i<=NUM_SHOWN_RADAR_CATEGORIES; i++ ) { const int c = i%NUM_SHOWN_RADAR_CATEGORIES; const float fDistFromCenter = ( m_fValuesOld[c] * (1-m_PercentTowardNew) + m_fValuesNew[c] * m_PercentTowardNew + 0.07f ) * fRadius; const float fRotation = RADAR_VALUE_ROTATION(i); const float fX = RageFastCos(fRotation) * fDistFromCenter; const float fY = -RageFastSin(fRotation) * fDistFromCenter; v[i].p = RageVector3( fX, fY, 0 ); v[i].c = this->m_pTempState->diffuse[0]; } // TODO: Add this back in -Chris // switch( PREFSMAN->m_iPolygonRadar ) // { // case 0: DISPLAY->DrawLoop_LinesAndPoints( v, NUM_SHOWN_RADAR_CATEGORIES, RADAR_EDGE_WIDTH ); break; // case 1: DISPLAY->DrawLoop_Polys( v, NUM_SHOWN_RADAR_CATEGORIES, RADAR_EDGE_WIDTH ); break; // default: // case -1: DISPLAY->DrawLineStrip( v, NUM_SHOWN_RADAR_CATEGORIES+1, RADAR_EDGE_WIDTH ); // break; // } }
void BitmapText::BuildChars() { /* If we don't have a font yet, we'll do this when it loads. */ if( m_pFont == NULL ) return; /* calculate line lengths and widths */ m_size.x = 0; m_iLineWidths.clear(); for( unsigned l=0; l<m_wTextLines.size(); l++ ) // for each line { m_iLineWidths.push_back(m_pFont->GetLineWidthInSourcePixels( m_wTextLines[l] )); m_size.x = max( m_size.x, m_iLineWidths.back() ); } m_aVertices.clear(); m_pTextures.clear(); if( m_wTextLines.empty() ) return; m_size.y = float(m_pFont->GetHeight() * m_wTextLines.size()); int MinSpacing = 0; /* The height (from the origin to the baseline): */ int Padding = max(m_pFont->GetLineSpacing(), MinSpacing) - m_pFont->GetHeight(); /* There's padding between every line: */ m_size.y += Padding * (m_wTextLines.size()-1); int iY; // the top position of the first row of characters switch( m_VertAlign ) { case align_top: iY = 0; break; case align_middle: iY = -(int)roundf(m_size.y/2.0f); break; case align_bottom: iY = -(int)m_size.y; break; default: ASSERT( false ); return; } for( unsigned i=0; i<m_wTextLines.size(); i++ ) // foreach line { iY += m_pFont->GetHeight(); const wstring &szLine = m_wTextLines[i]; const int iLineWidth = m_iLineWidths[i]; int iX; switch( m_HorizAlign ) { case align_left: iX = 0; break; case align_center: iX = -(int)roundf(iLineWidth/2.0f); break; case align_right: iX = -iLineWidth; break; default: ASSERT( false ); return; } for( unsigned j=0; j<szLine.size(); j++ ) // for each character in the line { RageSpriteVertex v[4]; const glyph &g = m_pFont->GetGlyph(szLine[j]); /* set vertex positions */ v[0].p = RageVector3( iX+g.m_fHshift, iY+g.m_pPage->m_fVshift, 0 ); // top left v[1].p = RageVector3( iX+g.m_fHshift, iY+g.m_pPage->m_fVshift+g.m_fHeight, 0 ); // bottom left v[2].p = RageVector3( iX+g.m_fHshift+g.m_fWidth, iY+g.m_pPage->m_fVshift+g.m_fHeight, 0 ); // bottom right v[3].p = RageVector3( iX+g.m_fHshift+g.m_fWidth, iY+g.m_pPage->m_fVshift, 0 ); // top right /* Advance the cursor. */ iX += g.m_iHadvance; /* set texture coordinates */ v[0].t = RageVector2( g.m_TexRect.left, g.m_TexRect.top ); v[1].t = RageVector2( g.m_TexRect.left, g.m_TexRect.bottom ); v[2].t = RageVector2( g.m_TexRect.right, g.m_TexRect.bottom ); v[3].t = RageVector2( g.m_TexRect.right, g.m_TexRect.top ); m_aVertices.insert( m_aVertices.end(), &v[0], &v[4] ); m_pTextures.push_back( g.GetTexture() ); } /* The amount of padding a line needs: */ iY += Padding; } }
void BitmapText::BuildChars() { // If we don't have a font yet, we'll do this when it loads. if( m_pFont == NULL ) return; // calculate line lengths and widths m_size.x = 0; m_iLineWidths.clear(); for( unsigned l=0; l<m_wTextLines.size(); l++ ) // for each line { m_iLineWidths.push_back(m_pFont->GetLineWidthInSourcePixels( m_wTextLines[l] )); m_size.x = max( m_size.x, m_iLineWidths.back() ); } /* Ensure that the width is always even. This maintains pixel alignment; * fX below will always be an integer. */ m_size.x = QuantizeUp( m_size.x, 2.0f ); m_aVertices.clear(); m_vpFontPageTextures.clear(); if( m_wTextLines.empty() ) return; m_size.y = float(m_pFont->GetHeight() * m_wTextLines.size()); // The height (from the origin to the baseline): int iPadding = m_pFont->GetLineSpacing() - m_pFont->GetHeight(); iPadding += m_iVertSpacing; // There's padding between every line: m_size.y += iPadding * int(m_wTextLines.size()-1); // the top position of the first row of characters int iY = lrintf(-m_size.y/2.0f); for( unsigned i=0; i<m_wTextLines.size(); i++ ) // foreach line { iY += m_pFont->GetHeight(); wstring sLine = m_wTextLines[i]; if( m_pFont->IsRightToLeft() ) reverse( sLine.begin(), sLine.end() ); const int iLineWidth = m_iLineWidths[i]; float fX = SCALE( m_fHorizAlign, 0.0f, 1.0f, -m_size.x/2.0f, +m_size.x/2.0f - iLineWidth ); int iX = lrintf( fX ); for( unsigned j = 0; j < sLine.size(); ++j ) { RageSpriteVertex v[4]; const glyph &g = m_pFont->GetGlyph( sLine[j] ); if( m_pFont->IsRightToLeft() ) iX -= g.m_iHadvance; // set vertex positions v[0].p = RageVector3( iX+g.m_fHshift, iY+g.m_pPage->m_fVshift, 0 ); // top left v[1].p = RageVector3( iX+g.m_fHshift, iY+g.m_pPage->m_fVshift+g.m_fHeight, 0 ); // bottom left v[2].p = RageVector3( iX+g.m_fHshift+g.m_fWidth, iY+g.m_pPage->m_fVshift+g.m_fHeight, 0 ); // bottom right v[3].p = RageVector3( iX+g.m_fHshift+g.m_fWidth, iY+g.m_pPage->m_fVshift, 0 ); // top right // Advance the cursor. iX += g.m_iHadvance; // set texture coordinates v[0].t = RageVector2( g.m_TexRect.left, g.m_TexRect.top ); v[1].t = RageVector2( g.m_TexRect.left, g.m_TexRect.bottom ); v[2].t = RageVector2( g.m_TexRect.right, g.m_TexRect.bottom ); v[3].t = RageVector2( g.m_TexRect.right, g.m_TexRect.top ); m_aVertices.insert( m_aVertices.end(), &v[0], &v[4] ); m_vpFontPageTextures.push_back( g.GetFontPageTextures() ); } // The amount of padding a line needs: iY += iPadding; } if( m_bUsingDistortion ) { int iSeed = lrintf( RageTimer::GetTimeSinceStartFast()*500000.0f ); RandomGen rnd( iSeed ); for(unsigned int i= 0; i < m_aVertices.size(); i+=4) { float w= m_aVertices[i+2].p.x - m_aVertices[i].p.x; float h= m_aVertices[i+2].p.y - m_aVertices[i].p.y; for(unsigned int ioff= 0; ioff < 4; ++ioff) { m_aVertices[i+ioff].p.x += ((rnd()%9) / 8.0f - .5f) * m_fDistortion * w; m_aVertices[i+ioff].p.y += ((rnd()%9) / 8.0f - .5f) * m_fDistortion * h; } } } }