1
- #include " global.h"
1
+ #include " global.h"
2
2
#include " ActorUtil.h"
3
3
#include " ArrowEffects.h"
4
4
#include " Foreach.h"
@@ -80,7 +80,9 @@ struct NoteMetricCache_t
80
80
bool m_bHoldTailIsAboveWavyParts;
81
81
int m_iStartDrawingHoldBodyOffsetFromHead;
82
82
int m_iStopDrawingHoldBodyOffsetFromTail;
83
- float m_fHoldLetGoGrayPercent;
83
+ float m_fHoldLetGoGrayPercent;
84
+ bool m_UseStretchHolds;
85
+ bool m_UseShrinkHolds;
84
86
bool m_bFlipHeadAndTailWhenReverse;
85
87
bool m_bFlipHoldBodyWhenReverse;
86
88
bool m_bTopHoldAnchorWhenReverse;
@@ -109,7 +111,9 @@ void NoteMetricCache_t::Load( const RString &sButton )
109
111
m_NoteColorType[p] = StringToNoteColorType (ct);
110
112
}
111
113
// I was here -DaisuMaster
112
- m_bAnimationBasedOnBeats = NOTESKIN->GetMetricB (sButton ," AnimationIsBeatBased" );
114
+ m_bAnimationBasedOnBeats = NOTESKIN->GetMetricB (sButton ," AnimationIsBeatBased" );
115
+ m_UseStretchHolds = NOTESKIN->GetMetricB (sButton , " UseStretchHolds" );
116
+ m_UseShrinkHolds = NOTESKIN->GetMetricB (sButton , " UseShrinkHolds" );
113
117
m_bHoldHeadIsAboveWavyParts = NOTESKIN->GetMetricB (sButton ," HoldHeadIsAboveWavyParts" );
114
118
m_bHoldTailIsAboveWavyParts = NOTESKIN->GetMetricB (sButton ," HoldTailIsAboveWavyParts" );
115
119
m_iStartDrawingHoldBodyOffsetFromHead = NOTESKIN->GetMetricI (sButton ," StartDrawingHoldBodyOffsetFromHead" );
@@ -182,26 +186,26 @@ struct NoteResource
182
186
Actor *m_pActor; // todo: AutoActor me? -aj
183
187
};
184
188
185
- static map<NoteSkinAndPath, NoteResource *> g_NoteResource;
189
+ static map<RString, map< NoteSkinAndPath, NoteResource *>> g_NoteResource;
186
190
187
- static NoteResource *MakeNoteResource ( const RString &sButton , const RString &sElement , PlayerNumber pn, GameController gc, bool bSpriteOnly )
191
+ static NoteResource *MakeNoteResource ( const RString &sButton , const RString &sElement , PlayerNumber pn, GameController gc, bool bSpriteOnly, RString Color)
188
192
{
189
193
RString sElementAndType = ssprintf ( " %s, %s" , sButton .c_str (), sElement .c_str () );
190
194
NoteSkinAndPath nsap ( NOTESKIN->GetCurrentNoteSkin (), sElementAndType , pn, gc );
191
195
192
- map<NoteSkinAndPath, NoteResource *>::iterator it = g_NoteResource.find ( nsap );
193
- if ( it == g_NoteResource.end () )
196
+ map<NoteSkinAndPath, NoteResource *>::iterator it = g_NoteResource[Color] .find ( nsap );
197
+ if ( it == g_NoteResource[Color] .end () )
194
198
{
195
199
auto *pRes = new NoteResource ( nsap );
196
200
197
201
NOTESKIN->SetPlayerNumber ( pn );
198
202
NOTESKIN->SetGameController ( gc );
199
203
200
- pRes->m_pActor = NOTESKIN->LoadActor ( sButton , sElement , NULL , bSpriteOnly );
204
+ pRes->m_pActor = NOTESKIN->LoadActor ( sButton , sElement , NULL , bSpriteOnly, Color);
201
205
ASSERT ( pRes->m_pActor != NULL );
202
206
203
- g_NoteResource[nsap] = pRes;
204
- it = g_NoteResource.find ( nsap );
207
+ g_NoteResource[Color][ nsap] = pRes;
208
+ it = g_NoteResource[Color] .find ( nsap );
205
209
}
206
210
207
211
NoteResource *pRet = it->second ;
@@ -218,55 +222,63 @@ static void DeleteNoteResource( NoteResource *pRes )
218
222
if ( pRes->m_iRefCount != 0 )
219
223
return ;
220
224
221
- g_NoteResource.erase ( pRes->m_nsap );
225
+ map<RString, map<NoteSkinAndPath, NoteResource *>>::iterator it;
226
+ for (it = g_NoteResource.begin (); it != g_NoteResource.end (); it++)
227
+ it->second .erase (pRes->m_nsap );
222
228
delete pRes;
223
229
}
224
230
225
231
/* NoteColorActor */
226
232
227
233
NoteColorActor::NoteColorActor ()
228
234
{
229
- m_p = NULL ;
235
+ g_p. clear ();
230
236
}
231
237
232
238
NoteColorActor::~NoteColorActor ()
233
239
{
234
- if ( m_p != nullptr )
235
- DeleteNoteResource ( m_p );
240
+ map<RString, NoteResource*>::iterator it;
241
+ for (it = g_p.begin (); it != g_p.end (); it++)
242
+ if (it->second )
243
+ DeleteNoteResource (it->second );
244
+ g_p.clear ();
236
245
}
237
246
238
- void NoteColorActor::Load ( const RString &sButton , const RString &sElement , PlayerNumber pn, GameController gc )
247
+ void NoteColorActor::Load ( const RString &sButton , const RString &sElement , PlayerNumber pn, GameController gc ,RString Color)
239
248
{
240
- m_p = MakeNoteResource ( sButton , sElement , pn, gc, false );
249
+ g_p[Color] = MakeNoteResource ( sButton , sElement , pn, gc, false , Color);
241
250
}
242
251
243
252
244
- Actor *NoteColorActor::Get ()
253
+ Actor *NoteColorActor::Get (RString Color)
245
254
{
246
- return m_p ->m_pActor ;
255
+ return g_p[Color] ->m_pActor ;
247
256
}
248
257
249
258
/* NoteColorSprite */
250
259
251
260
NoteColorSprite::NoteColorSprite ()
252
261
{
253
- m_p = NULL ;
262
+ g_p. clear ();
254
263
}
255
264
256
265
NoteColorSprite::~NoteColorSprite ()
257
266
{
258
- if ( m_p != nullptr )
259
- DeleteNoteResource ( m_p );
267
+ map<RString, NoteResource*>::iterator it;
268
+ for (it = g_p.begin (); it != g_p.end (); it++)
269
+ if (it->second )
270
+ DeleteNoteResource (it->second );
271
+ g_p.clear ();
260
272
}
261
273
262
- void NoteColorSprite::Load ( const RString &sButton , const RString &sElement , PlayerNumber pn, GameController gc )
274
+ void NoteColorSprite::Load ( const RString &sButton , const RString &sElement , PlayerNumber pn, GameController gc, RString Color)
263
275
{
264
- m_p = MakeNoteResource ( sButton , sElement , pn, gc, true );
276
+ g_p[Color] = MakeNoteResource (sButton , sElement , pn, gc, true , Color);
265
277
}
266
278
267
- Sprite *NoteColorSprite::Get ()
279
+ Sprite *NoteColorSprite::Get (RString Color)
268
280
{
269
- return dynamic_cast <Sprite *>( m_p ->m_pActor );
281
+ return dynamic_cast <Sprite *>( g_p[Color] ->m_pActor );
270
282
}
271
283
272
284
static const char *HoldTypeNames[] = {
@@ -418,23 +430,28 @@ void NoteDisplay::Load( int iColNum, const PlayerState* pPlayerState, float fYRe
418
430
419
431
cache->Load ( sButton );
420
432
421
- // "normal" note types
422
- m_TapNote.Load ( sButton , " Tap Note" , pn, GameI[0 ].controller );
423
- // m_TapAdd.Load( sButton, "Tap Addition", pn, GameI.controller );
424
- m_TapMine.Load ( sButton , " Tap Mine" , pn, GameI[0 ].controller );
425
- m_TapLift.Load ( sButton , " Tap Lift" , pn, GameI[0 ].controller );
426
- m_TapFake.Load ( sButton , " Tap Fake" , pn, GameI[0 ].controller );
433
+ vector<RString> Colors = {" 4th" ," 8th" , " 12th" , " 16th" , " 24th" , " 32nd" , " 48th" , " 64th" , " 192nd" };
427
434
428
- // hold types
429
- FOREACH_HoldType ( ht )
435
+ vector<RString>::iterator Color;
436
+ for ( Color = Colors. begin () ; Color != Colors. end () ; Color++ )
430
437
{
431
- FOREACH_ActiveType ( at )
438
+ // "normal" note types
439
+ m_TapNote.Load ( sButton , " Tap Note" , pn, GameI[0 ].controller , *Color);
440
+ m_TapMine.Load ( sButton , " Tap Mine" , pn, GameI[0 ].controller , *Color);
441
+ m_TapLift.Load ( sButton , " Tap Lift" , pn, GameI[0 ].controller , *Color);
442
+ m_TapFake.Load ( sButton , " Tap Fake" , pn, GameI[0 ].controller , *Color);
443
+
444
+ // hold types
445
+ FOREACH_HoldType ( ht )
432
446
{
433
- m_HoldHead[ht][at].Load ( sButton , HoldTypeToString (ht)+" Head " +ActiveTypeToString (at), pn, GameI[0 ].controller );
434
- m_HoldTopCap[ht][at].Load ( sButton , HoldTypeToString (ht)+" Topcap " +ActiveTypeToString (at), pn, GameI[0 ].controller );
435
- m_HoldBody[ht][at].Load ( sButton , HoldTypeToString (ht)+" Body " +ActiveTypeToString (at), pn, GameI[0 ].controller );
436
- m_HoldBottomCap[ht][at].Load ( sButton , HoldTypeToString (ht)+" Bottomcap " +ActiveTypeToString (at), pn, GameI[0 ].controller );
437
- m_HoldTail[ht][at].Load ( sButton , HoldTypeToString (ht)+" Tail " +ActiveTypeToString (at), pn, GameI[0 ].controller );
447
+ FOREACH_ActiveType ( at )
448
+ {
449
+ m_HoldHead[ht][at].Load ( sButton , HoldTypeToString (ht)+" Head " +ActiveTypeToString (at), pn, GameI[0 ].controller , *Color);
450
+ m_HoldTopCap[ht][at].Load ( sButton , HoldTypeToString (ht)+" Topcap " +ActiveTypeToString (at), pn, GameI[0 ].controller , *Color);
451
+ m_HoldBody[ht][at].Load ( sButton , HoldTypeToString (ht)+" Body " +ActiveTypeToString (at), pn, GameI[0 ].controller , *Color);
452
+ m_HoldBottomCap[ht][at].Load ( sButton , HoldTypeToString (ht)+" Bottomcap " +ActiveTypeToString (at), pn, GameI[0 ].controller , *Color);
453
+ m_HoldTail[ht][at].Load ( sButton , HoldTypeToString (ht)+" Tail " +ActiveTypeToString (at), pn, GameI[0 ].controller , *Color);
454
+ }
438
455
}
439
456
}
440
457
}
@@ -609,11 +626,15 @@ void NoteDisplay::Update( float fDeltaTime )
609
626
{
610
627
/* This function is static: it's called once per game loop, not once per
611
628
* NoteDisplay. Update each cached item exactly once. */
629
+ map<RString, map<NoteSkinAndPath, NoteResource *>>::iterator it2;
612
630
map<NoteSkinAndPath, NoteResource *>::iterator it;
613
- for ( it = g_NoteResource.begin (); it != g_NoteResource.end (); ++it )
631
+ for (it2 = g_NoteResource.begin () ; it2 != g_NoteResource.end () ; it2++)
614
632
{
615
- NoteResource *pRes = it->second ;
616
- pRes->m_pActor ->Update ( fDeltaTime );
633
+ for (it = it2->second .begin (); it != it2->second .end (); it++)
634
+ {
635
+ NoteResource *pRes = it->second ;
636
+ pRes->m_pActor ->Update (fDeltaTime );
637
+ }
617
638
}
618
639
}
619
640
@@ -652,7 +673,8 @@ void NoteDisplay::SetActiveFrame( float fNoteBeat, Actor &actorToSet, float fAni
652
673
653
674
Actor *NoteDisplay::GetTapActor ( NoteColorActor &nca, NotePart part, float fNoteBeat )
654
675
{
655
- Actor *pActorOut = nca.Get ();
676
+ RString Color = NoteTypeToString (BeatToNoteType (fNoteBeat ));
677
+ Actor *pActorOut = nca.Get (Color);
656
678
657
679
SetActiveFrame ( fNoteBeat , *pActorOut, cache->m_fAnimationLength [part], cache->m_bAnimationIsVivid [part] );
658
680
return pActorOut;
@@ -665,8 +687,9 @@ Actor *NoteDisplay::GetHoldActor( NoteColorActor nca[NUM_HoldType][NUM_ActiveTyp
665
687
666
688
Sprite *NoteDisplay::GetHoldSprite ( NoteColorSprite ncs[NUM_HoldType][NUM_ActiveType], NotePart part, float fNoteBeat , bool bIsRoll, bool bIsBeingHeld )
667
689
{
668
- Sprite *pSpriteOut = ncs[bIsRoll ? roll:hold][bIsBeingHeld ? active:inactive].Get ();
669
-
690
+ RString Color = NoteTypeToString (BeatToNoteType (fNoteBeat ));
691
+ Sprite *pSpriteOut = ncs[bIsRoll ? roll:hold][bIsBeingHeld ? active:inactive].Get (Color);
692
+
670
693
SetActiveFrame ( fNoteBeat , *pSpriteOut, cache->m_fAnimationLength [part], cache->m_bAnimationIsVivid [part] );
671
694
return pSpriteOut;
672
695
}
@@ -728,7 +751,9 @@ void NoteDisplay::DrawHoldPart(vector<Sprite*> &vpSpr,
728
751
if (part_args.flip_texture_vertically )
729
752
swap (rect.top , rect.bottom );
730
753
const float fFrameWidth = pSprite->GetUnzoomedWidth ();
731
- const float unzoomed_frame_height= pSprite->GetUnzoomedHeight ();
754
+ float unzoomed_frame_height = pSprite->GetUnzoomedHeight ();
755
+ if (part_type == hpt_body && cache->m_UseStretchHolds )
756
+ unzoomed_frame_height = part_args.y_length ;
732
757
733
758
/* Only draw the section that's within the range specified. If a hold note is
734
759
* very long, don't process or draw the part outside of the range. Don't change
@@ -1000,7 +1025,7 @@ void NoteDisplay::DrawHoldBodyInternal(vector<Sprite*>& sprite_top,
1000
1025
const NoteColumnRenderArgs& column_args,
1001
1026
draw_hold_part_args& part_args,
1002
1027
const float head_minus_top, const float tail_plus_bottom,
1003
- const float y_head, const float y_tail, const float top_beat,
1028
+ const float y_head, const float y_tail, const float y_length, const float top_beat,
1004
1029
const float bottom_beat, bool glow)
1005
1030
{
1006
1031
if (y_head < y_tail)
@@ -1015,7 +1040,8 @@ void NoteDisplay::DrawHoldBodyInternal(vector<Sprite*>& sprite_top,
1015
1040
1016
1041
// Draw the body if the start is not lower than the start of the tail
1017
1042
part_args.y_top = y_head;
1018
- part_args.y_bottom = y_tail;
1043
+ part_args.y_bottom = y_tail;
1044
+ part_args.y_length = y_length;
1019
1045
part_args.top_beat = top_beat;
1020
1046
part_args.bottom_beat = bottom_beat;
1021
1047
part_args.wrapping = true ;
@@ -1034,7 +1060,7 @@ void NoteDisplay::DrawHoldBodyInternal(vector<Sprite*>& sprite_top,
1034
1060
void NoteDisplay::DrawHoldBody (const TapNote& tn,
1035
1061
const NoteFieldRenderArgs& field_args,
1036
1062
const NoteColumnRenderArgs& column_args, float beat,
1037
- bool being_held, float y_head, float y_tail, float percent_fade_to_fail,
1063
+ bool being_held, float y_head, float y_tail, float y_length, float percent_fade_to_fail,
1038
1064
float color_scale, float top_beat, float bottom_beat)
1039
1065
{
1040
1066
draw_hold_part_args part_args;
@@ -1111,7 +1137,7 @@ void NoteDisplay::DrawHoldBody(const TapNote& tn,
1111
1137
DISPLAY->SetTextureMode (TextureUnit_1, TextureMode_Modulate);
1112
1138
DrawHoldBodyInternal (vpSprTop, vpSprBody, vpSprBottom, field_args,
1113
1139
column_args, part_args, head_minus_top,
1114
- tail_plus_bottom, y_head, y_tail, top_beat, bottom_beat,
1140
+ tail_plus_bottom, y_head, y_tail, y_length, top_beat, bottom_beat,
1115
1141
false );
1116
1142
1117
1143
if ((*field_args.selection_begin_marker != -1 && *field_args.selection_end_marker != -1 )
@@ -1121,10 +1147,12 @@ void NoteDisplay::DrawHoldBody(const TapNote& tn,
1121
1147
DISPLAY->SetTextureMode (TextureUnit_1, TextureMode_Glow);
1122
1148
DrawHoldBodyInternal (vpSprTop, vpSprBody, vpSprBottom, field_args,
1123
1149
column_args, part_args, head_minus_top,
1124
- tail_plus_bottom, y_head, y_tail, top_beat, bottom_beat,
1150
+ tail_plus_bottom, y_head, y_tail, y_length, top_beat, bottom_beat,
1125
1151
true );
1126
1152
}
1127
- }
1153
+ }
1154
+
1155
+ static map<int , map<int , map<int , float >>> HoldSize;
1128
1156
1129
1157
void NoteDisplay::DrawHold (const TapNote& tn,
1130
1158
const NoteFieldRenderArgs& field_args,
@@ -1155,7 +1183,13 @@ void NoteDisplay::DrawHold(const TapNote& tn,
1155
1183
1156
1184
float fEndPeakYOffset = 0 ;
1157
1185
bool bEndIsPastPeak = false ;
1158
- float fEndYOffset = ArrowEffects::GetYOffset ( m_pPlayerState, column_args.column , NoteRowToBeat (iEndRow), fEndPeakYOffset , bEndIsPastPeak );
1186
+ float fEndYOffset = ArrowEffects::GetYOffset ( m_pPlayerState, column_args.column , NoteRowToBeat (iEndRow), fEndPeakYOffset , bEndIsPastPeak );
1187
+ float length;
1188
+ if (!tn.HoldResult .bActive )
1189
+ HoldSize[m_pPlayerState->m_PlayerNumber ][iRow][column_args.column ] = fEndYOffset - fStartYOffset ;
1190
+ length = HoldSize[m_pPlayerState->m_PlayerNumber ][iRow][column_args.column ];
1191
+ if (cache->m_UseShrinkHolds )
1192
+ length = fEndYOffset - fStartYOffset ;
1159
1193
1160
1194
// In boomerang, the arrows reverse direction at Y offset value fPeakAtYOffset.
1161
1195
// If fPeakAtYOffset lies inside of the hold we're drawing, then the we
@@ -1194,7 +1228,7 @@ void NoteDisplay::DrawHold(const TapNote& tn,
1194
1228
}
1195
1229
*/
1196
1230
1197
- DrawHoldBody (tn, field_args, column_args, fBeat , bIsBeingHeld, fYHead , fYTail , fPercentFadeToFail , fColorScale , top_beat, bottom_beat);
1231
+ DrawHoldBody (tn, field_args, column_args, fBeat , bIsBeingHeld, fYHead , fYTail , length, fPercentFadeToFail , fColorScale , top_beat, bottom_beat);
1198
1232
1199
1233
/* These set the texture mode themselves. */
1200
1234
// this part was modified in pumpmania, where it flips the draw order
0 commit comments