diff --git a/CHANGELOG.md b/CHANGELOG.md index 1918ed0..56f2d91 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [0.9.7] +- added `MovieClip.gotoAndPlay` lastFrame for animation. +- exposed the `GifAtlas::textureFrames` so they can be used in MovieClips. +- added several methods from Flutters Path in `Graphics`... (conicCurveTo(), arcToPoint(), arc()) with some new optional parameters for relative drawing. +- added new signals for `stage.onMouseEnter`, `stage.onMouseLeave` to detect touch positions when it leaves the Widget area... ( useful for scene with buttons). + ## [0.9.6+2] - change `flutter_svg` version to be compatible with stable branch. diff --git a/lib/src/core/scene_painter.dart b/lib/src/core/scene_painter.dart index 721530f..63544f3 100644 --- a/lib/src/core/scene_painter.dart +++ b/lib/src/core/scene_painter.dart @@ -166,7 +166,9 @@ class ScenePainter with EventDispatcherMixin { void _mouseInputHandler(MouseInputData input) { input.time = $accumulatedFrameDeltaTime; - + // if (input.type != MouseInputType.still) { + // trace(input.type); + // } /// process it. if (input.type == MouseInputType.move || input.type == MouseInputType.exit) { @@ -180,6 +182,7 @@ class ScenePainter with EventDispatcherMixin { _lastMouseY = input.stageY; } _lastMouseInput = input; + stage.captureMouseInput(input); } diff --git a/lib/src/display/bitmap.dart b/lib/src/display/bitmap.dart index 4162a55..8ef18f1 100644 --- a/lib/src/display/bitmap.dart +++ b/lib/src/display/bitmap.dart @@ -65,7 +65,7 @@ class Bitmap extends DisplayObject { return out; } - final _paint = Paint(); + final _paint = Paint()..filterQuality = FilterQuality.high; Paint get nativePaint => _paint; diff --git a/lib/src/display/stage.dart b/lib/src/display/stage.dart index a693ec9..feb7465 100644 --- a/lib/src/display/stage.dart +++ b/lib/src/display/stage.dart @@ -26,7 +26,7 @@ import 'display_object.dart'; /// they will always contain default values: /// x, y, width, height, stageWidth, stageHeight, mask, name, filter. class Stage extends DisplayObjectContainer - with ResizeSignalMixin, TickerSignalMixin { + with ResizeSignalMixin, TickerSignalMixin, StageMouseSignalsMixin { final ScenePainter scene; static final _sMatrix = GxMatrix(); @@ -162,6 +162,27 @@ class Stage extends DisplayObjectContainer return super.hitTest(localPoint) ?? this; } + bool _isMouseInside = false; + + /// tells if the pointer is inside the stage area (available to detect + /// events). + bool get isMouseInside => _isMouseInside; + + /// capture context mouse inputs. + @override + void captureMouseInput(MouseInputData input) { + if (input.type == MouseInputType.exit) { + _isMouseInside = false; + var mouseInput = input.clone(this, this, input.type); + $onMouseLeave?.dispatch(mouseInput); + } else if (input.type == MouseInputType.unknown && !_isMouseInside) { + _isMouseInside = true; + $onMouseEnter?.dispatch(input.clone(this, this, MouseInputType.enter)); + } else { + super.captureMouseInput(input); + } + } + GxRect getStageBounds(DisplayObject targetSpace, [GxRect out]) { out ??= GxRect(); out.setTo(0, 0, stageWidth, stageHeight); @@ -190,6 +211,7 @@ class Stage extends DisplayObjectContainer $disposeDisplayListSignals(); $disposeResizeSignals(); $disposeTickerSignals(); + $disposeStagePointerSignals(); super.dispose(); } diff --git a/lib/src/events/mixins.dart b/lib/src/events/mixins.dart index 552bb94..d5c5753 100644 --- a/lib/src/events/mixins.dart +++ b/lib/src/events/mixins.dart @@ -98,6 +98,22 @@ mixin RenderSignalMixin { } } +/// use mouse signal for now. +mixin StageMouseSignalsMixin { + EventSignal $onMouseLeave; + EventSignal $onMouseEnter; + + EventSignal get onMouseLeave => $onMouseLeave ??= EventSignal(); + EventSignal get onMouseEnter => $onMouseEnter ??= EventSignal(); + + void $disposeStagePointerSignals() { + $onMouseLeave?.removeAll(); + $onMouseLeave = null; + $onMouseEnter?.removeAll(); + $onMouseEnter = null; + } +} + /// use mouse signal for now. mixin MouseSignalsMixin { EventSignal $onRightMouseDown; diff --git a/lib/src/events/pointer_data.dart b/lib/src/events/pointer_data.dart index 667af01..676cdca 100644 --- a/lib/src/events/pointer_data.dart +++ b/lib/src/events/pointer_data.dart @@ -95,6 +95,7 @@ enum MouseInputType { move, down, exit, + enter, up, click, still, diff --git a/lib/src/geom/gxrect.dart b/lib/src/geom/gxrect.dart index cf56d45..47977e2 100644 --- a/lib/src/geom/gxrect.dart +++ b/lib/src/geom/gxrect.dart @@ -94,7 +94,7 @@ class GxRect { GxRect intersection(GxRect rect) { GxRect result; - var x0 = x < rect.x ? rect.x : 0; + var x0 = x < rect.x ? rect.x : 0.0; var x1 = right > rect.right ? rect.right : right; if (x1 <= 0) { result = GxRect(); diff --git a/lib/src/render/graphics.dart b/lib/src/render/graphics.dart index f54f6fa..3de1efa 100644 --- a/lib/src/render/graphics.dart +++ b/lib/src/render/graphics.dart @@ -434,6 +434,17 @@ class Graphics with RenderUtilMixin implements GxRenderable { return this; } + Graphics conicCurveTo(double controlX, double controlY, double anchorX, + double anchorY, double weight, + [bool relative = false]) { + if (!relative) { + _path.conicTo(controlX, controlY, anchorX, anchorY, weight); + } else { + _path.relativeConicTo(controlX, controlY, anchorX, anchorY, weight); + } + return this; + } + Graphics drawCircle(double x, double y, double radius) { final pos = Offset(x, y); final circ = Rect.fromCircle(center: pos, radius: radius); @@ -541,15 +552,56 @@ class Graphics with RenderUtilMixin implements GxRenderable { return this; } - Graphics arc(double cx, double cy, double radius, double startAngle, - double sweepAngle) { + Graphics arc( + double cx, double cy, double radius, double startAngle, double sweepAngle, + [bool moveTo = false]) { if (sweepAngle == 0) return this; -// _path.arcToPoint(arcEnd) - _path.addArc( - Rect.fromCircle(center: Offset(cx, cy), radius: radius), - startAngle, - sweepAngle, - ); + if (!moveTo) { + _path.arcTo( + Rect.fromCircle(center: Offset(cx, cy), radius: radius), + startAngle, + sweepAngle, + false, + ); + } else { + _path.addArc( + Rect.fromCircle(center: Offset(cx, cy), radius: radius), + startAngle, + sweepAngle, + ); + } + + return this; + } + + Graphics arcToPoint( + double endX, + double endY, + double radius, [ + double rotation = 0.0, + bool largeArc = false, + bool clockwise = true, + bool relativeMoveTo = false, + ]) { + if (radius == 0) return this; + if (relativeMoveTo) { + _path.arcToPoint( + Offset(endX, endY), + radius: Radius.circular(radius), + clockwise: clockwise, + largeArc: largeArc, + rotation: rotation, + ); + } else { + _path.relativeArcToPoint( + Offset(endX, endY), + radius: Radius.circular(radius), + clockwise: clockwise, + largeArc: largeArc, + rotation: rotation, + ); + } + return this; } diff --git a/lib/src/render/movie_clip.dart b/lib/src/render/movie_clip.dart index 8b9845c..c0e6414 100644 --- a/lib/src/render/movie_clip.dart +++ b/lib/src/render/movie_clip.dart @@ -17,6 +17,9 @@ class MovieClip extends Bitmap { /// render into what int frameCount = 0; int currentFrame = -1; + + /// stops the playback when reaching this frame. + int targetFrame = -1; Bitmap bitmap; Signal _onFramesComplete; @@ -51,8 +54,14 @@ class MovieClip extends Bitmap { texture = _frameTextures[currentFrame]; } - void gotoAndPlay(int frame) { + void gotoAndPlay(int frame, {int lastFrame = -1}) { gotoFrame(frame); + if (lastFrame > frameCount) { + lastFrame %= frameCount; + } else if (lastFrame > -1 && lastFrame < frame) { + /// TODO: add repeatable logic? + } + targetFrame = lastFrame; play(); } @@ -93,6 +102,9 @@ class MovieClip extends Bitmap { return; } } + if (targetFrame > -1 && currentFrame == targetFrame) { + playing = false; + } texture = _frameTextures[currentFrame]; } accumulatedTime %= speed; diff --git a/lib/src/textures/gif_atlas.dart b/lib/src/textures/gif_atlas.dart index 54cbdc2..2d5f026 100644 --- a/lib/src/textures/gif_atlas.dart +++ b/lib/src/textures/gif_atlas.dart @@ -9,6 +9,10 @@ class GifFrame { class GifAtlas extends GTexture { final List _frames = []; + List get textureFrames { + return _frames.map((e) => e.texture).toList(); + } + void addFrame(GifFrame frame) { _frames.add(frame); if (_frames.length == 1) { diff --git a/pubspec.yaml b/pubspec.yaml index 2c434e4..430ed34 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: graphx description: Render API on top of CustomPainter to power-up your Flutter apps to the next level. -version: 0.9.6+2 +version: 0.9.7 homepage: https://github.com/roipeker/graphx environment: