@@ -39,6 +39,14 @@ class NoteField extends FieldBase
3939 public var optimizeHolds = false ; // ClientPrefs.optimizeHolds;
4040 public var defaultShader : FlxShader = new FlxShader ();
4141
42+ // Framerate-adaptive performance variables
43+ private var frameTimeAccumulator : Float = 0 ;
44+ private var frameCounter : Int = 0 ;
45+ private var avgFrameTime : Float = 0.0167 ; // Start assuming 60 FPS
46+ private var lastFrameTime : Float = 0 ;
47+ private var adaptiveSubdivisions : Int = 16 ;
48+ private var noteRenderSkipCounter : Int = 0 ;
49+
4250 public function new (field : PlayField , modManager : ModManager )
4351 {
4452 super (0 , 0 );
@@ -112,6 +120,35 @@ class NoteField extends FieldBase
112120 // does all the drawing logic, best not to touch unless you know what youre doing
113121 override function preDraw ()
114122 {
123+ // Framerate detection and adaptive subdivision adjustment
124+ var currentTime = haxe. Timer .stamp ();
125+ if (lastFrameTime > 0 ) {
126+ var frameTime = currentTime - lastFrameTime ;
127+ frameTimeAccumulator + = frameTime ;
128+ frameCounter ++ ;
129+
130+ // Update adaptive settings every 30 frames
131+ if (frameCounter >= 30 ) {
132+ avgFrameTime = frameTimeAccumulator / frameCounter ;
133+ var fps = 1.0 / avgFrameTime ;
134+
135+ // Adaptive subdivision scaling based on FPS
136+ if (fps > 120 ) {
137+ adaptiveSubdivisions = Math .max (1 , Std .int (holdSubdivisions * 0.25 )); // 25% subdivisions at 120+ FPS
138+ } else if (fps > 100 ) {
139+ adaptiveSubdivisions = Math .max (1 , Std .int (holdSubdivisions * 0.4 )); // 40% subdivisions at 100+ FPS
140+ } else if (fps > 80 ) {
141+ adaptiveSubdivisions = Math .max (1 , Std .int (holdSubdivisions * 0.6 )); // 60% subdivisions at 80+ FPS
142+ } else {
143+ adaptiveSubdivisions = holdSubdivisions ; // Full subdivisions at lower FPS
144+ }
145+
146+ frameTimeAccumulator = 0 ;
147+ frameCounter = 0 ;
148+ }
149+ }
150+ lastFrameTime = currentTime ;
151+
115152 drawQueue = [];
116153 if (field == null ) return ;
117154 if ((! exists || ! visible ) && ! forcePreDraw ) return ;
@@ -371,10 +408,11 @@ class NoteField extends FieldBase
371408 return null ;
372409
373410 var simpleDraw = ! hold .copyX && ! hold .copyY ;
374- // TODO: make simpleDraw reduce the amount of subdivisions used by the hold
411+ // Use adaptive subdivisions for performance (minimum 1)
412+ var currentSubdivisions : Num = optimizeHolds ? Math .max (1 , adaptiveSubdivisions ) : adaptiveSubdivisions ;
375413
376- var vertices = new Vector <Float >(8 * holdSubdivisions , true );
377- var uvData = new Vector <Float >(8 * holdSubdivisions , true );
414+ var vertices = new Vector <Float >(8 * currentSubdivisions , true );
415+ var uvData = new Vector <Float >(8 * currentSubdivisions , true );
378416 var alphas : Array <Float > = [];
379417 var glows : Array <Float > = [];
380418 var lastMe = null ;
@@ -417,11 +455,11 @@ class NoteField extends FieldBase
417455 var useSpiralHolds = modManager .getValue (" spiralHolds" , modNumber ) != 0 ;
418456
419457
420- for (sub in 0 ... holdSubdivisions )
458+ for (sub in 0 ... currentSubdivisions )
421459 {
422- var prog = sub / (holdSubdivisions + 1 );
423- var nextProg = (sub + 1 ) / (holdSubdivisions + 1 );
424- var strumSub = (crotchet / holdSubdivisions );
460+ var prog = sub / (currentSubdivisions + 1 );
461+ var nextProg = (sub + 1 ) / (currentSubdivisions + 1 );
462+ var strumSub = (crotchet / currentSubdivisions );
425463 var strumOff = (strumSub * sub );
426464 strumSub * = sv ;
427465 strumOff * = sv ;
@@ -511,7 +549,7 @@ class NoteField extends FieldBase
511549 vertices [subIndex + 6 ] = bot [1 ].x ;
512550 vertices [subIndex + 7 ] = bot [1 ].y ;
513551
514- appendUV (hold , uvData , false , sub );
552+ appendUV (hold , uvData , false , sub , currentSubdivisions );
515553 }
516554
517555 var shader = hold .shader != null ? hold .shader : defaultShader ;
@@ -536,14 +574,16 @@ class NoteField extends FieldBase
536574 }
537575 }
538576
539- private function appendUV (sprite : FlxSprite , uv : Vector <Float >, flipY : Bool , sub : Int )
577+ private function appendUV (sprite : FlxSprite , uv : Vector <Float >, flipY : Bool , sub : Int , ? currentSubdivisions : Int )
540578 {
579+ if (currentSubdivisions == null ) currentSubdivisions = adaptiveSubdivisions ;
580+
541581 var subIndex = sub * 8 ;
542582 var frameRect = sprite .frame .uv ;
543583
544584 if (! flipY )
545- sub = (holdSubdivisions - 1 ) - sub ;
546- var uvSub = 1.0 / holdSubdivisions ;
585+ sub = (currentSubdivisions - 1 ) - sub ;
586+ var uvSub = 1.0 / currentSubdivisions ;
547587 var uvOffset = uvSub * sub ;
548588
549589 var top = 0.0 ;
@@ -772,6 +812,9 @@ class NoteField extends FieldBase
772812
773813 function set_holdSubdivisions (to : Int )
774814 {
815+ // Clamp subdivisions: minimum 1, maximum is the client setting
816+ to = Std .int (Math .max (1 , Math .min (to , ClientPrefs .data .holdSubdivs )));
817+
775818 HOLD_INDICES .length = (to * 6 );
776819 for (sub in 0 ... to )
777820 {
@@ -783,6 +826,7 @@ class NoteField extends FieldBase
783826 HOLD_INDICES [intIndex + 1 ] = vertIndex + 1 ; // RT
784827 HOLD_INDICES [intIndex + 4 ] = vertIndex + 2 ; // LB
785828 }
829+ adaptiveSubdivisions = to ; // Initialize adaptive subdivisions
786830 return holdSubdivisions = to ;
787831 }
788832}
0 commit comments