Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.1.0

- **ADDED**: `RePaint` and `RePaint.inline` widget now has `repaintBoundary` property.

## 0.0.8

- **FIXED**: Allow to select empty rect in `QuadTree` example.
Expand Down
2 changes: 0 additions & 2 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,6 @@ linter:
unnecessary_statements: true
unnecessary_string_escapes: true
unnecessary_string_interpolations: true
unsafe_html: true
use_full_hex_values_for_flutter_colors: true
use_raw_strings: true
use_string_buffers: true
Expand Down Expand Up @@ -183,7 +182,6 @@ linter:
non_constant_identifier_names: true
constant_identifier_names: true
directives_ordering: true
package_api_docs: true
implementation_imports: true
prefer_interpolation_to_compose_strings: true
unnecessary_brace_in_string_interps: true
Expand Down
2 changes: 1 addition & 1 deletion example/lib/src/feature/fps/fps_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class _FpsScreenState extends State<FpsScreen> {
Positioned.fill(
child: RePaint.inline(
frameRate: frameRate,
repaintBoundary: true,
render: (box, state, canvas) {
final now = DateTime.now();
if (now.second != second) {
Expand Down Expand Up @@ -356,5 +357,4 @@ final class FrameRateGraph extends RePainterBase {

canvas.restore();
}

}
71 changes: 55 additions & 16 deletions example/lib/src/feature/sunflower/sunflower_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import 'dart:math' as math;
import 'dart:typed_data';
import 'dart:ui';
import 'dart:ui' as ui;

import 'package:flutter/material.dart';
import 'package:repaint/repaint.dart';
Expand Down Expand Up @@ -148,12 +148,12 @@ class SunflowerPainter extends PerformanceOverlayPainter {
int max = 10000,
}) : _maxSeeds = max,
_positions = Float32List(max * 6),
_colors = Int32List(max * 3),
/* _colors = Int32List(max * 3),
_vertices = Vertices.raw(
VertexMode.triangles,
Float32List(0),
colors: Int32List(0),
),
), */
_theme = ThemeData.light() {
_initVertices();
}
Expand Down Expand Up @@ -193,18 +193,18 @@ class SunflowerPainter extends PerformanceOverlayPainter {

ThemeData _theme;

final Float32List _positions;
Float32List _positions;

final Int32List _colors;
//final Int32List _colors;

Vertices _vertices;
//Vertices _vertices;

void _initVertices() {
_vertices = Vertices.raw(
/* _vertices = Vertices.raw(
VertexMode.triangles,
_positions,
colors: _colors,
);
); */
}

/// Set the number of seeds in the sunflower
Expand All @@ -215,7 +215,7 @@ class SunflowerPainter extends PerformanceOverlayPainter {

/// Генерирует вершины равнобедренного треугольника, вписанного в окружность
/// с радиусом [radius] и центром в точке [center].
static List<double> generateIsoscelesPoints(
/* static List<double> generateIsoscelesPoints(
Offset center, [
double radius = 6,
]) {
Expand All @@ -232,14 +232,29 @@ class SunflowerPainter extends PerformanceOverlayPainter {
result[y] = center.dy + radius * math.sin(angle);
}
return result;
}
} */

@override
void internalUpdate(RePaintBox box, Duration elapsed, double delta) {
final size = box.size;
final radius = size.shortestSide / 2; // Радиус окружности
final center = size.center(Offset.zero); // Центр окружности

// Draw points
final f32l = _positions = Float32List(_maxSeeds * 2);
for (var i = 0; i < _maxSeeds; i++) {
final outer = i < _seeds;
// Центр треугольника
final Offset(:dx, :dy) = center +
(outer
? _evalOuter(radius, _maxSeeds, i)
: _evalInner(radius, _maxSeeds, i));
f32l
..[i * 2 + 0] = dx
..[i * 2 + 1] = dy;
}

/*
// https://github.com/flutter/flutter/issues/160184#issuecomment-2560184639
int toARGB32(Color color) {
int floatToInt8(double x) => (x * 255.0).round() & 0xff;
Expand Down Expand Up @@ -294,28 +309,52 @@ class SunflowerPainter extends PerformanceOverlayPainter {
VertexMode.triangles,
_positions,
colors: _colors,
);
); */
}

@override
void internalPaint(RePaintBox box, PaintingContext context) {
final canvas = context.canvas;
var paint = Paint()
..style = PaintingStyle.fill
..strokeWidth = 4
..isAntiAlias = false
..blendMode = BlendMode.src
..filterQuality = FilterQuality.none;
..filterQuality = FilterQuality.none
..isAntiAlias = false;

canvas.drawRect(
Offset.zero & box.size,
paint..color = _theme.canvasColor,
);

canvas.drawVertices(
paint = Paint()
..strokeWidth = 8
..blendMode = BlendMode.src
..filterQuality = FilterQuality.none
..strokeCap = StrokeCap.round
..color = _theme.primaryColor
..isAntiAlias = false;

// Draw the sunflower seeds points per batch of 5000.
final count = _maxSeeds;
const batch = 5000;
for (var offset = 0; offset < count; offset += batch) {
final start = offset;
final end = math.min(offset + batch, count);
final positionsView =
Float32List.sublistView(_positions, start * 2, end * 2);
canvas.drawRawPoints(ui.PointMode.points, positionsView, paint);
}

/* canvas.drawRawPoints(
ui.PointMode.points,
_positions,
paint,
); */

/* canvas.drawVertices(
_vertices,
BlendMode.src,
paint,
);
); */
}
}
4 changes: 2 additions & 2 deletions example/macos/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ EXTERNAL SOURCES:

SPEC CHECKSUMS:
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
url_launcher_macos: c82c93949963e55b228a30115bd219499a6fe404
url_launcher_macos: 0fba8ddabfc33ce0a9afe7c5fef5aab3d8d2d673

PODFILE CHECKSUM: 236401fc2c932af29a9fcf0e97baeeb2d750d367

COCOAPODS: 1.15.2
COCOAPODS: 1.16.2
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
Expand Down
38 changes: 34 additions & 4 deletions lib/src/repaint.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class RePaint extends LeafRenderObjectWidget {
/// {@macro repaint}
const RePaint({
required this.painter,
this.repaintBoundary = true,
super.key,
});

Expand All @@ -22,18 +23,22 @@ class RePaint extends LeafRenderObjectWidget {
/// The [update] is called periodically by the loop.
/// The [render] is called to render the scene after the update.
/// The [tearDown] is called to unmount and dispose the controller.
/// The [repaintBoundary] is used to create a new layer for the scene.
/// The [key] is used to identify the widget.
///
/// After the [frameRate] is set, the real frame rate will be lower.
/// Before the frame rate, updates are limited by the flutter ticker,
/// so the resulting frame rate will be noticeably lower.
///
/// By default, the [repaintBoundary] is set to false for [inline] widgets.
/// {@macro repaint}
static Widget inline<T>({
required void Function(RePaintBox box, T state, Canvas canvas) render,
T Function(RePaintBox box)? setUp,
T? Function(RePaintBox box, T state, double delta)? update,
void Function(T state)? tearDown,
int? frameRate,
bool repaintBoundary = false,
Key? key,
}) =>
RePaintInline<T>(
Expand All @@ -42,24 +47,38 @@ class RePaint extends LeafRenderObjectWidget {
update: update,
tearDown: tearDown,
frameRate: frameRate,
repaintBoundary: repaintBoundary,
key: key,
);

/// The painter controller.
/// The painter controller, used to update and paint the scene.
/// For example, a game controller or a custom painter.
final RePainter painter;

/// Whether the controller should create a new layer for the scene.
/// If `true`, the controller will create a new layer for the scene.
/// If `false`, the controller will not create a new layer for the scene.
///
/// This is useful when the controller needs to be repainted frequently
/// separately from the other widgets and the scene is complex
/// and has many layers.
final bool repaintBoundary;

@override
RePaintElement createElement() => RePaintElement(this);

@override
RenderObject createRenderObject(BuildContext context) => RePaintBox(
painter: painter,
context: context,
isRepaintBoundary: repaintBoundary,
);

@override
void updateRenderObject(BuildContext context, RePaintBox renderObject) {
renderObject._context = context;
renderObject
.._context = context
..isRepaintBoundary = repaintBoundary;
if (identical(painter, renderObject.painter)) return;
if (renderObject.attached) painter.unmount();
assert(renderObject.owner != null, 'RenderObject is not attached.');
Expand Down Expand Up @@ -109,8 +128,10 @@ class RePaintBox extends RenderBox with WidgetsBindingObserver {
RePaintBox({
required RePainter painter,
required BuildContext context,
required bool isRepaintBoundary,
}) : _painter = painter,
_context = context;
_context = context,
_$isRepaintBoundary = isRepaintBoundary;

/// Current controller.
RePainter get painter => _painter;
Expand All @@ -128,8 +149,17 @@ class RePaintBox extends RenderBox with WidgetsBindingObserver {
Size get size => _size;
Size _size = Size.zero;

bool _$isRepaintBoundary;

// Change the repaint boundary flag.
set isRepaintBoundary(bool value) {
if (_$isRepaintBoundary == value) return;
_$isRepaintBoundary = value;
markNeedsCompositingBitsUpdate();
}

@override
bool get isRepaintBoundary => true;
bool get isRepaintBoundary => _$isRepaintBoundary;

@override
bool get alwaysNeedsCompositing => false;
Expand Down
13 changes: 12 additions & 1 deletion lib/src/repaint_inline.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class RePaintInline<T extends Object?> extends StatefulWidget {
this.tearDown,
this.frameRate,
this.needsPaint = true,
this.repaintBoundary = false,
super.key,
});

Expand All @@ -41,6 +42,15 @@ class RePaintInline<T extends Object?> extends StatefulWidget {
/// 120 - 120 frames per second.
final int? frameRate;

/// Whether the controller should create a new layer for the scene.
/// If `true`, the controller will create a new layer for the scene.
/// If `false`, the controller will not create a new layer for the scene.
///
/// This is useful when the controller needs to be repainted frequently
/// separately from the other widgets and the scene is complex
/// and has many layers.
final bool repaintBoundary;

/// The controller needs to be repainted after the update.
///
/// If `true`, the controller will be repainted.
Expand Down Expand Up @@ -80,7 +90,8 @@ class _RePaintInlineState<T> extends State<RePaintInline<T>> {
}

@override
Widget build(BuildContext context) => RePaint(painter: painter);
Widget build(BuildContext context) =>
RePaint(painter: painter, repaintBoundary: widget.repaintBoundary);
}

/// Internal controller for inline state.
Expand Down
4 changes: 2 additions & 2 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: repaint
description: >
Library for creating and managing a canvas similar to CustomPaint but with more features.

version: 0.0.8
version: 0.1.0

homepage: https://github.com/PlugFox/repaint

Expand Down Expand Up @@ -50,7 +50,7 @@ dev_dependencies:
sdk: flutter
test: ^1.25.0
fake_async: ^1.3.0
flutter_lints: '>=4.0.0 <6.0.0'
flutter_lints: ">=4.0.0 <6.0.0"
benchmark_harness: ^2.3.1
flame: ^1.23.0
vector_math: ^2.1.4