Adding support for parametric path origin.

This commit is contained in:
Luigi Rosso
2020-11-17 16:02:16 -08:00
parent 6816587bca
commit 8e1718c7bd
17 changed files with 182 additions and 90 deletions

View File

@ -105,7 +105,7 @@ abstract class ArtboardBase extends ContainerComponent {
double _originX;
static const int originXPropertyKey = 11;
/// Origin x in normalized coordinates (0 = center, -1 = left, 1 = right).
/// Origin x in normalized coordinates (0.5 = center, 0 = left, 1 = right).
double get originX => _originX;
/// Change the [_originX] field value.
@ -126,7 +126,7 @@ abstract class ArtboardBase extends ContainerComponent {
double _originY;
static const int originYPropertyKey = 12;
/// Origin y in normalized coordinates (0 = center, -1 = left, 1 = right).
/// Origin y in normalized coordinates (0.5 = center, 0 = top, 1 = bottom).
double get originY => _originY;
/// Change the [_originY] field value.

View File

@ -500,6 +500,16 @@ class RiveCoreContext {
object.height = value;
}
break;
case ParametricPathBase.originXPropertyKey:
if (object is ParametricPathBase && value is double) {
object.originX = value;
}
break;
case ParametricPathBase.originYPropertyKey:
if (object is ParametricPathBase && value is double) {
object.originY = value;
}
break;
case RectangleBase.cornerRadiusPropertyKey:
if (object is RectangleBase && value is double) {
object.cornerRadius = value;
@ -738,6 +748,8 @@ class RiveCoreContext {
case CubicAsymmetricVertexBase.outDistancePropertyKey:
case ParametricPathBase.widthPropertyKey:
case ParametricPathBase.heightPropertyKey:
case ParametricPathBase.originXPropertyKey:
case ParametricPathBase.originYPropertyKey:
case RectangleBase.cornerRadiusPropertyKey:
case CubicMirroredVertexBase.rotationPropertyKey:
case CubicMirroredVertexBase.distancePropertyKey:
@ -918,6 +930,10 @@ class RiveCoreContext {
return (object as ParametricPathBase).width;
case ParametricPathBase.heightPropertyKey:
return (object as ParametricPathBase).height;
case ParametricPathBase.originXPropertyKey:
return (object as ParametricPathBase).originX;
case ParametricPathBase.originYPropertyKey:
return (object as ParametricPathBase).originY;
case RectangleBase.cornerRadiusPropertyKey:
return (object as RectangleBase).cornerRadius;
case CubicMirroredVertexBase.rotationPropertyKey:
@ -1201,6 +1217,12 @@ class RiveCoreContext {
case ParametricPathBase.heightPropertyKey:
(object as ParametricPathBase).height = value;
break;
case ParametricPathBase.originXPropertyKey:
(object as ParametricPathBase).originX = value;
break;
case ParametricPathBase.originYPropertyKey:
(object as ParametricPathBase).originY = value;
break;
case RectangleBase.cornerRadiusPropertyKey:
(object as RectangleBase).cornerRadius = value;
break;

View File

@ -64,4 +64,46 @@ abstract class ParametricPathBase extends Path {
}
void heightChanged(double from, double to);
/// --------------------------------------------------------------------------
/// OriginX field with key 123.
double _originX = 0.5;
static const int originXPropertyKey = 123;
/// Origin x in normalized coordinates (0.5 = center, 0 = left, 1 = right).
double get originX => _originX;
/// Change the [_originX] field value.
/// [originXChanged] will be invoked only if the field's value has changed.
set originX(double value) {
if (_originX == value) {
return;
}
double from = _originX;
_originX = value;
originXChanged(from, value);
}
void originXChanged(double from, double to);
/// --------------------------------------------------------------------------
/// OriginY field with key 124.
double _originY = 0.5;
static const int originYPropertyKey = 124;
/// Origin y in normalized coordinates (0.5 = center, 0 = top, 1 = bottom).
double get originY => _originY;
/// Change the [_originY] field value.
/// [originYChanged] will be invoked only if the field's value has changed.
set originY(double value) {
if (_originY == value) {
return;
}
double from = _originY;
_originY = value;
originYChanged(from, value);
}
void originYChanged(double from, double to);
}

View File

@ -64,9 +64,7 @@ class RiveRenderObject extends RiveRenderBox {
AABB get aabb {
var width = _artboard.width;
var height = _artboard.height;
double minX = -1 * _artboard.originX * width;
double minY = -1 * _artboard.originY * height;
return AABB.fromValues(minX, minY, minX + width, minY + height);
return AABB.fromValues(0, 0, width, height);
}
@override

View File

@ -13,6 +13,10 @@ abstract class ContainerComponent extends ContainerComponentBase {
child.parent = this;
}
void prependChild(Component child) {
child.parent = this;
}
@mustCallSuper
void childAdded(Component child) {}
void childRemoved(Component child) {}

View File

@ -39,6 +39,12 @@ abstract class Drawable extends DrawableBase {
return true;
}
@override
void parentChanged(ContainerComponent from, ContainerComponent to) {
super.parentChanged(from, to);
addDirt(ComponentDirt.clip);
}
@override
void update(int dirt) {
super.update(dirt);

View File

@ -45,13 +45,7 @@ class AABB {
]);
}
double get area => width * height;
bool get isEmpty {
return _buffer[0] == double.maxFinite &&
_buffer[1] == double.maxFinite &&
_buffer[2] == -double.maxFinite &&
_buffer[3] == -double.maxFinite;
}
bool get isEmpty => !AABB.isValid(this);
Vec2D includePoint(Vec2D point, Mat2D transform) {
var transformedPoint = transform == null
? point

View File

@ -78,6 +78,15 @@ class TransformComponents {
return Vec2D.fromValues(_buffer[2], _buffer[3]);
}
static void copy(TransformComponents source, TransformComponents other) {
source._buffer[0] = other._buffer[0];
source._buffer[1] = other._buffer[1];
source._buffer[2] = other._buffer[2];
source._buffer[3] = other._buffer[3];
source._buffer[4] = other._buffer[4];
source._buffer[5] = other._buffer[5];
}
@override
String toString() {
return 'TransformComponents(x: $x y: $y sx: $scaleX '

View File

@ -28,7 +28,7 @@ class ClippingShape extends ClippingShapeBase {
@override
void sourceIdChanged(int from, int to) {
_source = context?.resolve(to);
source = context?.resolve(to);
}
@override

View File

@ -6,36 +6,41 @@ export 'package:rive/src/generated/shapes/ellipse_base.dart';
class Ellipse extends EllipseBase {
@override
List<PathVertex> get vertices => [
CubicDetachedVertex.fromValues(
x: 0,
y: -radiusY,
inX: -radiusX * circleConstant,
inY: -radiusY,
outX: radiusX * circleConstant,
outY: -radiusY),
CubicDetachedVertex.fromValues(
x: radiusX,
y: 0,
inX: radiusX,
inY: circleConstant * -radiusY,
outX: radiusX,
outY: circleConstant * radiusY),
CubicDetachedVertex.fromValues(
x: 0,
y: radiusY,
inX: radiusX * circleConstant,
inY: radiusY,
outX: -radiusX * circleConstant,
outY: radiusY),
CubicDetachedVertex.fromValues(
x: -radiusX,
y: 0,
inX: -radiusX,
inY: radiusY * circleConstant,
outX: -radiusX,
outY: -radiusY * circleConstant)
];
List<PathVertex> get vertices {
double ox = -originX * width + radiusX;
double oy = -originY * height + radiusY;
return [
CubicDetachedVertex.fromValues(
x: ox,
y: oy - radiusY,
inX: ox - radiusX * circleConstant,
inY: oy - radiusY,
outX: ox + radiusX * circleConstant,
outY: oy - radiusY),
CubicDetachedVertex.fromValues(
x: ox + radiusX,
y: oy,
inX: ox + radiusX,
inY: oy + circleConstant * -radiusY,
outX: ox + radiusX,
outY: oy + circleConstant * radiusY),
CubicDetachedVertex.fromValues(
x: ox,
y: oy + radiusY,
inX: ox + radiusX * circleConstant,
inY: oy + radiusY,
outX: ox - radiusX * circleConstant,
outY: oy + radiusY),
CubicDetachedVertex.fromValues(
x: ox - radiusX,
y: oy,
inX: ox - radiusX,
inY: oy + radiusY * circleConstant,
outX: ox - radiusX,
outY: oy - radiusY * circleConstant)
];
}
double get radiusX => width / 2;
double get radiusY => height / 2;
}

View File

@ -42,4 +42,9 @@ abstract class ParametricPath extends ParametricPathBase {
super.scaleYChanged(from, to);
shape?.pathChanged(this);
}
@override
void originXChanged(double from, double to) => markPathDirty();
@override
void originYChanged(double from, double to) => markPathDirty();
}

View File

@ -30,18 +30,17 @@ class PathComposer extends PathComposerBase {
localPath.reset();
var world = _shape.worldTransform;
Mat2D inverseWorld = Mat2D();
if (!Mat2D.invert(inverseWorld, world)) {
Mat2D.identity(inverseWorld);
}
for (final path in _shape.paths) {
Mat2D localTransform;
var transform = path.pathTransform;
if (transform != null) {
localTransform = Mat2D();
Mat2D.multiply(localTransform, inverseWorld, transform);
if (Mat2D.invert(inverseWorld, world)) {
for (final path in _shape.paths) {
Mat2D localTransform;
var transform = path.pathTransform;
if (transform != null) {
localTransform = Mat2D();
Mat2D.multiply(localTransform, inverseWorld, transform);
}
localPath.addPath(path.uiPath, ui.Offset.zero,
matrix4: localTransform?.mat4);
}
localPath.addPath(path.uiPath, ui.Offset.zero,
matrix4: localTransform?.mat4);
}
}
if (buildWorldPath) {

View File

@ -10,7 +10,7 @@ export 'package:rive/src/generated/shapes/path_vertex_base.dart';
abstract class PathVertex<T extends Weight> extends PathVertexBase {
T _weight;
T get weight => _weight;
Path get path => parent as Path;
Path get path => parent is Path ? parent as Path : null;
@override
void update(int dirt) {}
final Vec2D _renderTranslation = Vec2D();

View File

@ -5,24 +5,29 @@ export 'package:rive/src/generated/shapes/rectangle_base.dart';
class Rectangle extends RectangleBase {
@override
List<PathVertex> get vertices => [
StraightVertex()
..x = -width / 2
..y = -height / 2
..radius = cornerRadius,
StraightVertex()
..x = width / 2
..y = -height / 2
..radius = cornerRadius,
StraightVertex()
..x = width / 2
..y = height / 2
..radius = cornerRadius,
StraightVertex()
..x = -width / 2
..y = height / 2
..radius = cornerRadius
];
List<PathVertex> get vertices {
double ox = -originX * width;
double oy = -originY * height;
return [
StraightVertex()
..x = ox
..y = oy
..radius = cornerRadius,
StraightVertex()
..x = ox + width
..y = oy
..radius = cornerRadius,
StraightVertex()
..x = ox + width
..y = oy + height
..radius = cornerRadius,
StraightVertex()
..x = ox
..y = oy + height
..radius = cornerRadius
];
}
@override
void cornerRadiusChanged(double from, double to) => markPathDirty();
}

View File

@ -5,15 +5,19 @@ export 'package:rive/src/generated/shapes/triangle_base.dart';
class Triangle extends TriangleBase {
@override
List<PathVertex> get vertices => [
StraightVertex()
..x = 0
..y = -height / 2,
StraightVertex()
..x = width / 2
..y = height / 2,
StraightVertex()
..x = -width / 2
..y = height / 2
];
List<PathVertex> get vertices {
double ox = -originX * width;
double oy = -originY * height;
return [
StraightVertex()
..x = ox + width / 2
..y = oy,
StraightVertex()
..x = ox + width
..y = oy + height,
StraightVertex()
..x = ox
..y = oy + height
];
}
}

View File

@ -1,9 +1,8 @@
import 'dart:convert';
import 'dart:typed_data';
var _utf8Decoder = const Utf8Decoder();
class BinaryReader {
final _utf8Decoder = const Utf8Decoder();
final ByteData buffer;
final Endian endian;
@ -106,7 +105,7 @@ class BinaryReader {
return value;
}
Uint8List read(int length, [bool allocNew = false]) {
Uint8List read(int length, [bool allocNew = true]) {
var view =
Uint8List.view(buffer.buffer, buffer.offsetInBytes + readIndex, length);
readIndex += length;

View File

@ -3,10 +3,10 @@ import 'dart:math';
import 'dart:typed_data';
var _variableEncodeList = Uint8List(8);
var _utf8Encoder = const Utf8Encoder();
class BinaryWriter {
final _variableEncodeList = Uint8List(8);
final _utf8Encoder = const Utf8Encoder();
/// Stride we allocate buffer in chunks of.
final int _alignment;
int get alignment => _alignment;