Features
3D Transforms
Views can now have full 3D transformations via their transform property. This works because AffineTransform has been updated to support scale,
rotation, and translations that involve x, y and z axes. The result is that Views can now be placed in a full 3D space by simply giving them a
transform that has been modified accordingly.
import io.nacular.doodle.drawing.AffineTransform.Companion.Identity
import io.nacular.measured.units.Angle.Companion.degrees
// Rotate this View around they y-axis (through its center) by 45°
view.transform *= Identity.rotateY(around = view.center, by = 45 * degrees)Views can also now render in 3D, since Canvas also supports the new 3D transforms.
view {
render = {
transform(Identity.rotateY(by = 45 * degrees)) {
// ...
}
}
}3D Perspective
A realistic 3D space requires more than just affine transforms (which keep parallel lines parallel). Simulating this requires perspective transforms. Views now
have a camera property, which gives them a perspective when combined with a 3D transform. The following allows the y-axis rotation to look more realistic.
import io.nacular.doodle.drawing.AffineTransform.Companion.Identity
import io.nacular.measured.units.Angle.Companion.degrees
// Rotate this View around they y-axis (through its center) by 45°
view.transform *= Identity.rotateY(around = view.center, by = 45 * degrees)
// Position the View's camera to apply some realistic perspective warping
view.camera = Camera(position = view.center, distance = 1000.0)Canvas also takes a Camera in its transform method to enable perspective.
view {
render = {
transform(Identity.rotateY(by = 45 * degrees), camera = Camera(Origin, distance = 1000.0)) {
// ...
}
}
}Kotlin 1.7 Support
Doodle now supports 1.7.10!!
APIs
- New
View.intersectsmethod to simplify hit detection. This method works on a point that has been transformed into the View's plane. - Improved utilities for
PointerListeners andPointerMotionListeners that need to monitor a subset of the events. ConvexPolygon.reversedcreates a polygon with the points in reverse order- New
AffineTransform2Dtype to handle cases where full 3D transforms aren't supported (likePatternPainttransforms) AffineTransformnow represents 3D transforms and its APIs have been updated to reflect thisVector2D(alias forPoint) andVector3Dtypes to represent 2D and 3D points- [Breaking]
PathandPathBuilderare now sealed - [Breaking]
AffineMatrix3Dis nowinternal - [Breaking] Remove AffineTransform extensions for times/div(Number), and plus/minus(AffineTransform)
- [Breaking] No longer exposing AffineMatrix3D
- [Breaking] Fixed bug in
squareMatrixOfwhererowandcolwere reversed
Fixes | Improvements
- General
- Improved Matrix performance by switching from List to Array
- Render issue in
PathIcon - AffineTransform.scale when z != 1
- Edge case in RenderManagerImpl when View becomes invisible before it is first rendered
- Bug in FilteredList iterator implementation
- Browser
- UrlView not updating
urlvalue - Text can become blurry on Windows when transform applied to a View
- Fixed clipping withing
PatternPaint - Added work-around for cases (i.e. in
Document) whereRealGraphicsSurfaceis created as top-level, but is not within the display root.
- UrlView not updating
- Desktop
- Fixed antialias on
Canvasclipping
- Fixed antialias on
Dependencies
- Kotlin -> 1.7.10
- Coroutines -> 1.6.3
- DateTime -> 0.3.3
- Skiko -> 0.7.22
- Mockk -> 1.12.4