@@ -14,6 +14,7 @@ class RePaintInline<T extends Object?> extends StatefulWidget {
1414 this .update,
1515 this .tearDown,
1616 this .frameRate,
17+ this .needsPaint = true ,
1718 super .key,
1819 });
1920
@@ -40,6 +41,25 @@ class RePaintInline<T extends Object?> extends StatefulWidget {
4041 /// 120 - 120 frames per second.
4142 final int ? frameRate;
4243
44+ /// The controller needs to be repainted after the update.
45+ ///
46+ /// If `true` , the controller will be repainted.
47+ /// That means the [paint] method will be called after the [update] method.
48+ ///
49+ /// If `false` , the controller will not be repainted.
50+ /// That means the [paint] method
51+ /// will not be called after the [update] method.
52+ ///
53+ /// This is useful when the controller does not need to be repainted
54+ /// after the update if the scene is static and does not changed over time.
55+ ///
56+ /// You can use this flag to optimize the rendering process.
57+ /// For example, implement a frame skipper or a frame limiter.
58+ ///
59+ /// If you want to skip the [update] method too,
60+ /// just check it in the [update] method and return immediately.
61+ final bool needsPaint;
62+
4363 @override
4464 State <RePaintInline <T >> createState () => _RePaintInlineState <T >();
4565}
@@ -72,17 +92,40 @@ final class _InlinePainter<T> extends RePainterBase {
7292
7393 T ? state;
7494
95+ double _delta = 0 ;
96+
7597 @override
76- int ? get frameRate => widget? .frameRate;
98+ bool get needsPaint => _allowFrame && (widget? .needsPaint ?? true );
99+ bool _allowFrame = false ;
77100
78101 @override
79102 void mount (RePaintBox box, PipelineOwner owner) {
80103 state = widget? .setUp? .call (box);
104+ _delta = .0 ;
81105 }
82106
83107 @override
84108 void update (RePaintBox box, Duration elapsed, double delta) {
85- state = widget? .update? .call (box, state as T , delta) ?? state;
109+ _delta += delta;
110+ switch (widget? .frameRate) {
111+ case null :
112+ // No frame rate limit.
113+ _allowFrame = true ;
114+ case <= 0 :
115+ // Skip updating and rendering the game scene.
116+ _allowFrame = false ;
117+ return ;
118+ case int fr when fr > 0 :
119+ final targetFrameTime = 1000 / fr;
120+ if (_delta < targetFrameTime) {
121+ _allowFrame = false ;
122+ return ; // Limit frame rate
123+ }
124+ _allowFrame = true ;
125+ }
126+ final dt = _delta;
127+ _delta = .0 ; // Reset delta
128+ state = widget? .update? .call (box, state as T , dt) ?? state;
86129 }
87130
88131 @override
@@ -92,6 +135,7 @@ final class _InlinePainter<T> extends RePainterBase {
92135
93136 @override
94137 void unmount () {
138+ _delta = .0 ;
95139 widget? .tearDown? .call (state as T );
96140 }
97141}
0 commit comments