diff --git a/src/CubicSpline.cpp b/src/CubicSpline.cpp index cf38c462f7..685453930b 100644 --- a/src/CubicSpline.cpp +++ b/src/CubicSpline.cpp @@ -269,7 +269,7 @@ void CubicSpline::set_results(size_t last, vector& diagonals, vector max_t) { t-= max_t; } + while(t < 0.0f) { t+= max_t; } } int flort= static_cast(t); if(flort < 0) @@ -303,12 +305,12 @@ void CubicSpline::resize(size_t s) m_points.resize(s); } -size_t CubicSpline::size() +size_t CubicSpline::size() const { return m_points.size(); } -bool CubicSpline::empty() +bool CubicSpline::empty() const { return m_points.empty(); } @@ -335,9 +337,9 @@ void CubicSplineN::solve() m_dirty= false; } -void CubicSplineN::evaluate(float t, vector& v) +void CubicSplineN::evaluate(float t, vector& v) const { - for(spline_cont_t::iterator spline= m_splines.begin(); + for(spline_cont_t::const_iterator spline= m_splines.begin(); spline != m_splines.end(); ++spline) { v.push_back(spline->evaluate(t, loop)); @@ -364,7 +366,7 @@ void CubicSplineN::resize(size_t s) m_dirty= true; } -size_t CubicSplineN::size() +size_t CubicSplineN::size() const { if(!m_splines.empty()) { @@ -373,7 +375,7 @@ size_t CubicSplineN::size() return 0; } -bool CubicSplineN::empty() +bool CubicSplineN::empty() const { return m_splines.empty() || m_splines[0].empty(); } @@ -384,7 +386,7 @@ void CubicSplineN::redimension(size_t d) m_dirty= true; } -size_t CubicSplineN::dimension() +size_t CubicSplineN::dimension() const { return m_splines.size(); } @@ -440,7 +442,7 @@ struct LunaCubicSplineN : Luna { luaL_error(L, "Cannot set spline point at index less than 1."); } - if(i >= p->size()) + if(static_cast(i) >= p->size()) { luaL_error(L, "Cannot set spline point at index greater than size."); } diff --git a/src/CubicSpline.h b/src/CubicSpline.h index 1b5e16e322..2f5bd74dae 100644 --- a/src/CubicSpline.h +++ b/src/CubicSpline.h @@ -9,11 +9,11 @@ struct CubicSpline { void solve_looped(); void solve_straight(); - float evaluate(float t, bool loop); + float evaluate(float t, bool loop) const; void set_point(size_t i, float v); void resize(size_t s); - size_t size(); - bool empty(); + size_t size() const; + bool empty() const; private: bool check_minimum_size(); void prep_inner(size_t last, vector& results); @@ -29,16 +29,16 @@ private: struct CubicSplineN { CubicSplineN() - :m_dirty(true), m_owned_by_actor(false) + :m_owned_by_actor(false), m_dirty(true) {} void solve(); - void evaluate(float t, vector& v); + void evaluate(float t, vector& v) const; void set_point(size_t i, vector const& v); void resize(size_t s); - size_t size(); + size_t size() const; void redimension(size_t d); - size_t dimension(); - bool empty(); + size_t dimension() const; + bool empty() const; typedef vector spline_cont_t; bool loop; bool m_owned_by_actor; diff --git a/src/GhostArrowRow.cpp b/src/GhostArrowRow.cpp index 2afe66e1e0..70c49da3a3 100644 --- a/src/GhostArrowRow.cpp +++ b/src/GhostArrowRow.cpp @@ -42,6 +42,7 @@ void GhostArrowRow::SetColumnRenderers(vector& renderers) { m_Ghost[c]->SetFakeParent(&(renderers[c])); } + m_renderers= &renderers; } GhostArrowRow::~GhostArrowRow() @@ -55,15 +56,17 @@ void GhostArrowRow::Update( float fDeltaTime ) { for( unsigned c=0; c spline_pos; + (*m_renderers)[c].m_spline.evaluate((*m_renderers)[c].m_receptor_t, spline_pos); m_Ghost[c]->Update( fDeltaTime ); float fX = ArrowEffects::GetXPos( m_pPlayerState, c, 0 ); float fY = ArrowEffects::GetYPos( m_pPlayerState, c, 0, m_fYReverseOffsetPixels ); float fZ = ArrowEffects::GetZPos( m_pPlayerState, c, 0 ); - m_Ghost[c]->SetX( fX ); - m_Ghost[c]->SetY( fY ); - m_Ghost[c]->SetZ( fZ ); + m_Ghost[c]->SetX( fX + spline_pos[0] ); + m_Ghost[c]->SetY( fY + spline_pos[1] ); + m_Ghost[c]->SetZ( fZ + spline_pos[2] ); const float fRotation = ArrowEffects::ReceptorGetRotationZ( m_pPlayerState ); m_Ghost[c]->SetRotationZ( fRotation ); diff --git a/src/GhostArrowRow.h b/src/GhostArrowRow.h index c091b04a81..d2dc96e1b3 100644 --- a/src/GhostArrowRow.h +++ b/src/GhostArrowRow.h @@ -26,6 +26,7 @@ protected: float m_fYReverseOffsetPixels; const PlayerState* m_pPlayerState; + vector const* m_renderers; vector m_Ghost; vector m_bHoldShowing; vector m_bLastHoldShowing; diff --git a/src/NoteDisplay.cpp b/src/NoteDisplay.cpp index a9fe88813c..1e7d736933 100644 --- a/src/NoteDisplay.cpp +++ b/src/NoteDisplay.cpp @@ -342,6 +342,13 @@ bool NoteDisplay::IsOnScreen( float fBeat, int iCol, int iDrawDistanceAfterTarge return true; } +float NoteDisplay::BeatToTValue(CommonColumnRenderArgs const& args, float beat) const +{ + float song_beat= m_pPlayerState->GetDisplayedPosition().m_fSongBeatVisible; + float relative_beat= beat - song_beat; + return (relative_beat / args.beats_per_t) - args.receptor_t; +} + bool NoteDisplay::DrawHoldsInRange(CommonColumnRenderArgs const& args, int column, vector const& tap_set) { @@ -398,12 +405,9 @@ bool NoteDisplay::DrawHoldsInRange(CommonColumnRenderArgs const& args, end_row < *args.selection_end_marker); } - DrawHold(tn, column, start_row, is_holding, result, + DrawHold(tn, args, column, start_row, is_holding, result, use_addition_coloring, - in_selection_range ? args.selection_glow : args.fail_fade, - m_fYReverseOffsetPixels, (float)args.draw_pixels_after_targets, - (float)args.draw_pixels_before_targets, - args.draw_pixels_before_targets, args.fade_before_targets); + in_selection_range ? args.selection_glow : args.fail_fade); bool note_upcoming = NoteRowToBeat(start_row) > m_pPlayerState->GetDisplayedPosition().m_fSongBeat; @@ -485,12 +489,10 @@ bool NoteDisplay::DrawTapsInRange(CommonColumnRenderArgs const& args, bool is_addition = (tn.source == TapNoteSource_Addition); bool hopo_possible = (tn.bHopoPossible); bool use_addition_coloring = is_addition || hopo_possible; - DrawTap(tn, column, NoteRowToVisibleBeat(m_pPlayerState, tap_row), + DrawTap(tn, args, column, NoteRowToVisibleBeat(m_pPlayerState, tap_row), hold_begins_on_this_beat, roll_begins_on_this_beat, use_addition_coloring, - in_selection_range ? args.selection_glow : args.fail_fade, - m_fYReverseOffsetPixels, args.draw_pixels_after_targets, - args.draw_pixels_before_targets, args.fade_before_targets); + in_selection_range ? args.selection_glow : args.fail_fade); any_upcoming |= NoteRowToBeat(tap_row) > m_pPlayerState->GetDisplayedPosition().m_fSongBeat; @@ -611,12 +613,12 @@ struct StripBuffer int Free() const { return size - Used(); } }; -void NoteDisplay::DrawHoldPart( vector &vpSpr, int iCol, int fYStep, float fPercentFadeToFail, float fColorScale, bool bGlow, - float fDrawDistanceAfterTargetsPixels, float fDrawDistanceBeforeTargetsPixels, float fFadeInPercentOfDrawFar, - float fOverlappedTime, - float fYTop, float fYBottom, - float fYStartPos, float fYEndPos, - bool bWrapping, bool bAnchorToTop, bool bFlipTextureVertically ) +void NoteDisplay::DrawHoldPart(vector &vpSpr, + CommonColumnRenderArgs const& args, int iCol, int fYStep, + float fPercentFadeToFail, float fColorScale, bool bGlow, + float fOverlappedTime, float fYTop, float fYBottom, float fYStartPos, + float fYEndPos, bool bWrapping, bool bAnchorToTop, + bool bFlipTextureVertically, float top_t, float bottom_t) { ASSERT( !vpSpr.empty() ); @@ -681,12 +683,20 @@ void NoteDisplay::DrawHoldPart( vector &vpSpr, int iCol, int fYStep, fl bLast = true; } + float curtsy= top_t; + if(top_t != bottom_t) + { + curtsy= SCALE(fY, fYTop, fYBottom, top_t, bottom_t); + } + vector spline_pos; + args.spline->evaluate(curtsy, spline_pos); + const float fYOffset = ArrowEffects::GetYOffsetFromYPos( m_pPlayerState, iCol, fY, m_fYReverseOffsetPixels ); - const float fZ = ArrowEffects::GetZPos( m_pPlayerState, iCol, fYOffset ); + const float fZ = ArrowEffects::GetZPos( m_pPlayerState, iCol, fYOffset ) + spline_pos[2]; const float fFrameWidthScale = ArrowEffects::GetFrameWidthScale( m_pPlayerState, fYOffset, fOverlappedTime ); const float fScaledFrameWidth = fFrameWidth * fFrameWidthScale; - float fX = ArrowEffects::GetXPos( m_pPlayerState, iCol, fYOffset ); + float fX = ArrowEffects::GetXPos( m_pPlayerState, iCol, fYOffset ) + spline_pos[0]; // XXX: Actor rotations use degrees, RageFastCos/Sin use radians. Convert here. const float fRotationY = ArrowEffects::GetRotationY( m_pPlayerState, fYOffset ) * PI/180; @@ -708,15 +718,15 @@ void NoteDisplay::DrawHoldPart( vector &vpSpr, int iCol, int fYStep, fl float fTexCoordTop = SCALE( fDistFromTop, 0, fFrameHeight, rect.top, rect.bottom ); fTexCoordTop += fAddToTexCoord; - const float fAlpha = ArrowGetAlphaOrGlow( bGlow, m_pPlayerState, iCol, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels, fDrawDistanceBeforeTargetsPixels, fFadeInPercentOfDrawFar ); + const float fAlpha = ArrowGetAlphaOrGlow( bGlow, m_pPlayerState, iCol, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels, args.draw_pixels_before_targets, args.fade_before_targets ); 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(fXCenter, fY, fZCenter); queue.v[1].c = color; queue.v[1].t = RageVector2(fTexCoordCenter, fTexCoordTop); - queue.v[2].p = RageVector3(fXRight, fY, fZRight); queue.v[2].c = color; queue.v[2].t = RageVector2(fTexCoordRight, fTexCoordTop); + queue.v[0].p = RageVector3(fXLeft, fY + spline_pos[1], fZLeft); queue.v[0].c = color; queue.v[0].t = RageVector2(fTexCoordLeft, fTexCoordTop); + queue.v[1].p = RageVector3(fXCenter, fY + spline_pos[1], fZCenter); queue.v[1].c = color; queue.v[1].t = RageVector2(fTexCoordCenter, fTexCoordTop); + queue.v[2].p = RageVector3(fXRight, fY + spline_pos[1], fZRight); queue.v[2].c = color; queue.v[2].t = RageVector2(fTexCoordRight, fTexCoordTop); queue.v+=3; if( queue.Free() < 3 || bLast ) @@ -742,8 +752,11 @@ void NoteDisplay::DrawHoldPart( vector &vpSpr, int iCol, int fYStep, fl } } -void NoteDisplay::DrawHoldBody( const TapNote& tn, int iCol, float fBeat, bool bIsBeingHeld, float fYHead, float fYTail, bool /* bIsAddition */, float fPercentFadeToFail, float fColorScale, bool bGlow, - float fDrawDistanceAfterTargetsPixels, float fDrawDistanceBeforeTargetsPixels, float fFadeInPercentOfDrawFar ) +void NoteDisplay::DrawHoldBody(const TapNote& tn, + CommonColumnRenderArgs const& args, int iCol, float fBeat, + bool bIsBeingHeld, float fYHead, float fYTail, bool bIsAddition, + float fPercentFadeToFail, float fColorScale, bool bGlow, + float top_t, float bottom_t) { vector vpSprTop; Sprite *pSpriteTop = GetHoldSprite( m_HoldTopCap, NotePart_HoldTopCap, fBeat, tn.subType == TapNoteSubType_Roll, bIsBeingHeld && !cache->m_bHoldActiveIsAddLayer ); @@ -801,48 +814,51 @@ void NoteDisplay::DrawHoldBody( const TapNote& tn, int iCol, float fBeat, bool b const float fFrameHeightTop = pSpriteTop->GetUnzoomedHeight(); const float fFrameHeightBottom = pSpriteBottom->GetUnzoomedHeight(); - float fYStartPos = ArrowEffects::GetYPos( m_pPlayerState, iCol, fDrawDistanceAfterTargetsPixels, m_fYReverseOffsetPixels ); - float fYEndPos = ArrowEffects::GetYPos( m_pPlayerState, iCol, fDrawDistanceBeforeTargetsPixels, m_fYReverseOffsetPixels ); + float fYStartPos = ArrowEffects::GetYPos( m_pPlayerState, iCol, + args.draw_pixels_after_targets, m_fYReverseOffsetPixels ); + float fYEndPos = ArrowEffects::GetYPos( m_pPlayerState, iCol, + args.draw_pixels_before_targets, m_fYReverseOffsetPixels ); if( bReverse ) swap( fYStartPos, fYEndPos ); bool bTopAnchor = bReverse && cache->m_bTopHoldAnchorWhenReverse; // Draw the top cap - DrawHoldPart( - vpSprTop, - iCol, fYStep, fPercentFadeToFail, fColorScale, bGlow, - fDrawDistanceAfterTargetsPixels, fDrawDistanceBeforeTargetsPixels, fFadeInPercentOfDrawFar, + DrawHoldPart(vpSprTop, args, iCol, fYStep, fPercentFadeToFail, + fColorScale, bGlow, tn.HoldResult.fOverlappedTime, fYHead-fFrameHeightTop, fYHead, fYStartPos, fYEndPos, - false, bTopAnchor, bFlipHoldBody ); + false, bTopAnchor, bFlipHoldBody, top_t, top_t); // Draw the body - DrawHoldPart( - vpSprBody, - iCol, fYStep, fPercentFadeToFail, fColorScale, bGlow, - fDrawDistanceAfterTargetsPixels, fDrawDistanceBeforeTargetsPixels, fFadeInPercentOfDrawFar, + DrawHoldPart(vpSprBody, args, iCol, fYStep, fPercentFadeToFail, + fColorScale, bGlow, tn.HoldResult.fOverlappedTime, fYHead, fYTail, fYStartPos, fYEndPos, - true, bTopAnchor, bFlipHoldBody ); + true, bTopAnchor, bFlipHoldBody, top_t, bottom_t); // Draw the bottom cap - DrawHoldPart( - vpSprBottom, - iCol, fYStep, fPercentFadeToFail, fColorScale, bGlow, - fDrawDistanceAfterTargetsPixels, fDrawDistanceBeforeTargetsPixels, fFadeInPercentOfDrawFar, + DrawHoldPart(vpSprBottom, args, iCol, fYStep, fPercentFadeToFail, + fColorScale, bGlow, tn.HoldResult.fOverlappedTime, fYTail, fYTail+fFrameHeightBottom, max(fYStartPos, fYHead), fYEndPos, - false, bTopAnchor, bFlipHoldBody ); + false, bTopAnchor, bFlipHoldBody, bottom_t, bottom_t); } -void NoteDisplay::DrawHold( const TapNote &tn, int iCol, int iRow, bool bIsBeingHeld, const HoldNoteResult &Result, bool bIsAddition, float fPercentFadeToFail, - float fReverseOffsetPixels, float fDrawDistanceAfterTargetsPixels, float fDrawDistanceBeforeTargetsPixels, float fDrawDistanceBeforeTargetsPixels2, float fFadeInPercentOfDrawFar ) +void NoteDisplay::DrawHold(const TapNote& tn, + CommonColumnRenderArgs const& args, int iCol, int iRow, bool bIsBeingHeld, + const HoldNoteResult &Result, bool bIsAddition, float fPercentFadeToFail) { int iEndRow = iRow + tn.iDuration; + float top_t= BeatToTValue(args, NoteRowToVisibleBeat(m_pPlayerState, iRow)); + float bottom_t= BeatToTValue(args, NoteRowToVisibleBeat(m_pPlayerState, iEndRow)); + if(bIsBeingHeld) + { + top_t= args.receptor_t; + } // bDrawGlowOnly is a little hacky. We need to draw the diffuse part and the glow part one pass at a time to minimize state changes @@ -873,8 +889,8 @@ void NoteDisplay::DrawHold( const TapNote &tn, int iCol, int iRow, bool bIsBeing if( bReverse ) swap( fStartYOffset, fEndYOffset ); - const float fYHead = ArrowEffects::GetYPos( m_pPlayerState, iCol, fStartYOffset, fReverseOffsetPixels ); - const float fYTail = ArrowEffects::GetYPos( m_pPlayerState, iCol, fEndYOffset, fReverseOffsetPixels ); + const float fYHead = ArrowEffects::GetYPos( m_pPlayerState, iCol, fStartYOffset, m_fYReverseOffsetPixels ); + const float fYTail = ArrowEffects::GetYPos( m_pPlayerState, iCol, fEndYOffset, m_fYReverseOffsetPixels ); const float fColorScale = SCALE( tn.HoldResult.fLife, 0.0f, 1.0f, cache->m_fHoldLetGoGrayPercent, 1.0f ); @@ -896,8 +912,8 @@ void NoteDisplay::DrawHold( const TapNote &tn, int iCol, int iRow, bool bIsBeing } */ - DrawHoldBody( tn, iCol, fBeat, bIsBeingHeld, fYHead, fYTail, bIsAddition, fPercentFadeToFail, fColorScale, false, fDrawDistanceAfterTargetsPixels, fDrawDistanceBeforeTargetsPixels, fFadeInPercentOfDrawFar ); - DrawHoldBody( tn, iCol, fBeat, bIsBeingHeld, fYHead, fYTail, bIsAddition, fPercentFadeToFail, fColorScale, true, fDrawDistanceAfterTargetsPixels, fDrawDistanceBeforeTargetsPixels, fFadeInPercentOfDrawFar ); + DrawHoldBody(tn, args, iCol, fBeat, bIsBeingHeld, fYHead, fYTail, bIsAddition, fPercentFadeToFail, fColorScale, false, top_t, bottom_t); + DrawHoldBody(tn, args, iCol, fBeat, bIsBeingHeld, fYHead, fYTail, bIsAddition, fPercentFadeToFail, fColorScale, true, top_t, bottom_t); /* These set the texture mode themselves. */ // this part was modified in pumpmania, where it flips the draw order @@ -905,25 +921,33 @@ void NoteDisplay::DrawHold( const TapNote &tn, int iCol, int iRow, bool bIsBeing if( cache->m_bHoldTailIsAboveWavyParts ) { Actor *pActor = GetHoldActor( m_HoldTail, NotePart_HoldTail, NoteRowToBeat(iRow), tn.subType == TapNoteSubType_Roll, bIsBeingHeld ); - DrawActor( tn, pActor, NotePart_HoldTail, iCol, bFlipHeadAndTail ? fStartYOffset : fEndYOffset, fBeat, bIsAddition, fPercentFadeToFail, fReverseOffsetPixels, fColorScale, fDrawDistanceAfterTargetsPixels, fDrawDistanceBeforeTargetsPixels, fFadeInPercentOfDrawFar ); + DrawActor(tn, pActor, NotePart_HoldTail, args, iCol, bFlipHeadAndTail ? fStartYOffset : fEndYOffset, fBeat, bIsAddition, fPercentFadeToFail, fColorScale, false); } if( cache->m_bHoldHeadIsAboveWavyParts ) { Actor *pActor = GetHoldActor( m_HoldHead, NotePart_HoldHead, NoteRowToBeat(iRow), tn.subType == TapNoteSubType_Roll, bIsBeingHeld ); - DrawActor( tn, pActor, NotePart_HoldHead, iCol, bFlipHeadAndTail ? fEndYOffset : fStartYOffset, fBeat, bIsAddition, fPercentFadeToFail, fReverseOffsetPixels, fColorScale, fDrawDistanceAfterTargetsPixels, fDrawDistanceBeforeTargetsPixels, fFadeInPercentOfDrawFar ); + DrawActor(tn, pActor, NotePart_HoldHead, args, iCol, bFlipHeadAndTail ? fEndYOffset : fStartYOffset, fBeat, bIsAddition, fPercentFadeToFail, fColorScale, bIsBeingHeld); } } -void NoteDisplay::DrawActor( const TapNote& tn, Actor* pActor, NotePart part, int iCol, float fYOffset, float fBeat, bool bIsAddition, float fPercentFadeToFail, float fReverseOffsetPixels, float fColorScale, float fDrawDistanceAfterTargetsPixels, float fDrawDistanceBeforeTargetsPixels, float fFadeInPercentOfDrawFar ) +void NoteDisplay::DrawActor(const TapNote& tn, Actor* pActor, NotePart part, + CommonColumnRenderArgs const& args, int iCol, float fYOffset, float fBeat, + bool bIsAddition, float fPercentFadeToFail, float fColorScale, + bool is_being_held) { if (tn.type == TapNoteType_AutoKeysound && !GAMESTATE->m_bInStepEditor) return; - if( fYOffset < fDrawDistanceAfterTargetsPixels || fYOffset > fDrawDistanceBeforeTargetsPixels ) + if(fYOffset < args.draw_pixels_after_targets || + fYOffset > args.draw_pixels_before_targets) return; - const float fY = ArrowEffects::GetYPos( m_pPlayerState, iCol, fYOffset, fReverseOffsetPixels ); - 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, fDrawDistanceBeforeTargetsPixels, fFadeInPercentOfDrawFar ); - const float fGlow = ArrowEffects::GetGlow( m_pPlayerState, iCol, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels, fDrawDistanceBeforeTargetsPixels, fFadeInPercentOfDrawFar ); + float spline_t= BeatToTValue(args, fBeat); + if(is_being_held) { spline_t= args.receptor_t; } + vector spline_pos; + args.spline->evaluate(spline_t, spline_pos); + const float fY = ArrowEffects::GetYPos( m_pPlayerState, iCol, fYOffset, m_fYReverseOffsetPixels ) + spline_pos[1]; + const float fX = ArrowEffects::GetXPos( m_pPlayerState, iCol, fYOffset ) + spline_pos[0]; + const float fZ = ArrowEffects::GetZPos( m_pPlayerState, iCol, fYOffset ) + spline_pos[2]; + const float fAlpha = ArrowEffects::GetAlpha( m_pPlayerState, iCol, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels, args.draw_pixels_before_targets, args.fade_before_targets ); + const float fGlow = ArrowEffects::GetGlow( m_pPlayerState, iCol, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels, args.draw_pixels_before_targets, args.fade_before_targets ); const RageColor diffuse = RageColor(fColorScale,fColorScale,fColorScale,fAlpha); const RageColor glow = RageColor(1,1,1,fGlow); float fRotationX = 0, fRotationZ = 0; @@ -979,13 +1003,10 @@ void NoteDisplay::DrawActor( const TapNote& tn, Actor* pActor, NotePart part, in } } -void NoteDisplay::DrawTap(const TapNote& tn, int iCol, float fBeat, - bool bOnSameRowAsHoldStart, bool bOnSameRowAsRollStart, - bool bIsAddition, float fPercentFadeToFail, - float fReverseOffsetPixels, - float fDrawDistanceAfterTargetsPixels, - float fDrawDistanceBeforeTargetsPixels, - float fFadeInPercentOfDrawFar) +void NoteDisplay::DrawTap(const TapNote& tn, + CommonColumnRenderArgs const& args, int iCol, float fBeat, + bool bOnSameRowAsHoldStart, bool bOnSameRowAsRollStart, + bool bIsAddition, float fPercentFadeToFail) { Actor* pActor = NULL; NotePart part = NotePart_Tap; @@ -1059,7 +1080,7 @@ void NoteDisplay::DrawTap(const TapNote& tn, int iCol, float fBeat, const float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, iCol, fBeat ); // this is the line that forces the (1,1,1,x) part of the noteskin diffuse -aj - DrawActor( tn, pActor, part, iCol, fYOffset, fBeat, bIsAddition, fPercentFadeToFail, fReverseOffsetPixels, 1.0f, fDrawDistanceAfterTargetsPixels, fDrawDistanceBeforeTargetsPixels, fFadeInPercentOfDrawFar ); + DrawActor(tn, pActor, part, args, iCol, fYOffset, fBeat, bIsAddition, fPercentFadeToFail, 1.0f, false); if( tn.type == TapNoteType_Attack ) pActor->PlayCommand( "UnsetAttack" ); @@ -1067,6 +1088,11 @@ void NoteDisplay::DrawTap(const TapNote& tn, int iCol, float fBeat, void NoteColumnRenderer::DrawPrimitives() { + m_render_args->spline= &m_spline; + m_render_args->receptor_t= m_receptor_t; + m_render_args->beats_per_t= m_beats_per_t; + m_render_args->first_beat= NoteRowToBeat(m_render_args->first_row); + m_render_args->last_beat= NoteRowToBeat(m_render_args->last_row); bool any_upcoming= false; // Build lists of holds and taps for each player number, then pass those // lists to the displays to draw. @@ -1123,6 +1149,38 @@ void NoteColumnRenderer::DrawPrimitives() m_render_args->receptor_row->SetNoteUpcoming(m_column, any_upcoming); } +#include "LuaBinding.h" + +struct LunaNoteColumnRenderer : Luna +{ + static int get_spline(T* p, lua_State* L) + { + p->m_spline.PushSelf(L); + return 1; + } + DEFINE_METHOD(get_receptor_t, m_receptor_t); + DEFINE_METHOD(get_beats_per_t, m_beats_per_t); +#define SET_T(member, name) \ + static int name(T* p, lua_State* L) \ + { \ + p->member= FArg(1); \ + COMMON_RETURN_SELF; \ + } + SET_T(m_receptor_t, set_receptor_t); + SET_T(m_beats_per_t, set_beats_per_t); + + LunaNoteColumnRenderer() + { + ADD_METHOD(get_spline); + ADD_METHOD(get_receptor_t); + ADD_METHOD(get_beats_per_t); + ADD_METHOD(set_receptor_t); + ADD_METHOD(set_beats_per_t); + } +}; + +LUA_REGISTER_DERIVED_CLASS(NoteColumnRenderer, Actor) + /* * (c) 2001-2006 Brian Bugh, Ben Nordstrom, Chris Danford, Steve Checkoway * All rights reserved. diff --git a/src/NoteDisplay.h b/src/NoteDisplay.h index ade622f321..43121564b7 100644 --- a/src/NoteDisplay.h +++ b/src/NoteDisplay.h @@ -2,6 +2,7 @@ #define NOTE_DISPLAY_H #include "ActorFrame.h" +#include "CubicSpline.h" #include "NoteData.h" #include "PlayerNumber.h" #include "GameInput.h" @@ -93,10 +94,15 @@ struct CommonColumnRenderArgs ReceptorArrowRow* receptor_row; GhostArrowRow* ghost_row; NoteData const* note_data; + CubicSplineN const* spline; + float receptor_t; + float beats_per_t; + float first_beat; + float last_beat; int first_row; int last_row; - int draw_pixels_before_targets; - int draw_pixels_after_targets; + float draw_pixels_before_targets; + float draw_pixels_after_targets; int* selection_begin_marker; int* selection_end_marker; float selection_glow; @@ -116,6 +122,7 @@ public: static void Update( float fDeltaTime ); bool IsOnScreen( float fBeat, int iCol, int iDrawDistanceAfterTargetsPixels, int iDrawDistanceBeforeTargetsPixels ) const; + float BeatToTValue(CommonColumnRenderArgs const& args, float beat) const; bool DrawHoldsInRange(CommonColumnRenderArgs const& args, int column, vector const& tap_set); @@ -134,19 +141,14 @@ public: * @param fDrawDistanceAfterTargetsPixels how much to draw after the receptors. * @param fDrawDistanceBeforeTargetsPixels how much ot draw before the receptors. * @param fFadeInPercentOfDrawFar when to start fading in. */ - void DrawTap(const TapNote& tn, int iCol, float fBeat, - bool bOnSameRowAsHoldStart, bool bOnSameRowAsRollBeat, - bool bIsAddition, float fPercentFadeToFail, - float fReverseOffsetPixels, - float fDrawDistanceAfterTargetsPixels, - float fDrawDistanceBeforeTargetsPixels, - float fFadeInPercentOfDrawFar ); - void DrawHold( const TapNote& tn, int iCol, int iRow, bool bIsBeingHeld, const HoldNoteResult &Result, - bool bIsAddition, float fPercentFadeToFail, float fReverseOffsetPixels, float fDrawDistanceAfterTargetsPixels, float fDrawDistanceBeforeTargetsPixels, - float fDrawDistanceBeforeTargetsPixels2, float fFadeInPercentOfDrawFar ); - + void DrawTap(const TapNote& tn, CommonColumnRenderArgs const& args, + int iCol, float fBeat, bool bOnSameRowAsHoldStart, + bool bOnSameRowAsRollBeat, bool bIsAddition, float fPercentFadeToFail); + void DrawHold(const TapNote& tn, CommonColumnRenderArgs const& args, + int iCol, int iRow, bool bIsBeingHeld, const HoldNoteResult &Result, + bool bIsAddition, float fPercentFadeToFail); + bool DrawHoldHeadForTapsOnSameRow() const; - bool DrawRollHeadForTapsOnSameRow() const; private: @@ -155,14 +157,20 @@ private: Actor *GetHoldActor( NoteColorActor nca[NUM_HoldType][NUM_ActiveType], NotePart part, float fNoteBeat, bool bIsRoll, bool bIsBeingHeld ); Sprite *GetHoldSprite( NoteColorSprite ncs[NUM_HoldType][NUM_ActiveType], NotePart part, float fNoteBeat, bool bIsRoll, bool bIsBeingHeld ); - void DrawActor( const TapNote& tn, Actor* pActor, NotePart part, int iCol, float fYOffset, float fBeat, bool bIsAddition, float fPercentFadeToFail, - float fReverseOffsetPixels, float fColorScale, float fDrawDistanceAfterTargetsPixels, float fDrawDistanceBeforeTargetsPixels, float fFadeInPercentOfDrawFar ); - void DrawHoldBody( const TapNote& tn, int iCol, float fBeat, bool bIsBeingHeld, float fYHead, float fYTail, bool bIsAddition, float fPercentFadeToFail, - float fColorScale, - bool bGlow, float fDrawDistanceAfterTargetsPixels, float fDrawDistanceBeforeTargetsPixels, float fFadeInPercentOfDrawFar ); - void DrawHoldPart( vector &vpSpr, int iCol, int fYStep, float fPercentFadeToFail, float fColorScale, bool bGlow, - float fDrawDistanceAfterTargetsPixels, float fDrawDistanceBeforeTargetsPixels, float fFadeInPercentOfDrawFar, float fOverlappedTime, - float fYTop, float fYBottom, float fYStartPos, float fYEndPos, bool bWrapping, bool bAnchorToTop, bool bFlipTextureVertically ); + void DrawActor(const TapNote& tn, Actor* pActor, NotePart part, + CommonColumnRenderArgs const& args, int iCol, float fYOffset, float fBeat, + bool bIsAddition, float fPercentFadeToFail, float fColorScale, + bool is_being_held); + void DrawHoldBody(const TapNote& tn, CommonColumnRenderArgs const& args, + int iCol, float fBeat, bool bIsBeingHeld, float fYHead, float fYTail, + bool bIsAddition, float fPercentFadeToFail, float fColorScale, + bool bGlow, float top_t, float bottom_t); + void DrawHoldPart(vector &vpSpr, + CommonColumnRenderArgs const& args, int iCol, int fYStep, + float fPercentFadeToFail, float fColorScale, bool bGlow, + float fOverlappedTime, float fYTop, float fYBottom, float fYStartPos, + float fYEndPos, bool bWrapping, bool bAnchorToTop, + bool bFlipTextureVertically, float top_t, float bottom_t); const PlayerState *m_pPlayerState; // to look up PlayerOptions NoteMetricCache_t *cache; @@ -191,11 +199,20 @@ private: class NoteColumnRenderer : public Actor { public: + NoteColumnRenderer() + { + m_spline.redimension(3); + m_spline.m_owned_by_actor= true; + } NoteDisplay* m_displays[PLAYER_INVALID+1]; CommonColumnRenderArgs* m_render_args; int m_column; + float m_receptor_t; + float m_beats_per_t; + CubicSplineN m_spline; virtual void DrawPrimitives(); + virtual void PushSelf(lua_State* L); }; #endif diff --git a/src/ReceptorArrowRow.cpp b/src/ReceptorArrowRow.cpp index 8c7f6dc54c..19bce08bfc 100644 --- a/src/ReceptorArrowRow.cpp +++ b/src/ReceptorArrowRow.cpp @@ -37,6 +37,7 @@ void ReceptorArrowRow::SetColumnRenderers(vector& renderers) { m_ReceptorArrow[c]->SetFakeParent(&(renderers[c])); } + m_renderers= &renderers; } ReceptorArrowRow::~ReceptorArrowRow() @@ -52,6 +53,8 @@ void ReceptorArrowRow::Update( float fDeltaTime ) for( unsigned c=0; c spline_pos; + (*m_renderers)[c].m_spline.evaluate((*m_renderers)[c].m_receptor_t, spline_pos); // m_fDark==1 or m_fFadeToFailPercent==1 should make fBaseAlpha==0 float fBaseAlpha = (1 - m_pPlayerState->m_PlayerOptions.GetCurrent().m_fDark); if( m_fFadeToFailPercent != -1 ) @@ -65,9 +68,9 @@ void ReceptorArrowRow::Update( float fDeltaTime ) float fX = ArrowEffects::GetXPos( m_pPlayerState, c, 0 ); const float fY = ArrowEffects::GetYPos( m_pPlayerState, c, 0, m_fYReverseOffsetPixels ); const float fZ = ArrowEffects::GetZPos( m_pPlayerState, c, 0 ); - m_ReceptorArrow[c]->SetX( fX ); - m_ReceptorArrow[c]->SetY( fY ); - m_ReceptorArrow[c]->SetZ( fZ ); + m_ReceptorArrow[c]->SetX( fX + spline_pos[0] ); + m_ReceptorArrow[c]->SetY( fY + spline_pos[1] ); + m_ReceptorArrow[c]->SetZ( fZ + spline_pos[2] ); const float fRotation = ArrowEffects::ReceptorGetRotationZ( m_pPlayerState ); m_ReceptorArrow[c]->SetRotationZ( fRotation ); diff --git a/src/ReceptorArrowRow.h b/src/ReceptorArrowRow.h index ac6f081643..a65cd407bb 100644 --- a/src/ReceptorArrowRow.h +++ b/src/ReceptorArrowRow.h @@ -30,6 +30,7 @@ protected: float m_fYReverseOffsetPixels; float m_fFadeToFailPercent; + vector const* m_renderers; vector m_ReceptorArrow; };