浏览代码

Merge remote-tracking branch 'origin/master' into image

/main
gewentao 6 年前
当前提交
0fe729c6
共有 51 个文件被更改,包括 4862 次插入49 次删除
  1. 6
      .gitignore
  2. 5
      Assets/UIWidgets/Tests/Menu.cs
  3. 57
      Assets/UIWidgets/painting/basic_types.cs
  4. 118
      Assets/UIWidgets/rendering/object.mixin.gen.cs
  5. 17
      Assets/UIWidgets/rendering/object.mixin.njk
  6. 2
      Assets/UIWidgets/rendering/shifted_box.cs
  7. 514
      Assets/UIWidgets/rendering/sliver.cs
  8. 736
      Assets/UIWidgets/rendering/viewpoint.cs
  9. 61
      Assets/UIWidgets/rendering/viewport_offset.cs
  10. 35
      Assets/UIWidgets/ui/geometry.cs
  11. 10
      Assets/UIWidgets/ui/painting/canvas.cs
  12. 15
      Assets/UIWidgets/ui/painting/canvas_impl.cs
  13. 8
      Assets/UIWidgets/ui/painting/draw_cmd.cs
  14. 8
      Assets/UIWidgets/ui/painting/picture.cs
  15. 401
      Assets/UIWidgets/ui/text.cs
  16. 70
      Assets/UIWidgets/Resources/UIWidgets_Text.shader
  17. 3
      Assets/UIWidgets/Resources/UIWidgets_Text.shader.meta
  18. 152
      Assets/UIWidgets/Tests/Paragraph.cs
  19. 3
      Assets/UIWidgets/Tests/Paragraph.cs.meta
  20. 3
      Assets/UIWidgets/math.meta
  21. 288
      Assets/UIWidgets/painting/text_painter.cs
  22. 3
      Assets/UIWidgets/painting/text_painter.cs.meta
  23. 246
      Assets/UIWidgets/painting/text_span.cs
  24. 3
      Assets/UIWidgets/painting/text_span.cs.meta
  25. 86
      Assets/UIWidgets/painting/text_style.cs
  26. 3
      Assets/UIWidgets/painting/text_style.cs.meta
  27. 235
      Assets/UIWidgets/rendering/paragraph.cs
  28. 3
      Assets/UIWidgets/rendering/paragraph.cs.meta
  29. 170
      Assets/UIWidgets/rendering/sliver_fixed_extent_list.cs
  30. 3
      Assets/UIWidgets/rendering/sliver_fixed_extent_list.cs.meta
  31. 194
      Assets/UIWidgets/rendering/sliver_list.cs
  32. 3
      Assets/UIWidgets/rendering/sliver_list.cs.meta
  33. 299
      Assets/UIWidgets/rendering/sliver_multi_box_adaptor.cs
  34. 3
      Assets/UIWidgets/rendering/sliver_multi_box_adaptor.cs.meta
  35. 232
      Assets/UIWidgets/rendering/sliver_padding.cs
  36. 3
      Assets/UIWidgets/rendering/sliver_padding.cs.meta
  37. 3
      Assets/UIWidgets/ui/txt.meta
  38. 2
      Assets/UIWidgets/gestures/arena.cs
  39. 14
      Assets/UIWidgets/math/math.cs
  40. 3
      Assets/UIWidgets/math/math.cs.meta
  41. 3
      Assets/UIWidgets/ui/txt/linebreaker.cs.meta
  42. 3
      Assets/UIWidgets/ui/txt/paragraph.cs.meta
  43. 3
      Assets/UIWidgets/ui/txt/paragraph_builder.cs.meta
  44. 161
      Assets/UIWidgets/ui/txt/styled_runs.cs
  45. 3
      Assets/UIWidgets/ui/txt/styled_runs.cs.meta
  46. 152
      Assets/UIWidgets/ui/txt/linebreaker.cs
  47. 490
      Assets/UIWidgets/ui/txt/paragraph.cs
  48. 76
      Assets/UIWidgets/ui/txt/paragraph_builder.cs

6
.gitignore


# Builds
*.apk
*.unitypackage
# node.js
#
node_modules/
npm-debug.log
yarn-error.log

5
Assets/UIWidgets/Tests/Menu.cs


public static void renderBoxes() {
EditorWindow.GetWindow(typeof(RenderBoxes));
}
[MenuItem("UIWidgetsTests/RenderParagraph")]
public static void renderRenderParagraph() {
EditorWindow.GetWindow(typeof(Paragraph));
}
}
}

57
Assets/UIWidgets/painting/basic_types.cs


using System;
using System.ComponentModel;
using UIWidgets.ui;
namespace UIWidgets.painting {
public enum AxisDirection {

up,
down,
}
public static class AxisUtils {
public static Axis flipAxis(Axis direction) {
switch (direction) {

return Axis.horizontal;
}
public static Axis axisDirectionToAxis(AxisDirection axisDirection) {
switch (axisDirection) {
case AxisDirection.up:

throw new Exception("unknown axisDirection");
}
public static AxisDirection textDirectionToAxisDirection(TextDirection textDirection) {
switch (textDirection) {
case TextDirection.rtl:
return AxisDirection.left;
case TextDirection.ltr:
return AxisDirection.right;
}
throw new Exception("unknown textDirection");
}
public static AxisDirection flipAxisDirection(AxisDirection axisDirection) {
switch (axisDirection) {
case AxisDirection.up:
return AxisDirection.down;
case AxisDirection.right:
return AxisDirection.left;
case AxisDirection.down:
return AxisDirection.up;
case AxisDirection.left:
return AxisDirection.right;
}
throw new Exception("unknown axisDirection");
}
public static bool axisDirectionIsReversed(AxisDirection axisDirection) {
switch (axisDirection) {
case AxisDirection.up:
case AxisDirection.left:
return true;
case AxisDirection.down:
case AxisDirection.right:
return false;
}
throw new Exception("unknown axisDirection");
}
}
/// The values in this enum are ordered such that they are in increasing order
/// of cost. A value with index N implies all the values with index less than N.
/// For example, [layout] (index 3) implies [paint] (2).
public enum RenderComparison
{
identical,
metadata,
paint,
layout,
}
}

118
Assets/UIWidgets/rendering/object.mixin.gen.cs


}
public abstract class RenderObjectWithChildMixinRenderSliver<ChildType> : RenderSliver where ChildType : RenderObject {
public ChildType _child;
public ChildType child {
get { return this._child; }
set {
if (this._child != null) {
this.dropChild(this._child);
}
this._child = value;
if (this._child != null) {
this.adoptChild(this._child);
}
}
}
public override void attach(object owner) {
base.attach(owner);
if (this._child != null) {
this._child.attach(owner);
}
}
public override void detach() {
base.detach();
if (this._child != null) {
this._child.detach();
}
}
public override void redepthChildren() {
if (this._child != null) {
this.redepthChild(this._child);
}
}
public override void visitChildren(RenderObjectVisitor visitor) {
if (this._child != null) {
visitor(this._child);
}
}
}
public abstract class ContainerParentDataMixinParentData<ChildType> : ParentData, ContainerParentDataMixin<ChildType> where ChildType : RenderObject {

public abstract class ContainerParentDataMixinSliverPhysicalParentData<ChildType> : SliverPhysicalParentData, ContainerParentDataMixin<ChildType> where ChildType : RenderObject {
public ChildType previousSibling { get; set; }
public ChildType nextSibling { get; set; }
public override void detach() {
base.detach();
if (this.previousSibling != null) {
var previousSiblingParentData = (ContainerParentDataMixin<ChildType>) this.previousSibling.parentData;
previousSiblingParentData.nextSibling = this.nextSibling;
}
if (this.nextSibling != null) {
var nextSiblingParentData = (ContainerParentDataMixin<ChildType>) this.nextSibling.parentData;
nextSiblingParentData.previousSibling = this.previousSibling;
}
this.previousSibling = null;
this.nextSibling = null;
}
}
public abstract class ContainerParentDataMixinSliverLogicalParentData<ChildType> : SliverLogicalParentData, ContainerParentDataMixin<ChildType> where ChildType : RenderObject {
public ChildType previousSibling { get; set; }
public ChildType nextSibling { get; set; }
public override void detach() {
base.detach();
if (this.previousSibling != null) {
var previousSiblingParentData = (ContainerParentDataMixin<ChildType>) this.previousSibling.parentData;
previousSiblingParentData.nextSibling = this.nextSibling;
}
if (this.nextSibling != null) {
var nextSiblingParentData = (ContainerParentDataMixin<ChildType>) this.nextSibling.parentData;
nextSiblingParentData.previousSibling = this.previousSibling;
}
this.previousSibling = null;
this.nextSibling = null;
}
}
public abstract class ContainerRenderObjectMixinRenderBox<ChildType, ParentDataType> : RenderBox

public int _childCount = 0;
public int countCount {
public int childCount {
get { return this._childCount; }
}

}
}
public void insert(ChildType child, ChildType after = null) {
public virtual void insert(ChildType child, ChildType after = null) {
public void add(ChildType child) {
public virtual void add(ChildType child) {
public void addAll(List<ChildType> children) {
public virtual void addAll(List<ChildType> children) {
if (children != null) {
children.ForEach(this.add);
}

this._childCount--;
}
public void remove(ChildType child) {
public virtual void remove(ChildType child) {
public void removeAll() {
public virtual void removeAll() {
ChildType child = this._firstChild;
while (child != null) {
var childParentData = (ParentDataType) child.parentData;

public int _childCount = 0;
public int countCount {
public int childCount {
get { return this._childCount; }
}

}
}
public void insert(ChildType child, ChildType after = null) {
public virtual void insert(ChildType child, ChildType after = null) {
public void add(ChildType child) {
public virtual void add(ChildType child) {
public void addAll(List<ChildType> children) {
public virtual void addAll(List<ChildType> children) {
if (children != null) {
children.ForEach(this.add);
}

this._childCount--;
}
public void remove(ChildType child) {
public virtual void remove(ChildType child) {
public void removeAll() {
public virtual void removeAll() {
ChildType child = this._firstChild;
while (child != null) {
var childParentData = (ParentDataType) child.parentData;

17
Assets/UIWidgets/rendering/object.mixin.njk


{{ RenderObjectWithChildMixin('RenderBox') }}
{{ RenderObjectWithChildMixin('RenderSliver') }}
{% macro ContainerParentDataMixin(with) %}
public abstract class ContainerParentDataMixin{{with}}<ChildType> : {{with}}, ContainerParentDataMixin<ChildType> where ChildType : RenderObject {

{{ ContainerParentDataMixin('ParentData') }}
{{ ContainerParentDataMixin('BoxParentData') }}
{{ ContainerParentDataMixin('SliverPhysicalParentData') }}
{{ ContainerParentDataMixin('SliverLogicalParentData') }}
{% macro ContainerRenderObjectMixin(with) %}

public int _childCount = 0;
public int countCount {
public int childCount {
get { return this._childCount; }
}

}
}
public void insert(ChildType child, ChildType after = null) {
public virtual void insert(ChildType child, ChildType after = null) {
public void add(ChildType child) {
public virtual void add(ChildType child) {
public void addAll(List<ChildType> children) {
public virtual void addAll(List<ChildType> children) {
if (children != null) {
children.ForEach(this.add);
}

this._childCount--;
}
public void remove(ChildType child) {
public virtual void remove(ChildType child) {
public void removeAll() {
public virtual void removeAll() {
ChildType child = this._firstChild;
while (child != null) {
var childParentData = (ParentDataType) child.parentData;

2
Assets/UIWidgets/rendering/shifted_box.cs


}
public class RenderPadding : RenderShiftedBox {
RenderPadding(
public RenderPadding(
EdgeInsets padding = null,
RenderBox child = null
) : base(child) {

514
Assets/UIWidgets/rendering/sliver.cs


namespace UIWidgets.rendering {
using System;
using UIWidgets.painting;
using UIWidgets.ui;
using UnityEngine;
using Rect = UIWidgets.ui.Rect;
namespace UIWidgets.rendering {
public enum GrowthDirection {
forward,
reverse,
}
public static class GrowthDirectionUtils {
public static AxisDirection applyGrowthDirectionToAxisDirection(
AxisDirection axisDirection, GrowthDirection growthDirection) {
switch (growthDirection) {
case GrowthDirection.forward:
return axisDirection;
case GrowthDirection.reverse:
return AxisUtils.flipAxisDirection(axisDirection);
}
throw new Exception("unknown growthDirection");
}
public static ScrollDirection applyGrowthDirectionToScrollDirection(
ScrollDirection scrollDirection, GrowthDirection growthDirection) {
switch (growthDirection) {
case GrowthDirection.forward:
return scrollDirection;
case GrowthDirection.reverse:
return ScrollDirectionUtils.flipScrollDirection(scrollDirection);
}
public class SliverPhysicalParentData : ContainerParentDataMixinParentData<RenderSliver> {
throw new Exception("unknown growthDirection");
}
public class SliverPhysicalContainerParentData : SliverPhysicalParentData {
public class SliverConstraints : Constraints, IEquatable<SliverConstraints> {
public SliverConstraints(
AxisDirection axisDirection,
GrowthDirection growthDirection,
ScrollDirection userScrollDirection,
double scrollOffset,
double overlap,
double remainingPaintExtent,
double crossAxisExtent,
AxisDirection crossAxisDirection,
double viewportMainAxisExtent,
double remainingCacheExtent,
double cacheOrigin
) {
this.axisDirection = axisDirection;
this.growthDirection = growthDirection;
this.userScrollDirection = userScrollDirection;
this.scrollOffset = scrollOffset;
this.overlap = overlap;
this.remainingPaintExtent = remainingPaintExtent;
this.crossAxisExtent = crossAxisExtent;
this.crossAxisDirection = crossAxisDirection;
this.viewportMainAxisExtent = viewportMainAxisExtent;
this.remainingCacheExtent = remainingCacheExtent;
this.cacheOrigin = cacheOrigin;
}
public SliverConstraints copyWith(
AxisDirection? axisDirection = null,
GrowthDirection? growthDirection = null,
ScrollDirection? userScrollDirection = null,
double? scrollOffset = null,
double? overlap = null,
double? remainingPaintExtent = null,
double? crossAxisExtent = null,
AxisDirection? crossAxisDirection = null,
double? viewportMainAxisExtent = null,
double? remainingCacheExtent = null,
double? cacheOrigin = null
) {
return new SliverConstraints(
axisDirection: axisDirection ?? this.axisDirection,
growthDirection: growthDirection ?? this.growthDirection,
userScrollDirection: userScrollDirection ?? this.userScrollDirection,
scrollOffset: scrollOffset ?? this.scrollOffset,
overlap: overlap ?? this.overlap,
remainingPaintExtent: remainingPaintExtent ?? this.remainingPaintExtent,
crossAxisExtent: crossAxisExtent ?? this.crossAxisExtent,
crossAxisDirection: crossAxisDirection ?? this.crossAxisDirection,
viewportMainAxisExtent: viewportMainAxisExtent ?? this.viewportMainAxisExtent,
remainingCacheExtent: remainingCacheExtent ?? this.remainingCacheExtent,
cacheOrigin: cacheOrigin ?? this.cacheOrigin
);
}
public readonly AxisDirection axisDirection;
public readonly GrowthDirection growthDirection;
public readonly ScrollDirection userScrollDirection;
public readonly double scrollOffset;
public readonly double overlap;
public readonly double remainingPaintExtent;
public readonly double crossAxisExtent;
public readonly AxisDirection crossAxisDirection;
public readonly double viewportMainAxisExtent;
public readonly double cacheOrigin;
public readonly double remainingCacheExtent;
public Axis axis {
get { return AxisUtils.axisDirectionToAxis(this.axisDirection); }
}
public GrowthDirection normalizedGrowthDirection {
get {
switch (this.axisDirection) {
case AxisDirection.down:
case AxisDirection.right:
return this.growthDirection;
case AxisDirection.up:
case AxisDirection.left:
switch (this.growthDirection) {
case GrowthDirection.forward:
return GrowthDirection.reverse;
case GrowthDirection.reverse:
return GrowthDirection.forward;
}
throw new Exception("unknown growthDirection");
}
throw new Exception("unknown axisDirection");
}
}
public override bool isTight {
get { return false; }
}
public override bool isNormalized {
get {
return this.scrollOffset >= 0.0
&& this.crossAxisExtent >= 0.0
&& AxisUtils.axisDirectionToAxis(this.axisDirection) !=
AxisUtils.axisDirectionToAxis(this.crossAxisDirection)
&& this.viewportMainAxisExtent >= 0.0
&& this.remainingPaintExtent >= 0.0;
}
}
public BoxConstraints asBoxConstraints(
double minExtent = 0.0,
double maxExtent = double.PositiveInfinity,
double? crossAxisExtent = null
) {
crossAxisExtent = crossAxisExtent ?? this.crossAxisExtent;
switch (this.axis) {
case Axis.horizontal:
return new BoxConstraints(
minHeight: crossAxisExtent.Value,
maxHeight: crossAxisExtent.Value,
minWidth: minExtent,
maxWidth: maxExtent
);
case Axis.vertical:
return new BoxConstraints(
minWidth: crossAxisExtent.Value,
maxWidth: crossAxisExtent.Value,
minHeight: minExtent,
maxHeight: maxExtent
);
}
return null;
}
public bool Equals(SliverConstraints other) {
if (object.ReferenceEquals(null, other)) return false;
if (object.ReferenceEquals(this, other)) return true;
return this.axisDirection == other.axisDirection
&& this.growthDirection == other.growthDirection
&& this.userScrollDirection == other.userScrollDirection
&& this.scrollOffset.Equals(other.scrollOffset)
&& this.overlap.Equals(other.overlap)
&& this.remainingPaintExtent.Equals(other.remainingPaintExtent)
&& this.crossAxisExtent.Equals(other.crossAxisExtent)
&& this.crossAxisDirection == other.crossAxisDirection
&& this.viewportMainAxisExtent.Equals(other.viewportMainAxisExtent)
&& this.cacheOrigin.Equals(other.cacheOrigin)
&& this.remainingCacheExtent.Equals(other.remainingCacheExtent);
}
public override bool Equals(object obj) {
if (object.ReferenceEquals(null, obj)) return false;
if (object.ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return this.Equals((SliverConstraints) obj);
}
public override int GetHashCode() {
unchecked {
var hashCode = (int) this.axisDirection;
hashCode = (hashCode * 397) ^ (int) this.growthDirection;
hashCode = (hashCode * 397) ^ (int) this.userScrollDirection;
hashCode = (hashCode * 397) ^ this.scrollOffset.GetHashCode();
hashCode = (hashCode * 397) ^ this.overlap.GetHashCode();
hashCode = (hashCode * 397) ^ this.remainingPaintExtent.GetHashCode();
hashCode = (hashCode * 397) ^ this.crossAxisExtent.GetHashCode();
hashCode = (hashCode * 397) ^ (int) this.crossAxisDirection;
hashCode = (hashCode * 397) ^ this.viewportMainAxisExtent.GetHashCode();
hashCode = (hashCode * 397) ^ this.cacheOrigin.GetHashCode();
hashCode = (hashCode * 397) ^ this.remainingCacheExtent.GetHashCode();
return hashCode;
}
}
public static bool operator ==(SliverConstraints left, SliverConstraints right) {
return Equals(left, right);
}
public static bool operator !=(SliverConstraints left, SliverConstraints right) {
return !Equals(left, right);
}
public class SliverGeometry {
public SliverGeometry(
double scrollExtent = 0.0,
double paintExtent = 0.0,
double paintOrigin = 0.0,
double? layoutExtent = null,
double maxPaintExtent = 0.0,
double maxScrollObstructionExtent = 0.0,
double? hitTestExtent = null,
bool? visible = null,
bool hasVisualOverflow = false,
double scrollOffsetCorrection = 0.0,
double? cacheExtent = null
) {
this.scrollExtent = scrollExtent;
this.paintExtent = paintExtent;
this.paintOrigin = paintOrigin;
this.layoutExtent = layoutExtent ?? paintExtent;
this.maxPaintExtent = maxPaintExtent;
this.maxScrollObstructionExtent = maxScrollObstructionExtent;
this.hitTestExtent = hitTestExtent ?? paintExtent;
this.visible = visible ?? paintExtent > 0.0;
this.hasVisualOverflow = hasVisualOverflow;
this.scrollOffsetCorrection = scrollOffsetCorrection;
this.cacheExtent = cacheExtent ?? layoutExtent ?? paintExtent;
}
public static readonly SliverGeometry zero = new SliverGeometry();
public readonly double scrollExtent;
public readonly double paintOrigin;
public readonly double paintExtent;
public readonly double layoutExtent;
public readonly double maxPaintExtent;
public readonly double maxScrollObstructionExtent;
public readonly double hitTestExtent;
public readonly bool visible;
public readonly bool hasVisualOverflow;
public readonly double scrollOffsetCorrection;
public readonly double cacheExtent;
}
public class SliverPhysicalParentData : ParentData {
public Offset paintOffset = Offset.zero;
public void applyPaintTransform(ref Matrix4x4 transform) {
transform = Matrix4x4.Translate(this.paintOffset.toVector()) * transform;
}
}
public class SliverPhysicalContainerParentData : ContainerParentDataMixinSliverPhysicalParentData<RenderSliver> {
}
public class SliverLogicalParentData : ParentData {
public double layoutOffset = 0.0;
}
public class SliverLogicalContainerParentData : ContainerParentDataMixinSliverLogicalParentData<RenderSliver> {
}
public new SliverConstraints constraints {
get { return (SliverConstraints) base.constraints; }
}
public SliverGeometry geometry {
get { return this._geometry; }
set { this._geometry = value; }
}
public SliverGeometry _geometry;
public override Rect paintBounds {
get {
switch (this.constraints.axis) {
case Axis.horizontal:
return Rect.fromLTWH(
0.0, 0.0,
this.geometry.paintExtent,
this.constraints.crossAxisExtent
);
case Axis.vertical:
return Rect.fromLTWH(
0.0, 0.0,
this.constraints.crossAxisExtent,
this.geometry.paintExtent
);
}
return null;
}
}
public override void performResize() {
}
public double centerOffsetAdjustment {
get { return 0.0; }
}
public double calculatePaintOffset(SliverConstraints constraints, double from, double to) {
double a = constraints.scrollOffset;
double b = constraints.scrollOffset + constraints.remainingPaintExtent;
return (to.clamp(a, b) - from.clamp(a, b)).clamp(0.0, constraints.remainingPaintExtent);
}
public double calculateCacheOffset(SliverConstraints constraints, double from, double to) {
double a = constraints.scrollOffset + constraints.cacheOrigin;
double b = constraints.scrollOffset + constraints.remainingCacheExtent;
return (to.clamp(a, b) - from.clamp(a, b)).clamp(0.0, constraints.remainingCacheExtent);
}
public virtual double childMainAxisPosition(RenderObject child) {
return 0.0;
}
public virtual double childCrossAxisPosition(RenderObject child) {
return 0.0;
}
public virtual double childScrollOffset(RenderObject child) {
return 0.0;
}
public override void applyPaintTransform(RenderObject child, ref Matrix4x4 transform) {
}
public Size getAbsoluteSizeRelativeToOrigin() {
switch (GrowthDirectionUtils.applyGrowthDirectionToAxisDirection(
this.constraints.axisDirection, this.constraints.growthDirection)) {
case AxisDirection.up:
return new Size(this.constraints.crossAxisExtent, -this.geometry.paintExtent);
case AxisDirection.right:
return new Size(this.geometry.paintExtent, this.constraints.crossAxisExtent);
case AxisDirection.down:
return new Size(this.constraints.crossAxisExtent, this.geometry.paintExtent);
case AxisDirection.left:
return new Size(-this.geometry.paintExtent, this.constraints.crossAxisExtent);
}
return null;
}
}
public static class RenderSliverHelpers {
public static bool _getRightWayUp(SliverConstraints constraints) {
bool rightWayUp = true;
switch (constraints.axisDirection) {
case AxisDirection.up:
case AxisDirection.left:
rightWayUp = false;
break;
case AxisDirection.down:
case AxisDirection.right:
rightWayUp = true;
break;
}
switch (constraints.growthDirection) {
case GrowthDirection.forward:
break;
case GrowthDirection.reverse:
rightWayUp = !rightWayUp;
break;
}
return rightWayUp;
}
public static void applyPaintTransformForBoxChild(this RenderSliver it, RenderBox child,
ref Matrix4x4 transform) {
bool rightWayUp = RenderSliverHelpers._getRightWayUp(it.constraints);
double delta = it.childMainAxisPosition(child);
double crossAxisDelta = it.childCrossAxisPosition(child);
switch (it.constraints.axis) {
case Axis.horizontal:
if (!rightWayUp) {
delta = it.geometry.paintExtent - child.size.width - delta;
}
transform = Matrix4x4.Translate(new Vector2((float) delta, (float) crossAxisDelta)) * transform;
break;
case Axis.vertical:
if (!rightWayUp) {
delta = it.geometry.paintExtent - child.size.height - delta;
}
transform = Matrix4x4.Translate(new Vector2((float) crossAxisDelta, (float) delta)) * transform;
break;
}
}
}
public abstract class RenderSliverSingleBoxAdapter : RenderObjectWithChildMixinRenderSliver<RenderBox> {
public RenderSliverSingleBoxAdapter(
RenderBox child = null
) {
this.child = child;
}
public override void setupParentData(RenderObject child) {
if (!(child.parentData is SliverPhysicalParentData)) {
child.parentData = new SliverPhysicalParentData();
}
}
public void setChildParentData(RenderObject child, SliverConstraints constraints, SliverGeometry geometry) {
var childParentData = (SliverPhysicalParentData) child.parentData;
switch (GrowthDirectionUtils.applyGrowthDirectionToAxisDirection(constraints.axisDirection,
constraints.growthDirection)) {
case AxisDirection.up:
childParentData.paintOffset = new Offset(0.0,
-(geometry.scrollExtent - (geometry.paintExtent + constraints.scrollOffset)));
break;
case AxisDirection.right:
childParentData.paintOffset = new Offset(-constraints.scrollOffset, 0.0);
break;
case AxisDirection.down:
childParentData.paintOffset = new Offset(0.0, -constraints.scrollOffset);
break;
case AxisDirection.left:
childParentData.paintOffset =
new Offset(-(geometry.scrollExtent - (geometry.paintExtent + constraints.scrollOffset)), 0.0);
break;
}
}
public override double childMainAxisPosition(RenderObject child) {
return -this.constraints.scrollOffset;
}
public override void applyPaintTransform(RenderObject child, ref Matrix4x4 transform) {
var childParentData = (SliverPhysicalParentData) child.parentData;
childParentData.applyPaintTransform(ref transform);
}
public override void paint(PaintingContext context, Offset offset) {
if (this.child != null && this.geometry.visible) {
var childParentData = (SliverPhysicalParentData) this.child.parentData;
context.paintChild(this.child, offset + childParentData.paintOffset);
}
}
}
public class RenderSliverToBoxAdapter : RenderSliverSingleBoxAdapter {
public RenderSliverToBoxAdapter(
RenderBox child = null
) : base(child) {
}
public override void performLayout() {
if (this.child == null) {
this.geometry = SliverGeometry.zero;
return;
}
this.child.layout(this.constraints.asBoxConstraints(), parentUsesSize: true);
double childExtent = 0.0;
switch (this.constraints.axis) {
case Axis.horizontal:
childExtent = this.child.size.width;
break;
case Axis.vertical:
childExtent = this.child.size.height;
break;
}
double paintedChildSize = this.calculatePaintOffset(this.constraints, from: 0.0, to: childExtent);
double cacheExtent = this.calculateCacheOffset(this.constraints, from: 0.0, to: childExtent);
this.geometry = new SliverGeometry(
scrollExtent: childExtent,
paintExtent: paintedChildSize,
cacheExtent: cacheExtent,
maxPaintExtent: childExtent,
hitTestExtent: paintedChildSize,
hasVisualOverflow: childExtent > this.constraints.remainingPaintExtent
|| this.constraints.scrollOffset > 0.0
);
this.setChildParentData(this.child, this.constraints, this.geometry);
}
}
}

736
Assets/UIWidgets/rendering/viewpoint.cs


using UIWidgets.painting;
using System;
using System.Collections.Generic;
using UIWidgets.painting;
using UIWidgets.ui;
using UnityEngine;
using Rect = UIWidgets.ui.Rect;

public static class RenderAbstractViewportUtils {
public static RenderAbstractViewport of(RenderObject obj) {
while (obj != null) {
if (obj is RenderAbstractViewport)
if (obj is RenderAbstractViewport) {
}
obj = (RenderObject) obj.parent;
}

RenderAbstractViewport
where ParentDataClass : ParentData, ContainerParentDataMixin<RenderSliver> {
protected RenderViewportBase(
AxisDirection crossAxisDirection,
ViewportOffset offset,
double cacheExtent = RenderAbstractViewportUtils.defaultCacheExtent,
AxisDirection axisDirection = AxisDirection.down
AxisDirection axisDirection = AxisDirection.down,
AxisDirection crossAxisDirection = AxisDirection.right,
ViewportOffset offset = null,
double cacheExtent = RenderAbstractViewportUtils.defaultCacheExtent
Debug.Assert(AxisUtils.axisDirectionToAxis(axisDirection) !=
AxisUtils.axisDirectionToAxis(crossAxisDirection));
this._axisDirection = axisDirection;
this._crossAxisDirection = crossAxisDirection;
this._offset = offset;

public Axis axis {
get { return AxisUtils.axisDirectionToAxis(this.axisDirection); }
}
public ViewportOffset offset {
get { return this._offset; }

base.detach();
}
public override double computeMinIntrinsicWidth(double height) {
return 0.0;
}
public override double computeMaxIntrinsicWidth(double height) {
return 0.0;
}
public override double computeMinIntrinsicHeight(double width) {
return 0.0;
}
public override double computeMaxIntrinsicHeight(double width) {
return 0.0;
}
public override bool isRepaintBoundary {
get { return true; }
}
public double layoutChildSequence(
RenderSliver child,
double scrollOffset,
double overlap,
double layoutOffset,
double remainingPaintExtent,
double mainAxisExtent,
double crossAxisExtent,
GrowthDirection growthDirection,
Func<RenderSliver, RenderSliver> advance,
double remainingCacheExtent,
double cacheOrigin
) {
double initialLayoutOffset = layoutOffset;
ScrollDirection adjustedUserScrollDirection =
GrowthDirectionUtils.applyGrowthDirectionToScrollDirection(
this.offset.userScrollDirection, growthDirection);
double maxPaintOffset = layoutOffset + overlap;
while (child != null) {
double sliverScrollOffset = scrollOffset <= 0.0 ? 0.0 : scrollOffset;
double correctedCacheOrigin = Math.Max(cacheOrigin, -sliverScrollOffset);
double cacheExtentCorrection = cacheOrigin - correctedCacheOrigin;
child.layout(new SliverConstraints(
axisDirection: this.axisDirection,
growthDirection: growthDirection,
userScrollDirection: adjustedUserScrollDirection,
scrollOffset: sliverScrollOffset,
overlap: maxPaintOffset - layoutOffset,
remainingPaintExtent: Math.Max(0.0, remainingPaintExtent - layoutOffset + initialLayoutOffset),
crossAxisExtent: crossAxisExtent,
crossAxisDirection: this.crossAxisDirection,
viewportMainAxisExtent: mainAxisExtent,
remainingCacheExtent: Math.Max(0.0, remainingCacheExtent + cacheExtentCorrection),
cacheOrigin: correctedCacheOrigin
), parentUsesSize: true);
var childLayoutGeometry = child.geometry;
if (childLayoutGeometry.scrollOffsetCorrection != 0.0) {
return childLayoutGeometry.scrollOffsetCorrection;
}
double effectiveLayoutOffset = layoutOffset + childLayoutGeometry.paintOrigin;
if (childLayoutGeometry.visible || scrollOffset > 0) {
this.updateChildLayoutOffset(child, effectiveLayoutOffset, growthDirection);
} else {
this.updateChildLayoutOffset(child, -scrollOffset + initialLayoutOffset, growthDirection);
}
maxPaintOffset = Math.Max(effectiveLayoutOffset + childLayoutGeometry.paintExtent, maxPaintOffset);
scrollOffset -= childLayoutGeometry.scrollExtent;
layoutOffset += childLayoutGeometry.layoutExtent;
if (childLayoutGeometry.cacheExtent != 0.0) {
remainingCacheExtent -= childLayoutGeometry.cacheExtent - cacheExtentCorrection;
cacheOrigin = Math.Min(correctedCacheOrigin + childLayoutGeometry.cacheExtent, 0.0);
}
this.updateOutOfBandData(growthDirection, childLayoutGeometry);
child = advance(child);
}
return 0.0;
}
public override void paint(PaintingContext context, Offset offset) {
if (this.firstChild == null) {
return;
}
if (this.hasVisualOverflow) {
context.pushClipRect(this.needsCompositing, offset, Offset.zero & this.size, this._paintContents);
} else {
this._paintContents(context, offset);
}
}
public void _paintContents(PaintingContext context, Offset offset) {
foreach (RenderSliver child in this.childrenInPaintOrder) {
if (child.geometry.visible) {
context.paintChild(child, offset + this.paintOffsetOf(child));
}
}
}
throw new System.NotImplementedException();
double leadingScrollOffset = 0.0;
double targetMainAxisExtent = 0.0;
RenderObject descendant;
rect = rect ?? target.paintBounds;
Matrix4x4 transform;
if (target is RenderBox) {
RenderBox targetBox = (RenderBox) target;
RenderBox pivot = targetBox;
while (pivot.parent is RenderBox) {
pivot = (RenderBox) pivot.parent;
}
RenderSliver pivotParent = (RenderSliver) pivot.parent;
transform = targetBox.getTransformTo(pivot);
Rect bounds = MatrixUtils.transformRect(transform, rect);
double offset = 0.0;
GrowthDirection growthDirection = pivotParent.constraints.growthDirection;
switch (GrowthDirectionUtils.applyGrowthDirectionToAxisDirection(this.axisDirection, growthDirection)) {
case AxisDirection.up:
switch (growthDirection) {
case GrowthDirection.forward:
offset = bounds.bottom;
break;
case GrowthDirection.reverse:
offset = bounds.top;
break;
}
leadingScrollOffset = pivot.size.height - offset;
targetMainAxisExtent = bounds.height;
break;
case AxisDirection.right:
leadingScrollOffset = bounds.left;
targetMainAxisExtent = bounds.width;
break;
case AxisDirection.down:
leadingScrollOffset = bounds.top;
targetMainAxisExtent = bounds.height;
break;
case AxisDirection.left:
switch (growthDirection) {
case GrowthDirection.forward:
offset = bounds.right;
break;
case GrowthDirection.reverse:
offset = bounds.left;
break;
}
leadingScrollOffset = pivot.size.width - offset;
targetMainAxisExtent = bounds.width;
break;
}
descendant = pivot;
} else if (target is RenderSliver) {
RenderSliver targetSliver = (RenderSliver) target;
leadingScrollOffset = 0.0;
targetMainAxisExtent = targetSliver.geometry.scrollExtent;
descendant = targetSliver;
} else {
return new RevealedOffset(offset: this.offset.pixels, rect: rect);
}
RenderObject child = descendant;
while (child.parent is RenderSliver) {
var parent = (RenderSliver) child.parent;
leadingScrollOffset += parent.childScrollOffset(child);
child = parent;
}
RenderSliver sliver = (RenderSliver) child;
double extentOfPinnedSlivers = this.maxScrollObstructionExtentBefore(sliver);
leadingScrollOffset = this.scrollOffsetOf(sliver, leadingScrollOffset);
switch (sliver.constraints.growthDirection) {
case GrowthDirection.forward:
leadingScrollOffset -= extentOfPinnedSlivers;
break;
case GrowthDirection.reverse:
break;
}
double mainAxisExtent = 0.0;
switch (this.axis) {
case Axis.horizontal:
mainAxisExtent = this.size.width - extentOfPinnedSlivers;
break;
case Axis.vertical:
mainAxisExtent = this.size.height - extentOfPinnedSlivers;
break;
}
double targetOffset = leadingScrollOffset - (mainAxisExtent - targetMainAxisExtent) * alignment;
double offsetDifference = this.offset.pixels - targetOffset;
transform = target.getTransformTo(this);
this.applyPaintTransform(child, ref transform);
Rect targetRect = MatrixUtils.transformRect(transform, rect);
switch (this.axisDirection) {
case AxisDirection.down:
targetRect = targetRect.translate(0.0, offsetDifference);
break;
case AxisDirection.right:
targetRect = targetRect.translate(offsetDifference, 0.0);
break;
case AxisDirection.up:
targetRect = targetRect.translate(0.0, -offsetDifference);
break;
case AxisDirection.left:
targetRect = targetRect.translate(-offsetDifference, 0.0);
break;
}
return new RevealedOffset(offset: targetOffset, rect: targetRect);
public Offset computeAbsolutePaintOffset(RenderSliver child, double layoutOffset,
GrowthDirection growthDirection) {
switch (GrowthDirectionUtils.applyGrowthDirectionToAxisDirection(this.axisDirection, growthDirection)) {
case AxisDirection.up:
return new Offset(0.0, this.size.height - (layoutOffset + child.geometry.paintExtent));
case AxisDirection.right:
return new Offset(layoutOffset, 0.0);
case AxisDirection.down:
return new Offset(0.0, layoutOffset);
case AxisDirection.left:
return new Offset(this.size.width - (layoutOffset + child.geometry.paintExtent), 0.0);
}
return null;
}
public abstract bool hasVisualOverflow { get; }
public abstract void updateOutOfBandData(GrowthDirection growthDirection, SliverGeometry childLayoutGeometry);
public abstract void updateChildLayoutOffset(RenderSliver child, double layoutOffset,
GrowthDirection growthDirection);
public abstract Offset paintOffsetOf(RenderSliver child);
public abstract double scrollOffsetOf(RenderSliver child, double scrollOffsetWithinChild);
public abstract double maxScrollObstructionExtentBefore(RenderSliver child);
public abstract IEnumerable<RenderSliver> childrenInPaintOrder { get; }
public RenderViewport(AxisDirection crossAxisDirection, ViewportOffset offset,
double cacheExtent = RenderAbstractViewportUtils.defaultCacheExtent,
AxisDirection axisDirection = AxisDirection.down) : base(crossAxisDirection, offset, cacheExtent,
axisDirection) {
public RenderViewport(
AxisDirection axisDirection = AxisDirection.down,
AxisDirection crossAxisDirection = AxisDirection.right,
ViewportOffset offset = null,
double anchor = 0.0,
List<RenderSliver> children = null,
RenderSliver center = null,
double cacheExtent = RenderAbstractViewportUtils.defaultCacheExtent
) : base(axisDirection, crossAxisDirection, offset, cacheExtent) {
this.addAll(children);
if (center == null && this.firstChild != null) {
this._center = this.firstChild;
}
}
public override void setupParentData(RenderObject child) {
if (!(child.parentData is SliverPhysicalContainerParentData)) {
child.parentData = new SliverPhysicalContainerParentData();
}
}
public double anchor {
get { return this._anchor; }
set {
if (value != this._anchor) {
return;
}
this._anchor = value;
this.markNeedsLayout();
}
}
public double _anchor;
public RenderSliver center {
get { return this._center; }
set {
if (value == this._center) {
return;
}
this._center = value;
this.markNeedsLayout();
}
}
public RenderSliver _center;
public override bool sizedByParent {
get { return true; }
}
public override void performResize() {
this.size = this.constraints.biggest;
switch (this.axis) {
case Axis.vertical:
this.offset.applyViewportDimension(this.size.height);
break;
case Axis.horizontal:
this.offset.applyViewportDimension(this.size.width);
break;
}
}
public const int _maxLayoutCycles = 10;
public double _minScrollExtent;
public double _maxScrollExtent;
public bool _hasVisualOverflow = false;
public override void performLayout() {
if (this.center == null) {
this._minScrollExtent = 0.0;
this._maxScrollExtent = 0.0;
this._hasVisualOverflow = false;
this.offset.applyContentDimensions(0.0, 0.0);
return;
}
double mainAxisExtent = 0.0;
double crossAxisExtent = 0.0;
switch (this.axis) {
case Axis.vertical:
mainAxisExtent = this.size.height;
crossAxisExtent = this.size.width;
break;
case Axis.horizontal:
mainAxisExtent = this.size.width;
crossAxisExtent = this.size.height;
break;
}
double centerOffsetAdjustment = this.center.centerOffsetAdjustment;
int count = 0;
do {
var correction = this._attemptLayout(mainAxisExtent, crossAxisExtent,
this.offset.pixels + centerOffsetAdjustment);
if (correction != 0.0) {
this.offset.correctBy(correction);
} else {
if (this.offset.applyContentDimensions(
Math.Min(0.0, this._minScrollExtent + mainAxisExtent * this.anchor),
Math.Max(0.0, this._maxScrollExtent - mainAxisExtent * (1.0 - this.anchor))
))
break;
}
count += 1;
} while (count < RenderViewport._maxLayoutCycles);
}
public double _attemptLayout(double mainAxisExtent, double crossAxisExtent, double correctedOffset) {
this._minScrollExtent = 0.0;
this._maxScrollExtent = 0.0;
this._hasVisualOverflow = false;
double centerOffset = mainAxisExtent * this.anchor - correctedOffset;
double reverseDirectionRemainingPaintExtent = centerOffset.clamp(0.0, mainAxisExtent);
double forwardDirectionRemainingPaintExtent = (mainAxisExtent - centerOffset).clamp(0.0, mainAxisExtent);
double fullCacheExtent = mainAxisExtent + 2 * this.cacheExtent;
double centerCacheOffset = centerOffset + this.cacheExtent;
double reverseDirectionRemainingCacheExtent = centerCacheOffset.clamp(0.0, fullCacheExtent);
double forwardDirectionRemainingCacheExtent =
(fullCacheExtent - centerCacheOffset).clamp(0.0, fullCacheExtent);
RenderSliver leadingNegativeChild = this.childBefore(this.center);
if (leadingNegativeChild != null) {
double result = this.layoutChildSequence(
child: leadingNegativeChild,
scrollOffset: Math.Max(mainAxisExtent, centerOffset) - mainAxisExtent,
overlap: 0.0,
layoutOffset: forwardDirectionRemainingPaintExtent,
remainingPaintExtent: reverseDirectionRemainingPaintExtent,
mainAxisExtent: mainAxisExtent,
crossAxisExtent: crossAxisExtent,
growthDirection: GrowthDirection.reverse,
advance: this.childBefore,
remainingCacheExtent: reverseDirectionRemainingCacheExtent,
cacheOrigin: (mainAxisExtent - centerOffset).clamp(-this.cacheExtent, 0.0)
);
if (result != 0.0) {
return -result;
}
}
return this.layoutChildSequence(
child: this.center,
scrollOffset: Math.Max(0.0, -centerOffset),
overlap: leadingNegativeChild == null ? Math.Min(0.0, -centerOffset) : 0.0,
layoutOffset: centerOffset >= mainAxisExtent ? centerOffset : reverseDirectionRemainingPaintExtent,
remainingPaintExtent: forwardDirectionRemainingPaintExtent,
mainAxisExtent: mainAxisExtent,
crossAxisExtent: crossAxisExtent,
growthDirection: GrowthDirection.forward,
advance: this.childAfter,
remainingCacheExtent: forwardDirectionRemainingCacheExtent,
cacheOrigin: centerOffset.clamp(-this.cacheExtent, 0.0)
);
}
public override bool hasVisualOverflow {
get { return this._hasVisualOverflow; }
}
public override void updateOutOfBandData(GrowthDirection growthDirection, SliverGeometry childLayoutGeometry) {
switch (growthDirection) {
case GrowthDirection.forward:
this._maxScrollExtent += childLayoutGeometry.scrollExtent;
break;
case GrowthDirection.reverse:
this._minScrollExtent -= childLayoutGeometry.scrollExtent;
break;
}
if (childLayoutGeometry.hasVisualOverflow) {
this._hasVisualOverflow = true;
}
}
public override void updateChildLayoutOffset(RenderSliver child, double layoutOffset,
GrowthDirection growthDirection) {
var childParentData = (SliverPhysicalParentData) child.parentData;
childParentData.paintOffset = this.computeAbsolutePaintOffset(child, layoutOffset, growthDirection);
}
public override Offset paintOffsetOf(RenderSliver child) {
var childParentData = (SliverPhysicalParentData) child.parentData;
return childParentData.paintOffset;
}
public override double scrollOffsetOf(RenderSliver child, double scrollOffsetWithinChild) {
GrowthDirection growthDirection = child.constraints.growthDirection;
switch (growthDirection) {
case GrowthDirection.forward: {
double scrollOffsetToChild = 0.0;
RenderSliver current = this.center;
while (current != child) {
scrollOffsetToChild += current.geometry.scrollExtent;
current = this.childAfter(current);
}
return scrollOffsetToChild + scrollOffsetWithinChild;
}
case GrowthDirection.reverse: {
double scrollOffsetToChild = 0.0;
RenderSliver current = this.childBefore(this.center);
while (current != child) {
scrollOffsetToChild -= current.geometry.scrollExtent;
current = this.childBefore(current);
}
return scrollOffsetToChild - scrollOffsetWithinChild;
}
}
return 0.0;
}
public override double maxScrollObstructionExtentBefore(RenderSliver child) {
GrowthDirection growthDirection = child.constraints.growthDirection;
switch (growthDirection) {
case GrowthDirection.forward: {
double pinnedExtent = 0.0;
RenderSliver current = this.center;
while (current != child) {
pinnedExtent += current.geometry.maxScrollObstructionExtent;
current = this.childAfter(current);
}
return pinnedExtent;
}
case GrowthDirection.reverse: {
double pinnedExtent = 0.0;
RenderSliver current = this.childBefore(this.center);
while (current != child) {
pinnedExtent += current.geometry.maxScrollObstructionExtent;
current = this.childBefore(current);
}
return pinnedExtent;
}
}
return 0.0;
}
public override void applyPaintTransform(RenderObject child, ref Matrix4x4 transform) {
var childParentData = (SliverPhysicalParentData) child.parentData;
childParentData.applyPaintTransform(ref transform);
}
public override IEnumerable<RenderSliver> childrenInPaintOrder {
get {
if (this.firstChild == null) {
yield break;
}
var child = this.firstChild;
while (child != this.center) {
yield return child;
child = this.childAfter(child);
}
child = this.lastChild;
while (true) {
yield return child;
if (child == this.center) {
yield break;
}
child = this.childBefore(child);
}
}
}
}
public class RenderShrinkWrappingViewport : RenderViewportBase<SliverLogicalContainerParentData> {
public RenderShrinkWrappingViewport(
AxisDirection axisDirection = AxisDirection.down,
AxisDirection crossAxisDirection = AxisDirection.right,
ViewportOffset offset = null,
List<RenderSliver> children = null
) : base(
axisDirection: axisDirection,
crossAxisDirection: crossAxisDirection,
offset: offset) {
this.addAll(children);
}
public override void setupParentData(RenderObject child) {
if (!(child.parentData is SliverLogicalContainerParentData)) {
child.parentData = new SliverLogicalContainerParentData();
}
}
public double _maxScrollExtent = 0.0;
public double _shrinkWrapExtent = 0.0;
public bool _hasVisualOverflow = false;
public override void performLayout() {
if (this.firstChild == null) {
switch (this.axis) {
case Axis.vertical:
this.size = new Size(this.constraints.maxWidth, this.constraints.minHeight);
break;
case Axis.horizontal:
this.size = new Size(this.constraints.minWidth, this.constraints.maxHeight);
break;
}
this.offset.applyViewportDimension(0.0);
this._maxScrollExtent = 0.0;
this._shrinkWrapExtent = 0.0;
this._hasVisualOverflow = false;
this.offset.applyContentDimensions(0.0, 0.0);
return;
}
double mainAxisExtent = 0.0;
double crossAxisExtent = 0.0;
switch (this.axis) {
case Axis.vertical:
mainAxisExtent = this.constraints.maxHeight;
crossAxisExtent = this.constraints.maxWidth;
break;
case Axis.horizontal:
mainAxisExtent = this.constraints.maxWidth;
crossAxisExtent = this.constraints.maxHeight;
break;
}
double effectiveExtent = 0.0;
do {
var correction = this._attemptLayout(mainAxisExtent, crossAxisExtent, this.offset.pixels);
if (correction != 0.0) {
this.offset.correctBy(correction);
} else {
switch (this.axis) {
case Axis.vertical:
effectiveExtent = this.constraints.constrainHeight(this._shrinkWrapExtent);
break;
case Axis.horizontal:
effectiveExtent = this.constraints.constrainWidth(this._shrinkWrapExtent);
break;
}
bool didAcceptViewportDimension = this.offset.applyViewportDimension(effectiveExtent);
bool didAcceptContentDimension =
this.offset.applyContentDimensions(0.0, Math.Max(0.0, this._maxScrollExtent - effectiveExtent));
if (didAcceptViewportDimension && didAcceptContentDimension) {
break;
}
}
} while (true);
switch (this.axis) {
case Axis.vertical:
this.size = this.constraints.constrainDimensions(crossAxisExtent, effectiveExtent);
break;
case Axis.horizontal:
this.size = this.constraints.constrainDimensions(effectiveExtent, crossAxisExtent);
break;
}
}
public double _attemptLayout(double mainAxisExtent, double crossAxisExtent, double correctedOffset) {
this._maxScrollExtent = 0.0;
this._shrinkWrapExtent = 0.0;
this._hasVisualOverflow = false;
return this.layoutChildSequence(
child: this.firstChild,
scrollOffset: Math.Max(0.0, correctedOffset),
overlap: Math.Min(0.0, correctedOffset),
layoutOffset: 0.0,
remainingPaintExtent: mainAxisExtent,
mainAxisExtent: mainAxisExtent,
crossAxisExtent: crossAxisExtent,
growthDirection: GrowthDirection.forward,
advance: this.childAfter,
remainingCacheExtent: mainAxisExtent + 2 * this.cacheExtent,
cacheOrigin: -this.cacheExtent
);
}
public override bool hasVisualOverflow {
get { return this._hasVisualOverflow; }
}
public override void updateOutOfBandData(GrowthDirection growthDirection, SliverGeometry childLayoutGeometry) {
this._maxScrollExtent += childLayoutGeometry.scrollExtent;
if (childLayoutGeometry.hasVisualOverflow) {
this._hasVisualOverflow = true;
}
this._shrinkWrapExtent += childLayoutGeometry.maxPaintExtent;
}
public override void updateChildLayoutOffset(RenderSliver child, double layoutOffset,
GrowthDirection growthDirection) {
var childParentData = (SliverLogicalParentData) child.parentData;
childParentData.layoutOffset = layoutOffset;
}
public override Offset paintOffsetOf(RenderSliver child) {
var childParentData = (SliverLogicalParentData) child.parentData;
return this.computeAbsolutePaintOffset(child, childParentData.layoutOffset, GrowthDirection.forward);
}
public override double scrollOffsetOf(RenderSliver child, double scrollOffsetWithinChild) {
double scrollOffsetToChild = 0.0;
RenderSliver current = this.firstChild;
while (current != child) {
scrollOffsetToChild += current.geometry.scrollExtent;
current = this.childAfter(current);
}
return scrollOffsetToChild + scrollOffsetWithinChild;
}
public override double maxScrollObstructionExtentBefore(RenderSliver child) {
double pinnedExtent = 0.0;
RenderSliver current = this.firstChild;
while (current != child) {
pinnedExtent += current.geometry.maxScrollObstructionExtent;
current = this.childAfter(current);
}
return pinnedExtent;
}
public override void applyPaintTransform(RenderObject child, ref Matrix4x4 transform) {
Offset offset = this.paintOffsetOf((RenderSliver) child);
transform = Matrix4x4.Translate(offset.toVector()) * transform;
}
public override IEnumerable<RenderSliver> childrenInPaintOrder {
get {
RenderSliver child = this.firstChild;
while (child != null) {
yield return child;
child = this.childAfter(child);
}
}
}
}
}

61
Assets/UIWidgets/rendering/viewport_offset.cs


using UIWidgets.foundation;
using System;
using UIWidgets.foundation;
namespace UIWidgets.rendering {
public enum ScrollDirection {

}
public static class ScrollDirectionUtils {
public static ScrollDirection flipScrollDirection(ScrollDirection direction) {
switch (direction) {
case ScrollDirection.idle:
return ScrollDirection.idle;
case ScrollDirection.forward:
return ScrollDirection.reverse;
case ScrollDirection.reverse:
return ScrollDirection.forward;
}
throw new Exception("unknown direction");
}
}
return null;
return new _FixedViewportOffset(value);
return null;
return _FixedViewportOffset.zero();
}
public abstract double pixels { get; }

public abstract void correctBy(double correction);
public abstract void jumpTo(double pixels);
public abstract ScrollDirection userScrollDirection { get; }
}
public class _FixedViewportOffset : ViewportOffset {
public _FixedViewportOffset(double _pixels) {
this._pixels = _pixels;
}
public new static _FixedViewportOffset zero() {
return new _FixedViewportOffset(0.0);
}
public double _pixels;
public override double pixels {
get { return this._pixels; }
}
public override bool applyViewportDimension(double viewportDimension) {
return true;
}
public override bool applyContentDimensions(double minScrollExtent, double maxScrollExtent) {
return true;
}
public override void correctBy(double correction) {
this._pixels += correction;
}
public override void jumpTo(double pixels) {
}
public override ScrollDirection userScrollDirection {
get { return ScrollDirection.idle; }
}
}
}

35
Assets/UIWidgets/ui/geometry.cs


using System;
namespace UIWidgets.ui {
public static class MathUtils {
public static double clamp(this double value, double min, double max) {
if (value < min) {
value = min;
} else if (value > max) {
value = max;
}
return value;
}
public static int clamp(this int value, int min, int max) {
if (value < min) {
value = min;
} else if (value > max) {
value = max;
}
return value;
}
}
public abstract class OffsetBase : IEquatable<OffsetBase> {
protected OffsetBase(double _dx, double _dy) {
this._dx = _dx;

public static Offset operator +(Offset a, Offset b) {
return new Offset(a.dx + b.dx, a.dy + b.dy);
}
public static Offset operator *(Offset a, double operand) {
return new Offset(a.dx * operand, a.dy * operand);
}
public static Offset operator /(Offset a, double operand) {
return new Offset(a.dx / operand, a.dy / operand);
}
public static Rect operator &(Offset a, Size other) {

public Rect shift(Offset offset) {
return Rect.fromLTRB(this.left + offset.dx, this.top + offset.dy, this.right + offset.dx,
this.bottom + offset.dy);
}
public Rect translate(double translateX, double translateY) {
return Rect.fromLTRB(this.left + translateX, this.top + translateY, this.right + translateX,
this.bottom + translateY);
}
public Rect inflate(double delta) {

10
Assets/UIWidgets/ui/painting/canvas.cs


void clipRect(Rect rect);
void clipRRect(RRect rrect);
void drawMesh(Mesh mesh, Material material);
}
public class RecorderCanvas : Canvas {

public void clipRRect(RRect rrect) {
this._recorder.addDrawCmd(new DrawClipRRect {
rrect = rrect,
});
}
public void drawMesh(Mesh mesh, Material material)
{
this._recorder.addDrawCmd(new DrawMesh() {
mesh = mesh,
material = material,
});
}
}

15
Assets/UIWidgets/ui/painting/canvas_impl.cs


GL.End();
}
}
public void drawRect(Rect rect, BorderWidth borderWidth, BorderRadius borderRadius, Paint paint) {
this.prepareGL(CanvasImpl.guiRoundedRectMat);

new UnityEngine.Rect(0.0f, 0.0f, 1f, 1f), 0, 0, 0, 0,
paint.color.toColor(), CanvasImpl.guiRoundedRectMat);
}
public void drawRectShadow(Rect rect, Paint paint) {
this.prepareGL(CanvasImpl.shadowRectMat);

else if (drawCmd is DrawClipRRect) {
var drawClipRRect = (DrawClipRRect) drawCmd;
this.clipRRect(drawClipRRect.rrect);
}
else {
} else if (drawCmd is DrawMesh) {
var drawMesh = (DrawMesh) drawCmd;
this.drawMesh(drawMesh.mesh, drawMesh.material);
} else {
throw new Exception("unknown drawCmd: " + drawCmd);
}
}

}
this.pushClipRRect(rect, this._transform);
}
public void drawMesh(Mesh mesh, Material material)
{
prepareGL(material);
material.SetPass(0);
Graphics.DrawMeshNow(mesh, Matrix4x4.identity);
}
private void pushClipRect(Rect clipRect, Matrix4x4 transform) {

8
Assets/UIWidgets/ui/painting/draw_cmd.cs


public class DrawClipRRect : DrawCmd {
public RRect rrect;
}
}
public class DrawMesh : DrawCmd {
public Mesh mesh;
public Material material;
}
}

8
Assets/UIWidgets/ui/painting/picture.cs


} else if (drawCmd is DrawClipRRect) {
var drawClipRRect = (DrawClipRRect) drawCmd;
this.addClipRect(drawClipRRect.rrect.outerRect);
} else {
} else if (drawCmd is DrawMesh) {
var bounds = ((DrawMesh)drawCmd).mesh.bounds;
var rect = Rect.fromLTRB(bounds.min.x, bounds.min.y, bounds.max.x, bounds.max.y);
this.addPaintBounds(rect);
} else
{
throw new Exception("unknown drawCmd: " + drawCmd);
}
}

401
Assets/UIWidgets/ui/text.cs


namespace UIWidgets.ui {
using System;
using System.Collections.Generic;
using JetBrains.Annotations;
using UnityEngine;
namespace UIWidgets.ui {
public enum FontStyle {
/// Use the upright glyphs
normal,
/// Use glyphs designed for slanting
italic,
}
public enum TextAlign {
/// Align the text on the left edge of the container.
left,
/// Align the text on the right edge of the container.
right,
/// Align the text in the center of the container.
center,
/// Stretch lines of text that end with a soft line break to fill the width of
/// the container.
///
/// Lines that end with hard line breaks are aligned towards the [start] edge.
justify,
}
public class ParagraphConstraints: IEquatable<ParagraphConstraints>
{
public readonly double width;
public ParagraphConstraints(double width)
{
this.width = width;
}
public bool Equals(ParagraphConstraints other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return width.Equals(other.width);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((ParagraphConstraints) obj);
}
public override int GetHashCode()
{
return width.GetHashCode();
}
public override string ToString()
{
return string.Format("Width: {0}", width);
}
}
public class TextStyle:IEquatable<TextStyle>
{
public static readonly string defaultFontFamily = "Helvetica";
public static readonly double defaultFontSize = 14.0;
public static readonly FontWeight defaultFontWeight = FontWeight.w400;
public static readonly FontStyle defaultFontStyle = FontStyle.normal;
public static readonly Color defaultColor = Color.fromARGB(255, 0, 0, 0);
public Color color;
public double? fontSize;
public FontWeight? fontWeight;
public FontStyle? fontStyle;
public double? letterSpacing;
public double? wordSpacing;
public TextBaseline? textBaseline;
public double? height;
public TextDecoration decoration;
public string fontFamily;
public FontStyle safeFontStyle
{
get { return fontStyle ?? defaultFontStyle; }
}
public string safeFontFamily
{
get { return fontFamily ?? defaultFontFamily; }
}
public double safeFontSize
{
get { return fontSize ?? defaultFontSize; }
}
public FontWeight safeFontWeight
{
get { return fontWeight ?? defaultFontWeight; }
}
public UnityEngine.Color UnityColor
{
get { return (color ?? defaultColor).toColor(); }
}
public UnityEngine.FontStyle UnityFontStyle
{
get
{
if (safeFontStyle == FontStyle.italic)
{
if (safeFontWeight == FontWeight.w700)
{
return UnityEngine.FontStyle.BoldAndItalic;
}
else
{
return UnityEngine.FontStyle.Italic;
}
} else if (safeFontWeight == FontWeight.w700)
{
return UnityEngine.FontStyle.Bold;
}
return UnityEngine.FontStyle.Normal;
}
}
public int UnityFontSize
{
get { return (int) safeFontSize; }
}
public TextStyle merge(TextStyle style)
{
var ret = new TextStyle();
ret.color = style.color??color;
ret.fontSize = style.fontSize??fontSize;
ret.fontWeight = style.fontWeight??fontWeight;
ret.fontStyle = style.fontStyle??fontStyle;
ret.letterSpacing = style.letterSpacing??letterSpacing;
ret.textBaseline = style.textBaseline??textBaseline;
ret.height = style.height??height;
ret.decoration = style.decoration??decoration;
ret.fontFamily = style.fontFamily??fontFamily;
return ret;
}
public bool Equals(TextStyle other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return color == other.color && fontSize == other.fontSize && fontWeight == other.fontWeight &&
fontStyle == other.fontStyle && letterSpacing == other.letterSpacing &&
wordSpacing == other.wordSpacing && textBaseline == other.textBaseline &&
height == other.height && decoration == other.decoration && fontFamily == other.fontFamily;
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((TextStyle) obj);
}
public override int GetHashCode()
{
unchecked
{
var hashCode = (color != null ? color.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ fontSize.GetHashCode();
hashCode = (hashCode * 397) ^ fontWeight.GetHashCode();
hashCode = (hashCode * 397) ^ fontStyle.GetHashCode();
hashCode = (hashCode * 397) ^ letterSpacing.GetHashCode();
hashCode = (hashCode * 397) ^ wordSpacing.GetHashCode();
hashCode = (hashCode * 397) ^ textBaseline.GetHashCode();
hashCode = (hashCode * 397) ^ height.GetHashCode();
hashCode = (hashCode * 397) ^ (decoration != null ? decoration.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (fontFamily != null ? fontFamily.GetHashCode() : 0);
return hashCode;
}
}
public static bool operator ==(TextStyle left, TextStyle right)
{
return Equals(left, right);
}
public static bool operator !=(TextStyle left, TextStyle right)
{
return !Equals(left, right);
}
public TextStyle(Color color = null, double? fontSize = default(double?), FontWeight? fontWeight = default(FontWeight?), FontStyle? fontStyle = default(FontStyle?), double? letterSpacing = default(double?), double? wordSpacing = default(double?), TextBaseline? textBaseline = default(TextBaseline?), double? height = default(double?), TextDecoration decoration = null, string fontFamily = null)
{
this.color = color;
this.fontSize = fontSize;
this.fontWeight = fontWeight;
this.fontStyle = fontStyle;
this.letterSpacing = letterSpacing;
this.wordSpacing = wordSpacing;
this.textBaseline = textBaseline;
this.height = height;
this.decoration = decoration;
this.fontFamily = fontFamily;
}
}
public class ParagraphStyle: IEquatable<ParagraphStyle>
{
public ParagraphStyle(TextAlign? textAlign = null,
TextDirection? textDirection = null,
FontWeight? fontWeight = null,
FontStyle? fontStyle = null,
int? maxLines = null,
double? fontSize = null,
string fontFamily = null,
double? lineHeight = null, // todo
string ellipsis = null)
{
this.textAlign = textAlign;
this.textDirection = textDirection;
this.fontWeight = fontWeight;
this.fontStyle = fontStyle;
this.maxLines = maxLines;
this.fontSize = fontSize;
this.fontFamily = fontFamily;
this.lineHeight = lineHeight;
this.ellipsis = ellipsis;
}
public bool Equals(ParagraphStyle other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return textAlign == other.textAlign && textDirection == other.textDirection && fontWeight == other.fontWeight && fontStyle == other.fontStyle && maxLines == other.maxLines && fontSize.Equals(other.fontSize) && string.Equals(fontFamily, other.fontFamily) && lineHeight.Equals(other.lineHeight) && string.Equals(ellipsis, other.ellipsis);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((ParagraphStyle) obj);
}
public static bool operator ==(ParagraphStyle a, ParagraphStyle b) {
return Equals(a, b);
}
public static bool operator !=(ParagraphStyle a, ParagraphStyle b) {
return !(a == b);
}
public override int GetHashCode()
{
unchecked
{
var hashCode = textAlign.GetHashCode();
hashCode = (hashCode * 397) ^ textDirection.GetHashCode();
hashCode = (hashCode * 397) ^ fontWeight.GetHashCode();
hashCode = (hashCode * 397) ^ fontStyle.GetHashCode();
hashCode = (hashCode * 397) ^ maxLines.GetHashCode();
hashCode = (hashCode * 397) ^ fontSize.GetHashCode();
hashCode = (hashCode * 397) ^ (fontFamily != null ? fontFamily.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ lineHeight.GetHashCode();
hashCode = (hashCode * 397) ^ (ellipsis != null ? ellipsis.GetHashCode() : 0);
return hashCode;
}
}
public TextStyle getTextStyle()
{
return new TextStyle(
fontWeight: fontWeight,
fontStyle: fontStyle,
fontFamily: fontFamily,
fontSize: fontSize,
height: lineHeight
);
}
public readonly TextAlign? textAlign;
public readonly TextDirection? textDirection;
public readonly FontWeight? fontWeight;
public readonly FontStyle? fontStyle;
public readonly int? maxLines;
public readonly double? fontSize;
public readonly string fontFamily;
public readonly double? lineHeight;
public readonly string ellipsis;
}
public class TextDecoration: IEquatable<TextDecoration>
{
public bool Equals(TextDecoration other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return mask == other.mask;
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((TextDecoration) obj);
}
public override int GetHashCode()
{
return mask;
}
public static bool operator ==(TextDecoration a, TextDecoration b) {
return Equals(a, b);
}
public static bool operator !=(TextDecoration a, TextDecoration b) {
return !(a == b);
}
public static readonly TextDecoration none = new TextDecoration(0);
public static readonly TextDecoration underline = new TextDecoration(1);
public static readonly TextDecoration overline = new TextDecoration(2);
public static readonly TextDecoration lineThrough = new TextDecoration(4);
public readonly int mask;
public TextDecoration(int mask)
{
this.mask = mask;
}
bool contains(TextDecoration other) {
return (mask | other.mask) == mask;
}
}
}
public enum TextAffinity {
upstream,
downstream,
}
public enum FontWeight
{
w400, // normal
w700, // bold
}
public class TextPosition
{
public readonly int offset;
public readonly TextAffinity affinity;
public TextPosition(int offset, TextAffinity affinity = TextAffinity.downstream)
{
this.offset = offset;
this.affinity = affinity;
}
public override string ToString()
{
return string.Format("Offset: {0}, Affinity: {1}", offset, affinity);
}
protected bool Equals(TextPosition other)
{
return offset == other.offset && affinity == other.affinity;
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((TextPosition) obj);
}
public override int GetHashCode()
{
unchecked
{
return (offset * 397) ^ (int) affinity;
}
}
}
}

70
Assets/UIWidgets/Resources/UIWidgets_Text.shader


Shader "UIWidgets/Text Shader" {
Properties {
_MainTex ("Font Texture", 2D) = "white" {}
_Color ("Text Color", Color) = (1,1,1,1)
}
SubShader {
Tags {
"Queue"="Transparent"
"IgnoreProjector"="True"
"RenderType"="Transparent"
"PreviewType"="Plane"
}
Lighting Off Cull Off ZTest Always ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile _ UNITY_SINGLE_PASS_STEREO STEREO_INSTANCING_ON STEREO_MULTIVIEW_ON
#include "UnityCG.cginc"
struct appdata_t {
float4 vertex : POSITION;
fixed4 color : COLOR;
float2 texcoord : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f {
float4 vertex : SV_POSITION;
fixed4 color : COLOR;
float2 texcoord : TEXCOORD0;
float2 clipUV : TEXCOORD1;
UNITY_VERTEX_OUTPUT_STEREO
};
sampler2D _MainTex;
uniform float4 _MainTex_ST;
uniform fixed4 _Color;
#include "UIWidgets_CG.cginc"
v2f vert (appdata_t v)
{
v2f o;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
o.vertex = UnityObjectToClipPos(v.vertex);
float3 eyePos = UnityObjectToViewPos(v.vertex);
o.color = v.color * _Color;
o.texcoord = TRANSFORM_TEX(v.texcoord,_MainTex);
o.clipUV = mul(UIWidgets_GUIClipMatrix, float4(eyePos.xy, 0, 1.0));
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = i.color;
col.a *= tex2D(_MainTex, i.texcoord).a;
float pixelScale = 1.0f / abs(ddx(i.clipUV.x));
col.a *= getClipAlpha(i.clipUV, pixelScale);
return col;
}
ENDCG
}
}
}

3
Assets/UIWidgets/Resources/UIWidgets_Text.shader.meta


fileFormatVersion: 2
guid: 3d9aebae673b434491eb311fc9d0df0f
timeCreated: 1536033642

152
Assets/UIWidgets/Tests/Paragraph.cs


using System;
using System.Collections.Generic;
using System.Linq;
using UIWidgets.editor;
using UIWidgets.painting;
using UIWidgets.rendering;
using UIWidgets.ui;
using UnityEditor;
using UnityEngine;
using Color = UIWidgets.ui.Color;
using FontStyle = UIWidgets.ui.FontStyle;
using Rect = UIWidgets.ui.Rect;
namespace UIWidgets.Tests
{
public class Paragraph : EditorWindow
{
private readonly Func<RenderBox>[] _options;
private readonly string[] _optionStrings;
private int _selected;
Paragraph() {
this._options = new Func<RenderBox>[] {
this.text,
this.textHeight,
this.textOverflow
};
this._optionStrings = this._options.Select(x => x.Method.Name).ToArray();
this._selected = 0;
this.titleContent = new GUIContent("RenderBoxes");
}
private WindowAdapter windowAdapter;
private RendererBindings rendererBindings;
[NonSerialized] private bool hasInvoked = false;
void OnGUI() {
var selected = EditorGUILayout.Popup("test case", this._selected, this._optionStrings);
if (selected != this._selected || !this.hasInvoked) {
this._selected = selected;
this.hasInvoked = true;
var renderBox = this._options[this._selected]();
this.rendererBindings.setRoot(renderBox);
}
if (this.windowAdapter != null) {
this.windowAdapter.OnGUI();
}
}
void Update() {
if (this.windowAdapter != null) {
this.windowAdapter.Update();
}
}
private void OnEnable() {
this.windowAdapter = new WindowAdapter(this);
this.rendererBindings = new RendererBindings(this.windowAdapter);
}
void OnDestroy() {
this.windowAdapter = null;
this.rendererBindings = null;
}
RenderBox none() {
return null;
}
private RenderBox box(RenderParagraph p, int width = 300, int height = 300)
{
return new RenderConstrainedOverflowBox(
minWidth: width,
maxWidth: width,
minHeight: height,
maxHeight: height,
alignment: Alignment.center,
child: new RenderDecoratedBox(
decoration: new BoxDecoration(
color: new Color(0xFFFFFFFF),
borderRadius: BorderRadius.all(3),
border: Border.all(Color.fromARGB(255, 255, 0, 0), 1)
),
child: new RenderPadding(EdgeInsets.all(10), p
)
)
);
}
RenderBox text()
{
return box(
new RenderParagraph(new TextSpan("", children:
new List<TextSpan>()
{
new TextSpan("Real-time 3D revolutioni淡粉色的方式地方zes the animation pipeline ", null),
new TextSpan(style: new painting.TextStyle(color: Color.fromARGB(255, 255, 0, 0)),
text: "for Disney Television Animation's “Baymax Dreams"),
new TextSpan(" Unity Widgets"),
new TextSpan(" Text"),
new TextSpan("Real-time 3D revolutionizes the animation pipeline "),
new TextSpan(style: new painting.TextStyle(color: Color.fromARGB(125, 255, 0, 0)),
text: "Transparent Red Text\n\n"),
new TextSpan(style: new painting.TextStyle(fontWeight: FontWeight.w700),
text: "Bold Text Test Bold Textfs Test: FontWeight.w70\n\n"),
new TextSpan(style: new painting.TextStyle(fontStyle: FontStyle.italic),
text: "This is FontStyle.italic Text This is FontStyle.italic Text\n\n"),
new TextSpan(style: new painting.TextStyle(fontStyle: FontStyle.italic, fontWeight: FontWeight.w700),
text: "This is FontStyle.italic And 发撒放豆腐sad 发生的 Bold Text This is FontStyle.italic And Bold Text\n\n"),
new TextSpan(style: new painting.TextStyle(fontSize: 18),
text: "FontSize 18: Get a named matrix value from the shader."),
new TextSpan(style: new painting.TextStyle(fontSize: 14),
text: "FontSize 14"),
})));
}
RenderBox textOverflow()
{
return box(
new RenderParagraph(new TextSpan("", children:
new List<TextSpan>()
{
new TextSpan("Real-time 3D revolutionizes:\n the animation pipeline.\n\n\revolutionizesn\n\nReal-time 3D revolutionizes the animation pipeline ", null),
})), 200, 80);
}
RenderBox textHeight()
{
var text =
"Hello UIWidgets. Real-time 3D revolutionize \nReal-time 3D revolutionize\nReal-time 3D revolutionize\n\n";
return box(
new RenderParagraph(new TextSpan(text: "", children:
new List<TextSpan>()
{
new TextSpan(style: new painting.TextStyle(height: 1),
text: "Height 1.0 Text:" + text),
new TextSpan(style: new painting.TextStyle(height: 1.2),
text: "Height 1.2 Text:" + text),
new TextSpan(style: new painting.TextStyle(height: 1.5),
text: "Height 1.5 Text:" + text),
})));
}
}
}

3
Assets/UIWidgets/Tests/Paragraph.cs.meta


fileFormatVersion: 2
guid: f4121086094d45de9e29781269270102
timeCreated: 1535424100

3
Assets/UIWidgets/math.meta


fileFormatVersion: 2
guid: c53bae489a2f499ea5b9000edb31b0bb
timeCreated: 1535421229

288
Assets/UIWidgets/painting/text_painter.cs


using System;
using System.Runtime.ConstrainedExecution;
using UIWidgets.math;
using UIWidgets.ui;
using UnityEngine;
using Canvas = UIWidgets.ui.Canvas;
namespace UIWidgets.painting
{
public class TextPainter
{
private TextSpan _text;
private TextAlign _textAlign;
private TextDirection? _textDirection;
private double _textScaleFactor;
private Paragraph _layoutTemplate;
private Paragraph _paragraph;
private bool _needsLayout = true;
private int _maxLines;
private string _ellipsis;
private double _lastMinWidth;
private double _lastMaxWidth;
public TextPainter(TextSpan text,
TextAlign textAlign = TextAlign.left,
TextDirection textDirection = TextDirection.ltr,
double textScaleFactor = 1.0,
int maxLines = 0,
string ellipsis = "")
{
_text = text;
_textAlign = textAlign;
_textDirection = textDirection;
_textScaleFactor = textScaleFactor;
_maxLines = maxLines;
_ellipsis = ellipsis;
}
public double textScaleFactor
{
get { return _textScaleFactor; }
set
{
if (_textScaleFactor == value)
return;
_textScaleFactor = value;
_paragraph = null;
_layoutTemplate = null;
_needsLayout = true;
}
}
public string ellipsis
{
get { return _ellipsis; }
set
{
if (_ellipsis == value)
{
return;
}
_ellipsis = value;
_paragraph = null;
_needsLayout = true;
}
}
public TextSpan text
{
get { return _text; }
set
{
if (text.Equals(value))
{
return;
}
if (!Equals(_text == null ? null : _text.style, value == null ? null : value.style))
{
_layoutTemplate = null;
}
_text = value;
_paragraph = null;
_needsLayout = true;
}
}
public Size size
{
get
{
Debug.Assert(!_needsLayout);
return new Size(width, height);
}
}
public TextDirection? textDirection
{
get { return _textDirection; }
set
{
if (textDirection == value)
{
return;
}
_textDirection = value;
_paragraph = null;
_layoutTemplate = null;
_needsLayout = true;
}
}
public TextAlign textAlign
{
get { return _textAlign; }
set
{
if (_textAlign == value)
{
return;
}
_textAlign = value;
_paragraph = null;
_needsLayout = true;
}
}
public bool didExceedMaxLines
{
get
{
Debug.Assert(!_needsLayout);
return _paragraph.didExceedMaxLines;
}
}
public int maxLines
{
get { return _maxLines; }
set
{
if (_maxLines == value)
{
return;
}
_maxLines = value;
_paragraph = null;
_needsLayout = true;
}
}
public double minIntrinsicWidth
{
get
{
Debug.Assert(!_needsLayout);
return _applyFloatingPointHack(_paragraph.minIntrinsicWidth);
}
}
public double maxIntrinsicWidth
{
get
{
Debug.Assert(!_needsLayout);
return _applyFloatingPointHack(_paragraph.maxIntrinsicWidth);
}
}
public double height
{
get
{
Debug.Assert(!_needsLayout);
return _applyFloatingPointHack(_paragraph.height);
}
}
public double width
{
get
{
Debug.Assert(!_needsLayout);
return _applyFloatingPointHack(_paragraph.width);
}
}
public double computeDistanceToActualBaseline(TextBaseline baseline)
{
Debug.Assert(!_needsLayout);
switch (baseline)
{
case TextBaseline.alphabetic:
return _paragraph.alphabeticBaseline;
case TextBaseline.ideographic:
return _paragraph.ideographicBaseline;
}
return 0.0;
}
public void layout(double minWidth = 0.0, double maxWidth = double.PositiveInfinity)
{
Debug.Assert(text != null, "TextPainter.text must be set to a non-null value before using the TextPainter.");
Debug.Assert(textDirection != null, "TextPainter.textDirection must be set to a non-null value before using the TextPainter.");
if (_needsLayout && minWidth == _lastMaxWidth && maxWidth == _lastMaxWidth)
{
return;
}
_needsLayout = false;
if (_paragraph == null)
{
var builder = new ParagraphBuilder(_createParagraphStyle());
_text.build(builder, textScaleFactor);
_paragraph = builder.build();
}
_lastMinWidth = minWidth;
_lastMaxWidth = minWidth;
_paragraph.layout(new ParagraphConstraints(maxWidth));
if (minWidth != maxWidth)
{
var newWidth = MathUtil.Clamp(maxIntrinsicWidth, minWidth, maxWidth);
if (newWidth != width)
{
_paragraph.layout(new ParagraphConstraints(newWidth));
}
}
}
public void paint(Canvas canvas, Offset offset)
{
Debug.Assert(!_needsLayout);
_paragraph.paint(canvas, offset.dx, offset.dy);
}
private ParagraphStyle _createParagraphStyle(TextDirection defaultTextDirection = TextDirection.ltr)
{
if (_text.style == null)
{
return new ParagraphStyle(
textAlign: textAlign,
textDirection: textDirection ?? defaultTextDirection,
maxLines: maxLines,
ellipsis: ellipsis
);
}
return _text.style.getParagraphStyle(textAlign, textDirection ?? defaultTextDirection,
ellipsis, maxLines, textScaleFactor);
}
public double preferredLineHeight
{
get
{
if (_layoutTemplate == null)
{
var builder = new ParagraphBuilder(
_createParagraphStyle(TextDirection.ltr)
); // direction doesn't matter, text is just a space
if (text != null && text.style != null)
{
builder.pushStyle(text.style.getTextStyle(textScaleFactor));
}
builder.addText(" ");
_layoutTemplate = builder.build();
_layoutTemplate.layout(new ParagraphConstraints(double.PositiveInfinity));
}
return _layoutTemplate.height;
}
}
private double _applyFloatingPointHack(double layoutValue)
{
return Math.Ceiling(layoutValue);
}
}
}

3
Assets/UIWidgets/painting/text_painter.cs.meta


fileFormatVersion: 2
guid: 23fd2d1247bf4e308d9f88f3488da38f
timeCreated: 1535348672

246
Assets/UIWidgets/painting/text_span.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UIWidgets.ui;
using UnityEditor;
using UnityEngine.Assertions;
namespace UIWidgets.painting
{
public class GestureMock
{
}
public class TextSpan: IEquatable<TextSpan>
{
public delegate bool Visitor(TextSpan span);
public readonly TextStyle style;
public readonly string text;
public readonly List<TextSpan> children;
public readonly GestureMock recognizer;
public TextSpan(string text = "", TextStyle style = null, List<TextSpan> children = null)
{
this.text = text;
this.style = style;
this.children = children;
}
public void build(ParagraphBuilder builder, double textScaleFactor = 1.0)
{
var hasTyle = style != null;
if (hasTyle)
{
builder.pushStyle(style.getTextStyle(textScaleFactor));
}
if (!string.IsNullOrEmpty(text))
{
builder.addText(text);
}
if (children != null)
{
foreach (var child in children)
{
Assert.IsNotNull(child);
child.build(builder, textScaleFactor);
}
}
if (hasTyle)
{
builder.pop();
}
}
bool visitTextSpan(Visitor visitor)
{
if (!string.IsNullOrEmpty(text))
{
if (!visitor.Invoke(this))
{
return false;
}
}
if (children != null)
{
foreach (var child in children)
{
if (!child.visitTextSpan(visitor))
{
return false;
}
}
}
return true;
}
TextSpan getSpanForPosition(TextPosition position)
{
var offset = 0;
var targetOffset = position.offset;
var affinity = position.affinity;
TextSpan result = null;
visitTextSpan((span) =>
{
var endOffset = offset + span.text.Length;
if ((targetOffset == offset && affinity == TextAffinity.downstream) ||
(targetOffset > offset && targetOffset < endOffset) ||
(targetOffset == endOffset && affinity == TextAffinity.upstream))
{
result = span;
return false;
}
offset = endOffset;
return true;
});
return result;
}
string toPlainText()
{
var sb = new StringBuilder();
visitTextSpan((span) =>
{
sb.Append(span.text);
return true;
});
return sb.ToString();
}
public int codeUnitAt(int index)
{
if (index < 0)
{
return -1;
}
var offset = 0;
var result = -1;
visitTextSpan(span =>
{
if (index - offset < span.text.Length)
{
result = span.text[index - offset];
return false;
}
offset += span.text.Length;
return true;
});
return result;
}
public RenderComparison compareTo(TextSpan other)
{
if (Equals(other))
{
return RenderComparison.identical;
}
if (other.text != text
|| ((children == null) != (other.children == null))
|| (children != null && other.children != null && children.Count != other.children.Count)
|| ((style == null) != (other.style != null))
)
{
return RenderComparison.layout;
}
RenderComparison result = Equals(recognizer, other.recognizer)
? RenderComparison.identical
: RenderComparison.metadata;
if (style != null)
{
var candidate = style.compareTo(other.style);
if (candidate > result)
{
result = candidate;
}
if (result == RenderComparison.layout)
{
return result;
}
}
if (children != null)
{
for (var index = 0; index < children.Count; index++)
{
var candidate = children[index].compareTo(other.children[index]);
if (candidate > result)
{
result = candidate;
}
if (result == RenderComparison.layout)
{
return result;
}
}
}
return result;
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((TextSpan) obj);
}
public override int GetHashCode()
{
unchecked
{
var hashCode = (style != null ? style.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (text != null ? text.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (childHash());
return hashCode;
}
}
public bool Equals(TextSpan other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return Equals(style, other.style) && string.Equals(text, other.text) && childEquals(children, other.children);
}
private int childHash()
{
unchecked
{
var hashCode = 0;
if (children != null)
{
foreach (var child in children)
{
hashCode = (hashCode * 397) ^ (child != null ? child.GetHashCode() : 0);
}
}
return hashCode;
}
}
private static bool childEquals(List<TextSpan> left, List<TextSpan> right)
{
if (ReferenceEquals(left, right))
{
return true;
}
if (left == null || right == null)
{
return false;
}
return left.SequenceEqual(right);
}
}
}

3
Assets/UIWidgets/painting/text_span.cs.meta


fileFormatVersion: 2
guid: 08861f205e19466880d9af4e7cc1dde4
timeCreated: 1535348576

86
Assets/UIWidgets/painting/text_style.cs


using System;
using UIWidgets.painting;
using UIWidgets.ui;
namespace UIWidgets.painting
{
public class TextStyle
{
public static readonly double _defaultFontSize = 14.0;
public readonly bool? inherit;
public readonly Color color;
public readonly double? fontSize;
public readonly FontWeight? fontWeight;
public readonly FontStyle? fontStyle;
public readonly double? letterSpacing;
public readonly double? wordSpacing;
public readonly TextBaseline? textBaseline;
public readonly double? height;
public readonly TextDecoration decoration;
public readonly string fontFamily;
public TextStyle(bool? inherit = null, Color color = null, double? fontSize = null, FontWeight? fontWeight = null,
FontStyle? fontStyle = null, double? letterSpacing = null, double? wordSpacing = null,
TextBaseline? textBaseline = null, double? height = null, TextDecoration decoration = null, string fontFamily = null)
{
this.inherit = inherit;
this.color = color;
this.fontSize = fontSize;
this.fontWeight = fontWeight;
this.fontStyle = fontStyle;
this.letterSpacing = letterSpacing;
this.wordSpacing = wordSpacing;
this.textBaseline = textBaseline;
this.height = height;
this.decoration = decoration;
this.fontFamily = fontFamily;
}
public ui.TextStyle getTextStyle(double textScaleFactor = 1.0)
{
return new ui.TextStyle(
color: color,
decoration: decoration,
fontWeight: fontWeight,
fontStyle: fontStyle,
fontSize: fontSize == null ? null : fontSize * textScaleFactor,
letterSpacing: letterSpacing,
wordSpacing: wordSpacing,
textBaseline: textBaseline,
height: height,
fontFamily: fontFamily
);
}
public RenderComparison compareTo(TextStyle other)
{
if (inherit != other.inherit || fontFamily != other.fontFamily
|| fontSize != other.fontSize || fontWeight != other.fontWeight
|| fontStyle != other.fontStyle || letterSpacing != other.letterSpacing
|| wordSpacing != other.wordSpacing || textBaseline != other.textBaseline
|| height != other.height)
{
return RenderComparison.layout;
}
if (color != other.color || decoration != other.decoration)
{
return RenderComparison.paint;
}
return RenderComparison.identical;
}
public ParagraphStyle getParagraphStyle(TextAlign textAlign,
TextDirection textDirection, string ellipsis, int maxLines, double textScaleFactor = 1.0)
{
return new ParagraphStyle(
textAlign, textDirection, fontWeight, fontStyle,
maxLines, (fontSize ?? _defaultFontSize) * textScaleFactor,
fontFamily, height, ellipsis
);
}
}
}

3
Assets/UIWidgets/painting/text_style.cs.meta


fileFormatVersion: 2
guid: 93d2ea584e0947e1b61a8ca8bdd1cf9a
timeCreated: 1535348621

235
Assets/UIWidgets/rendering/paragraph.cs


using System;
using UIWidgets.painting;
using UIWidgets.ui;
using UnityEngine;
namespace UIWidgets.rendering
{
public enum TextOverflow {
/// Clip the overflowing text to fix its container.
clip,
/// Fade the overflowing text to transparent.
fade,
/// Use an ellipsis to indicate that the text has overflowed.
ellipsis,
}
public class RenderParagraph: RenderBox
{
private static readonly string _kEllipsis = "\u2026";
private bool _softWrap;
private TextOverflow _overflow;
private readonly TextPainter _textPainter;
private bool _hasVisualOverflow = false;
public RenderParagraph(TextSpan text,
TextAlign textAlign = TextAlign.left,
TextDirection textDirection = TextDirection.ltr,
bool softWrap = true,
TextOverflow overflow = TextOverflow.clip,
double textScaleFactor = 1.0,
int maxLines = 0
)
{
_softWrap = softWrap;
_overflow = overflow;
_textPainter = new TextPainter(
text,
textAlign,
textDirection,
textScaleFactor,
maxLines,
overflow == TextOverflow.ellipsis ? _kEllipsis : ""
);
}
public TextSpan text
{
get
{
return _textPainter.text;
}
set
{
Debug.Assert(value != null);
switch (_textPainter.text.compareTo(value))
{
case RenderComparison.identical:
case RenderComparison.metadata:
return;
case RenderComparison.paint:
_textPainter.text = value;
markNeedsPaint();
break;
case RenderComparison.layout:
_textPainter.text = value;
markNeedsLayout();
break;
}
}
}
public TextAlign textAlign
{
get { return _textPainter.textAlign; }
set
{
if (_textPainter.textAlign == value)
{
return;
}
_textPainter.textAlign = value;
markNeedsPaint();
}
}
public TextDirection? textDirection
{
get { return _textPainter.textDirection; }
set
{
if (_textPainter.textDirection == value)
{
return;
}
_textPainter.textDirection = textDirection;
markNeedsLayout();
}
}
public bool softWrap
{
get { return _softWrap; }
set
{
if (_softWrap == value)
{
return;
}
_softWrap = value;
markNeedsLayout();
}
}
public TextOverflow overflow
{
get { return _overflow; }
set
{
if (_overflow == value)
{
return;
}
_overflow = value;
_textPainter.ellipsis = value == TextOverflow.ellipsis ? _kEllipsis : null;
// _textPainter.e
markNeedsLayout();
}
}
public double textScaleFactor
{
get { return _textPainter.textScaleFactor; }
set
{
if (Math.Abs(_textPainter.textScaleFactor - value) < 0.00000001)
{
return;
}
_textPainter.textScaleFactor = value;
markNeedsLayout();
}
}
public int maxLines
{
get { return _textPainter.maxLines; }
set
{
if (_textPainter.maxLines == value)
{
return;
}
_textPainter.maxLines = value;
markNeedsLayout();
}
}
public Size textSize
{
get { return _textPainter.size; }
}
public override double computeMinIntrinsicWidth(double height) {
_layoutText();
return _textPainter.minIntrinsicWidth;
}
public override double computeMaxIntrinsicWidth(double height) {
_layoutText();
return _textPainter.maxIntrinsicWidth;
}
double _computeIntrinsicHeight(double width) {
_layoutText(minWidth: width, maxWidth: width);
return _textPainter.height;
}
public override double computeMinIntrinsicHeight(double width) {
return _computeIntrinsicHeight(width);
}
public override double computeMaxIntrinsicHeight(double width) {
return _computeIntrinsicHeight(width);
}
public override double? computeDistanceToActualBaseline(TextBaseline baseline) {
_layoutTextWithConstraints(constraints);
return _textPainter.computeDistanceToActualBaseline(baseline);
}
public override void performLayout() {
_layoutTextWithConstraints(constraints);
var textSize = _textPainter.size;
var didOverflowHeight = _textPainter.didExceedMaxLines;
size = constraints.constrain(textSize);
var didOverflowWidth = size.width < textSize.width;
_hasVisualOverflow = didOverflowWidth || didOverflowHeight;
}
public override void paint(PaintingContext context, Offset offset) {
_layoutTextWithConstraints(constraints);
var canvas = context.canvas;
if (_hasVisualOverflow) {
var bounds = offset & size;
canvas.save();
canvas.clipRect(bounds);
}
_textPainter.paint(canvas, offset);
if (_hasVisualOverflow) {
canvas.restore();
}
}
private void _layoutText(double minWidth = 0.0, double maxWidth = double.PositiveInfinity)
{
var widthMatters = softWrap || overflow == TextOverflow.ellipsis;
_textPainter.layout(minWidth, widthMatters ? maxWidth : double.PositiveInfinity);
}
private void _layoutTextWithConstraints(BoxConstraints constraints) {
_layoutText(minWidth: constraints.minWidth, maxWidth: constraints.maxWidth);
}
}
}

3
Assets/UIWidgets/rendering/paragraph.cs.meta


fileFormatVersion: 2
guid: 69e1c7c86f0d4f4e9aae4c3131653270
timeCreated: 1535348727

170
Assets/UIWidgets/rendering/sliver_fixed_extent_list.cs


using System;
using UIWidgets.ui;
namespace UIWidgets.rendering {
public abstract class RenderSliverFixedExtentBoxAdaptor : RenderSliverMultiBoxAdaptor {
RenderSliverFixedExtentBoxAdaptor(
RenderSliverBoxChildManager childManager = null
) : base(childManager: childManager) {
}
public abstract double itemExtent { get; }
public double indexToLayoutOffset(double itemExtent, int index) {
return itemExtent * index;
}
public int getMinChildIndexForScrollOffset(double scrollOffset, double itemExtent) {
return itemExtent > 0.0 ? Math.Max(0, (int) (scrollOffset / itemExtent)) : 0;
}
public int getMaxChildIndexForScrollOffset(double scrollOffset, double itemExtent) {
return itemExtent > 0.0 ? Math.Max(0, (int) Math.Ceiling(scrollOffset / itemExtent) - 1) : 0;
}
public double estimateMaxScrollOffset(SliverConstraints constraints,
int firstIndex = 0,
int lastIndex = 0,
double leadingScrollOffset = 0.0,
double trailingScrollOffset = 0.0
) {
return this.childManager.estimateMaxScrollOffset(
constraints,
firstIndex: firstIndex,
lastIndex: lastIndex,
leadingScrollOffset: leadingScrollOffset,
trailingScrollOffset: trailingScrollOffset
);
}
public double computeMaxScrollOffset(SliverConstraints constraints, double itemExtent) {
return this.childManager.childCount * itemExtent;
}
public override void performLayout() {
this.childManager.didStartLayout();
this.childManager.setDidUnderflow(false);
double itemExtent = this.itemExtent;
double scrollOffset = this.constraints.scrollOffset + this.constraints.cacheOrigin;
double remainingExtent = this.constraints.remainingCacheExtent;
double targetEndScrollOffset = scrollOffset + remainingExtent;
BoxConstraints childConstraints = this.constraints.asBoxConstraints(
minExtent: itemExtent,
maxExtent: itemExtent
);
int firstIndex = this.getMinChildIndexForScrollOffset(scrollOffset, itemExtent);
int? targetLastIndex = !double.IsInfinity(targetEndScrollOffset)
? this.getMaxChildIndexForScrollOffset(targetEndScrollOffset, itemExtent)
: (int?) null;
if (this.firstChild != null) {
int oldFirstIndex = this.indexOf(this.firstChild);
int oldLastIndex = this.indexOf(this.lastChild);
int leadingGarbage = (firstIndex - oldFirstIndex).clamp(0, this.childCount);
int trailingGarbage =
targetLastIndex == null ? 0 : (oldLastIndex - targetLastIndex.Value).clamp(0, this.childCount);
this.collectGarbage(leadingGarbage, trailingGarbage);
} else {
this.collectGarbage(0, 0);
}
if (this.firstChild == null) {
if (!this.addInitialChild(index: firstIndex,
layoutOffset: this.indexToLayoutOffset(itemExtent, firstIndex))) {
double max = this.computeMaxScrollOffset(this.constraints, itemExtent);
this.geometry = new SliverGeometry(
scrollExtent: max,
maxPaintExtent: max
);
this.childManager.didFinishLayout();
return;
}
}
RenderBox trailingChildWithLayout = null;
for (int index = this.indexOf(this.firstChild) - 1; index >= firstIndex; --index) {
RenderBox child = this.insertAndLayoutLeadingChild(childConstraints);
if (child == null) {
this.geometry = new SliverGeometry(scrollOffsetCorrection: index * itemExtent);
return;
}
var childParentData = (SliverMultiBoxAdaptorParentData) child.parentData;
childParentData.layoutOffset = this.indexToLayoutOffset(itemExtent, index);
trailingChildWithLayout = trailingChildWithLayout ?? child;
}
if (trailingChildWithLayout == null) {
this.firstChild.layout(childConstraints);
var childParentData = (SliverMultiBoxAdaptorParentData) this.firstChild.parentData;
childParentData.layoutOffset = this.indexToLayoutOffset(itemExtent, firstIndex);
trailingChildWithLayout = this.firstChild;
}
while (targetLastIndex == null || this.indexOf(trailingChildWithLayout) < targetLastIndex) {
RenderBox child = this.childAfter(trailingChildWithLayout);
if (child == null) {
child = this.insertAndLayoutChild(childConstraints, after: trailingChildWithLayout);
if (child == null) {
break;
}
} else {
child.layout(childConstraints);
}
trailingChildWithLayout = child;
var childParentData = (SliverMultiBoxAdaptorParentData) child.parentData;
childParentData.layoutOffset = this.indexToLayoutOffset(itemExtent, childParentData.index);
}
int lastIndex = this.indexOf(this.lastChild);
double leadingScrollOffset = this.indexToLayoutOffset(itemExtent, firstIndex);
double trailingScrollOffset = this.indexToLayoutOffset(itemExtent, lastIndex + 1);
double estimatedMaxScrollOffset = this.estimateMaxScrollOffset(
this.constraints,
firstIndex: firstIndex,
lastIndex: lastIndex,
leadingScrollOffset: leadingScrollOffset,
trailingScrollOffset: trailingScrollOffset
);
double paintExtent = this.calculatePaintOffset(
this.constraints,
from: leadingScrollOffset,
to: trailingScrollOffset
);
double cacheExtent = this.calculateCacheOffset(
this.constraints,
from: leadingScrollOffset,
to: trailingScrollOffset
);
double targetEndScrollOffsetForPaint =
this.constraints.scrollOffset + this.constraints.remainingPaintExtent;
int? targetLastIndexForPaint = !double.IsInfinity(targetEndScrollOffsetForPaint)
? this.getMaxChildIndexForScrollOffset(targetEndScrollOffsetForPaint, itemExtent)
: (int?) null;
this.geometry = new SliverGeometry(
scrollExtent: estimatedMaxScrollOffset,
paintExtent: paintExtent,
cacheExtent: cacheExtent,
maxPaintExtent: estimatedMaxScrollOffset,
hasVisualOverflow: (targetLastIndexForPaint != null && lastIndex >= targetLastIndexForPaint)
|| this.constraints.scrollOffset > 0.0
);
if (estimatedMaxScrollOffset == trailingScrollOffset) {
this.childManager.setDidUnderflow(true);
}
this.childManager.didFinishLayout();
}
}
}

3
Assets/UIWidgets/rendering/sliver_fixed_extent_list.cs.meta


fileFormatVersion: 2
guid: e602742e1e9c408989efd79055a9e552
timeCreated: 1535524936

194
Assets/UIWidgets/rendering/sliver_list.cs


using System;
namespace UIWidgets.rendering {
public class RenderSliverList : RenderSliverMultiBoxAdaptor {
RenderSliverList(
RenderSliverBoxChildManager childManager = null
) : base(childManager: childManager) {
}
public override void performLayout() {
this.childManager.didStartLayout();
this.childManager.setDidUnderflow(false);
double scrollOffset = this.constraints.scrollOffset + this.constraints.cacheOrigin;
double remainingExtent = this.constraints.remainingCacheExtent;
double targetEndScrollOffset = scrollOffset + remainingExtent;
BoxConstraints childConstraints = this.constraints.asBoxConstraints();
int leadingGarbage = 0;
int trailingGarbage = 0;
bool reachedEnd = false;
if (this.firstChild == null) {
if (!this.addInitialChild()) {
this.geometry = SliverGeometry.zero;
this.childManager.didFinishLayout();
return;
}
}
RenderBox leadingChildWithLayout = null, trailingChildWithLayout = null;
RenderBox earliestUsefulChild = this.firstChild;
for (double earliestScrollOffset = this.childScrollOffset(earliestUsefulChild);
earliestScrollOffset > scrollOffset;
earliestScrollOffset = this.childScrollOffset(earliestUsefulChild)) {
earliestUsefulChild = this.insertAndLayoutLeadingChild(childConstraints, parentUsesSize: true);
if (earliestUsefulChild == null) {
var childParentData = (SliverMultiBoxAdaptorParentData) this.firstChild.parentData;
childParentData.layoutOffset = 0.0;
if (scrollOffset == 0.0) {
earliestUsefulChild = this.firstChild;
leadingChildWithLayout = earliestUsefulChild;
trailingChildWithLayout = trailingChildWithLayout ?? earliestUsefulChild;
break;
} else {
this.geometry = new SliverGeometry(
scrollOffsetCorrection: -scrollOffset
);
return;
}
} else {
double firstChildScrollOffset = earliestScrollOffset - this.paintExtentOf(this.firstChild);
if (firstChildScrollOffset < 0.0) {
double correction = 0.0;
while (earliestUsefulChild != null) {
correction += this.paintExtentOf(firstChild);
earliestUsefulChild =
this.insertAndLayoutLeadingChild(childConstraints, parentUsesSize: true);
}
this.geometry = new SliverGeometry(
scrollOffsetCorrection: correction - earliestScrollOffset
);
var childParentData = (SliverMultiBoxAdaptorParentData) this.firstChild.parentData;
childParentData.layoutOffset = 0.0;
return;
} else {
var childParentData = (SliverMultiBoxAdaptorParentData) earliestUsefulChild.parentData;
childParentData.layoutOffset = firstChildScrollOffset;
leadingChildWithLayout = earliestUsefulChild;
trailingChildWithLayout = trailingChildWithLayout ?? earliestUsefulChild;
}
}
}
if (leadingChildWithLayout == null) {
earliestUsefulChild.layout(childConstraints, parentUsesSize: true);
leadingChildWithLayout = earliestUsefulChild;
trailingChildWithLayout = earliestUsefulChild;
}
bool inLayoutRange = true;
RenderBox child = earliestUsefulChild;
int index = this.indexOf(child);
double endScrollOffset = this.childScrollOffset(child) + this.paintExtentOf(child);
Func<bool> advance = () => {
if (child == trailingChildWithLayout) {
inLayoutRange = false;
}
child = this.childAfter(child);
if (child == null) {
inLayoutRange = false;
}
index += 1;
if (!inLayoutRange) {
if (child == null || this.indexOf(child) != index) {
child = insertAndLayoutChild(childConstraints,
after: trailingChildWithLayout,
parentUsesSize: true
);
if (child == null) {
return false;
}
} else {
child.layout(childConstraints, parentUsesSize: true);
}
trailingChildWithLayout = child;
}
var childParentData = (SliverMultiBoxAdaptorParentData) child.parentData;
childParentData.layoutOffset = endScrollOffset;
endScrollOffset = this.childScrollOffset(child) + this.paintExtentOf(child);
return true;
};
while (endScrollOffset < scrollOffset) {
leadingGarbage += 1;
if (!advance()) {
this.collectGarbage(leadingGarbage - 1, 0);
double extent = this.childScrollOffset(this.lastChild) + this.paintExtentOf(this.lastChild);
this.geometry = new SliverGeometry(
scrollExtent: extent,
paintExtent: 0.0,
maxPaintExtent: extent
);
return;
}
}
while (endScrollOffset < targetEndScrollOffset) {
if (!advance()) {
reachedEnd = true;
break;
}
}
if (child != null) {
child = this.childAfter(child);
while (child != null) {
trailingGarbage += 1;
child = this.childAfter(child);
}
}
this.collectGarbage(leadingGarbage, trailingGarbage);
double estimatedMaxScrollOffset;
if (reachedEnd) {
estimatedMaxScrollOffset = endScrollOffset;
} else {
estimatedMaxScrollOffset = this.childManager.estimateMaxScrollOffset(
this.constraints,
firstIndex: this.indexOf(this.firstChild),
lastIndex: this.indexOf(this.lastChild),
leadingScrollOffset: this.childScrollOffset(this.firstChild),
trailingScrollOffset: endScrollOffset
);
}
double paintExtent = this.calculatePaintOffset(
this.constraints,
from: this.childScrollOffset(this.firstChild),
to: endScrollOffset
);
double cacheExtent = this.calculateCacheOffset(
this.constraints,
from: this.childScrollOffset(this.firstChild),
to: endScrollOffset
);
double targetEndScrollOffsetForPaint =
this.constraints.scrollOffset + this.constraints.remainingPaintExtent;
this.geometry = new SliverGeometry(
scrollExtent: estimatedMaxScrollOffset,
paintExtent: paintExtent,
cacheExtent: cacheExtent,
maxPaintExtent: estimatedMaxScrollOffset,
hasVisualOverflow: endScrollOffset > targetEndScrollOffsetForPaint ||
this.constraints.scrollOffset > 0.0
);
if (estimatedMaxScrollOffset == endScrollOffset) {
this.childManager.setDidUnderflow(true);
}
this.childManager.didFinishLayout();
}
}
}

3
Assets/UIWidgets/rendering/sliver_list.cs.meta


fileFormatVersion: 2
guid: 1db4d92862744fcdb527f4020106fdf8
timeCreated: 1535522746

299
Assets/UIWidgets/rendering/sliver_multi_box_adaptor.cs


using System.Collections.Generic;
using System.Linq;
using UIWidgets.foundation;
using UIWidgets.painting;
using UIWidgets.ui;
using UnityEngine;
namespace UIWidgets.rendering {
public interface RenderSliverBoxChildManager {
void createChild(int index, RenderBox after = null);
void removeChild(RenderBox child);
double estimateMaxScrollOffset(
SliverConstraints constraints,
int firstIndex = 0,
int lastIndex = 0,
double leadingScrollOffset = 0,
double trailingScrollOffset = 0);
int childCount { get; }
void didAdoptChild(RenderBox child);
void setDidUnderflow(bool value);
void didStartLayout();
void didFinishLayout();
}
public class SliverMultiBoxAdaptorParentData : ContainerParentDataMixinSliverLogicalParentData<RenderBox> {
public int index;
public bool keepAlive = false;
public bool _keptAlive = false;
}
public abstract class RenderSliverMultiBoxAdaptor
: ContainerRenderObjectMixinRenderSliver<RenderBox, SliverMultiBoxAdaptorParentData> {
public RenderSliverMultiBoxAdaptor(
RenderSliverBoxChildManager childManager = null
) {
this._childManager = childManager;
}
public override void setupParentData(RenderObject child) {
if (!(child.parentData is SliverMultiBoxAdaptorParentData)) {
child.parentData = new SliverMultiBoxAdaptorParentData();
}
}
public RenderSliverBoxChildManager childManager {
get { return this._childManager; }
}
public RenderSliverBoxChildManager _childManager;
public readonly Dictionary<int, RenderBox> _keepAliveBucket = new Dictionary<int, RenderBox>();
public override void adoptChild(AbstractNode childNode) {
base.adoptChild(childNode);
var child = (RenderBox) childNode;
var childParentData = (SliverMultiBoxAdaptorParentData) child.parentData;
if (!childParentData._keptAlive) {
this.childManager.didAdoptChild(child);
}
}
public override void insert(RenderBox child, RenderBox after = null) {
base.insert(child, after: after);
}
public override void remove(RenderBox child) {
var childParentData = (SliverMultiBoxAdaptorParentData) child.parentData;
if (!childParentData._keptAlive) {
base.remove(child);
return;
}
this._keepAliveBucket.Remove(childParentData.index);
this.dropChild(child);
}
public override void removeAll() {
base.removeAll();
foreach (var child in this._keepAliveBucket.Values) {
this.dropChild(child);
}
this._keepAliveBucket.Clear();
}
void _createOrObtainChild(int index, RenderBox after = null) {
this.invokeLayoutCallback<SliverConstraints>((SliverConstraints constraints) => {
if (this._keepAliveBucket.ContainsKey(index)) {
RenderBox child = this._keepAliveBucket[index];
this._keepAliveBucket.Remove(index);
var childParentData = (SliverMultiBoxAdaptorParentData) child.parentData;
this.dropChild(child);
child.parentData = childParentData;
this.insert(child, after: after);
childParentData._keptAlive = false;
} else {
this._childManager.createChild(index, after: after);
}
});
}
public void _destroyOrCacheChild(RenderBox child) {
var childParentData = (SliverMultiBoxAdaptorParentData) child.parentData;
if (childParentData.keepAlive) {
this.remove(child);
this._keepAliveBucket[childParentData.index] = child;
child.parentData = childParentData;
base.adoptChild(child);
childParentData._keptAlive = true;
} else {
this._childManager.removeChild(child);
}
}
public override void attach(object owner) {
base.attach(owner);
foreach (RenderBox child in this._keepAliveBucket.Values) {
child.attach(owner);
}
}
public override void detach() {
base.detach();
foreach (RenderBox child in this._keepAliveBucket.Values) {
child.detach();
}
}
public override void redepthChildren() {
base.redepthChildren();
foreach (var child in this._keepAliveBucket.Values) {
this.redepthChild(child);
}
}
public override void visitChildren(RenderObjectVisitor visitor) {
base.visitChildren(visitor);
foreach (var child in this._keepAliveBucket.Values) {
visitor(child);
}
}
public bool addInitialChild(int index = 0, double layoutOffset = 0.0) {
this._createOrObtainChild(index, after: null);
if (this.firstChild != null) {
var firstChildParentData = (SliverMultiBoxAdaptorParentData) this.firstChild.parentData;
firstChildParentData.layoutOffset = layoutOffset;
return true;
}
this.childManager.setDidUnderflow(true);
return false;
}
public RenderBox insertAndLayoutLeadingChild(BoxConstraints childConstraints, bool parentUsesSize = false) {
int index = this.indexOf(this.firstChild) - 1;
this._createOrObtainChild(index, after: null);
if (this.indexOf(this.firstChild) == index) {
this.firstChild.layout(childConstraints, parentUsesSize: parentUsesSize);
return this.firstChild;
}
this.childManager.setDidUnderflow(true);
return null;
}
public RenderBox insertAndLayoutChild(
BoxConstraints childConstraints,
RenderBox after = null,
bool parentUsesSize = false
) {
int index = this.indexOf(after) + 1;
this._createOrObtainChild(index, after: after);
RenderBox child = this.childAfter(after);
if (child != null && this.indexOf(child) == index) {
child.layout(childConstraints, parentUsesSize: parentUsesSize);
return child;
}
this.childManager.setDidUnderflow(true);
return null;
}
public void collectGarbage(int leadingGarbage, int trailingGarbage) {
this.invokeLayoutCallback<SliverConstraints>((SliverConstraints constraints) => {
while (leadingGarbage > 0) {
this._destroyOrCacheChild(this.firstChild);
leadingGarbage -= 1;
}
while (trailingGarbage > 0) {
this._destroyOrCacheChild(this.lastChild);
trailingGarbage -= 1;
}
this._keepAliveBucket.Values.Where((RenderBox child) => {
var childParentData = (SliverMultiBoxAdaptorParentData) child.parentData;
return !childParentData.keepAlive;
}).ToList().ForEach(this._childManager.removeChild);
});
}
public int indexOf(RenderBox child) {
var childParentData = (SliverMultiBoxAdaptorParentData) child.parentData;
return childParentData.index;
}
public double paintExtentOf(RenderBox child) {
switch (this.constraints.axis) {
case Axis.horizontal:
return child.size.width;
case Axis.vertical:
return child.size.height;
}
return 0.0;
}
public override double childMainAxisPosition(RenderObject child) {
return this.childScrollOffset(child) - this.constraints.scrollOffset;
}
public override double childScrollOffset(RenderObject child) {
var childParentData = (SliverMultiBoxAdaptorParentData) child.parentData;
return childParentData.layoutOffset;
}
public override void applyPaintTransform(RenderObject child, ref Matrix4x4 transform) {
this.applyPaintTransformForBoxChild((RenderBox) child, ref transform);
}
public override void paint(PaintingContext context, Offset offset) {
if (this.firstChild == null) {
return;
}
Offset mainAxisUnit = null, crossAxisUnit = null, originOffset = null;
bool addExtent = false;
switch (GrowthDirectionUtils.applyGrowthDirectionToAxisDirection(this.constraints.axisDirection,
this.constraints.growthDirection)) {
case AxisDirection.up:
mainAxisUnit = new Offset(0.0, -1.0);
crossAxisUnit = new Offset(1.0, 0.0);
originOffset = offset + new Offset(0.0, this.geometry.paintExtent);
addExtent = true;
break;
case AxisDirection.right:
mainAxisUnit = new Offset(1.0, 0.0);
crossAxisUnit = new Offset(0.0, 1.0);
originOffset = offset;
addExtent = false;
break;
case AxisDirection.down:
mainAxisUnit = new Offset(0.0, 1.0);
crossAxisUnit = new Offset(1.0, 0.0);
originOffset = offset;
addExtent = false;
break;
case AxisDirection.left:
mainAxisUnit = new Offset(-1.0, 0.0);
crossAxisUnit = new Offset(0.0, 1.0);
originOffset = offset + new Offset(this.geometry.paintExtent, 0.0);
addExtent = true;
break;
}
RenderBox child = this.firstChild;
while (child != null) {
double mainAxisDelta = this.childMainAxisPosition(child);
double crossAxisDelta = this.childCrossAxisPosition(child);
Offset childOffset = new Offset(
originOffset.dx + mainAxisUnit.dx * mainAxisDelta + crossAxisUnit.dx * crossAxisDelta,
originOffset.dy + mainAxisUnit.dy * mainAxisDelta + crossAxisUnit.dy * crossAxisDelta
);
if (addExtent) {
childOffset += mainAxisUnit * this.paintExtentOf(child);
}
if (mainAxisDelta < this.constraints.remainingPaintExtent &&
mainAxisDelta + this.paintExtentOf(child) > 0) {
context.paintChild(child, childOffset);
}
child = this.childAfter(child);
}
}
}
}

3
Assets/UIWidgets/rendering/sliver_multi_box_adaptor.cs.meta


fileFormatVersion: 2
guid: 00853d7738fe40eeb3e7b44db23248be
timeCreated: 1535502825

232
Assets/UIWidgets/rendering/sliver_padding.cs


using System;
using UIWidgets.painting;
using UIWidgets.ui;
using UnityEngine;
namespace UIWidgets.rendering {
public class RenderSliverPadding : RenderObjectWithChildMixinRenderSliver<RenderSliver> {
RenderSliverPadding(
EdgeInsets padding,
RenderSliver child
) {
this._padding = padding;
this.child = child;
}
public EdgeInsets padding {
get { return this._padding; }
set {
if (this._padding == value) {
return;
}
this._padding = value;
this.markNeedsLayout();
}
}
public EdgeInsets _padding;
public double beforePadding {
get {
switch (GrowthDirectionUtils.applyGrowthDirectionToAxisDirection(
this.constraints.axisDirection, this.constraints.growthDirection)) {
case AxisDirection.up:
return this._padding.bottom;
case AxisDirection.right:
return this._padding.left;
case AxisDirection.down:
return this._padding.top;
case AxisDirection.left:
return this._padding.right;
}
return 0.0;
}
}
public double afterPadding {
get {
switch (GrowthDirectionUtils.applyGrowthDirectionToAxisDirection(
this.constraints.axisDirection, this.constraints.growthDirection)) {
case AxisDirection.up:
return this._padding.top;
case AxisDirection.right:
return this._padding.right;
case AxisDirection.down:
return this._padding.bottom;
case AxisDirection.left:
return this._padding.left;
}
return 0.0;
}
}
public double mainAxisPadding {
get { return this._padding.along(this.constraints.axis); }
}
public double crossAxisPadding {
get {
switch (this.constraints.axis) {
case Axis.horizontal:
return this._padding.vertical;
case Axis.vertical:
return this._padding.horizontal;
}
return 0.0;
}
}
public override void setupParentData(RenderObject child) {
if (!(child.parentData is SliverPhysicalParentData)) {
child.parentData = new SliverPhysicalParentData();
}
}
public override void performLayout() {
double beforePadding = this.beforePadding;
double afterPadding = this.afterPadding;
double mainAxisPadding = this.mainAxisPadding;
double crossAxisPadding = this.crossAxisPadding;
if (this.child == null) {
this.geometry = new SliverGeometry(
scrollExtent: mainAxisPadding,
paintExtent: Math.Min(mainAxisPadding, this.constraints.remainingPaintExtent),
maxPaintExtent: mainAxisPadding
);
return;
}
this.child.layout(
this.constraints.copyWith(
scrollOffset: Math.Max(0.0, this.constraints.scrollOffset - beforePadding),
cacheOrigin: Math.Min(0.0, this.constraints.cacheOrigin + beforePadding),
overlap: 0.0,
remainingPaintExtent: this.constraints.remainingPaintExtent -
this.calculatePaintOffset(this.constraints, from: 0.0, to: beforePadding),
remainingCacheExtent: this.constraints.remainingCacheExtent -
this.calculateCacheOffset(this.constraints, from: 0.0, to: beforePadding),
crossAxisExtent: Math.Max(0.0, this.constraints.crossAxisExtent - crossAxisPadding)
),
parentUsesSize: true
);
SliverGeometry childLayoutGeometry = this.child.geometry;
if (childLayoutGeometry.scrollOffsetCorrection != 0.0) {
this.geometry = new SliverGeometry(
scrollOffsetCorrection: childLayoutGeometry.scrollOffsetCorrection
);
return;
}
double beforePaddingPaintExtent = this.calculatePaintOffset(
this.constraints,
from: 0.0,
to: beforePadding
);
double afterPaddingPaintExtent = this.calculatePaintOffset(
this.constraints,
from: beforePadding + childLayoutGeometry.scrollExtent,
to: mainAxisPadding + childLayoutGeometry.scrollExtent
);
double mainAxisPaddingPaintExtent = beforePaddingPaintExtent + afterPaddingPaintExtent;
double beforePaddingCacheExtent = this.calculateCacheOffset(
this.constraints,
from: 0.0,
to: beforePadding
);
double afterPaddingCacheExtent = this.calculateCacheOffset(
this.constraints,
from: beforePadding + childLayoutGeometry.scrollExtent,
to: mainAxisPadding + childLayoutGeometry.scrollExtent
);
double mainAxisPaddingCacheExtent = afterPaddingCacheExtent + beforePaddingCacheExtent;
double paintExtent = Math.Min(
beforePaddingPaintExtent + Math.Max(childLayoutGeometry.paintExtent,
childLayoutGeometry.layoutExtent + afterPaddingPaintExtent),
this.constraints.remainingPaintExtent
);
this.geometry = new SliverGeometry(
scrollExtent: mainAxisPadding + childLayoutGeometry.scrollExtent,
paintExtent: paintExtent,
layoutExtent: Math.Min(mainAxisPaddingPaintExtent + childLayoutGeometry.layoutExtent, paintExtent),
cacheExtent: Math.Min(mainAxisPaddingCacheExtent + childLayoutGeometry.cacheExtent,
this.constraints.remainingCacheExtent),
maxPaintExtent: mainAxisPadding + childLayoutGeometry.maxPaintExtent,
hitTestExtent: Math.Max(
mainAxisPaddingPaintExtent + childLayoutGeometry.paintExtent,
beforePaddingPaintExtent + childLayoutGeometry.hitTestExtent
),
hasVisualOverflow: childLayoutGeometry.hasVisualOverflow
);
var childParentData = (SliverPhysicalParentData) this.child.parentData;
switch (GrowthDirectionUtils.applyGrowthDirectionToAxisDirection(this.constraints.axisDirection,
this.constraints.growthDirection)) {
case AxisDirection.up:
childParentData.paintOffset = new Offset(this._padding.left,
this.calculatePaintOffset(this.constraints,
from: this._padding.bottom + childLayoutGeometry.scrollExtent,
to: this._padding.bottom + childLayoutGeometry.scrollExtent + this._padding.top));
break;
case AxisDirection.right:
childParentData.paintOffset =
new Offset(this.calculatePaintOffset(this.constraints, from: 0.0, to: this._padding.left),
this._padding.top);
break;
case AxisDirection.down:
childParentData.paintOffset = new Offset(this._padding.left,
this.calculatePaintOffset(this.constraints, from: 0.0, to: this._padding.top));
break;
case AxisDirection.left:
childParentData.paintOffset = new Offset(
this.calculatePaintOffset(this.constraints,
from: this._padding.right + childLayoutGeometry.scrollExtent,
to: this._padding.right + childLayoutGeometry.scrollExtent + this._padding.left),
this._padding.top);
break;
}
}
public override double childMainAxisPosition(RenderObject child) {
return this.calculatePaintOffset(this.constraints, from: 0.0, to: this.beforePadding);
}
public override double childCrossAxisPosition(RenderObject child) {
switch (GrowthDirectionUtils.applyGrowthDirectionToAxisDirection(
this.constraints.axisDirection, this.constraints.growthDirection)) {
case AxisDirection.up:
case AxisDirection.down:
return this._padding.left;
case AxisDirection.left:
case AxisDirection.right:
return this._padding.top;
}
return 0.0;
}
public override double childScrollOffset(RenderObject child) {
return this.beforePadding;
}
public override void applyPaintTransform(RenderObject child, ref Matrix4x4 transform) {
var childParentData = (SliverPhysicalParentData) child.parentData;
childParentData.applyPaintTransform(ref transform);
}
public override void paint(PaintingContext context, Offset offset) {
if (this.child != null && this.child.geometry.visible) {
var childParentData = (SliverPhysicalParentData) this.child.parentData;
context.paintChild(this.child, offset + childParentData.paintOffset);
}
}
}
}

3
Assets/UIWidgets/rendering/sliver_padding.cs.meta


fileFormatVersion: 2
guid: 470336df9a5d4af3a4ccfa5fa759d854
timeCreated: 1535523877

3
Assets/UIWidgets/ui/txt.meta


fileFormatVersion: 2
guid: 00abcb769ae345788c13376e3170023b
timeCreated: 1535349060

2
Assets/UIWidgets/gestures/arena.cs


namespace UIWidgets.gestures {
}

14
Assets/UIWidgets/math/math.cs


namespace UIWidgets.math
{
public class MathUtil
{
public static double Clamp(double value, double min, double max)
{
if ((double) value < (double) min)
value = min;
else if ((double) value > (double) max)
value = max;
return value;
}
}
}

3
Assets/UIWidgets/math/math.cs.meta


fileFormatVersion: 2
guid: b170f0bc9c074368b3be9db736974c6f
timeCreated: 1535421239

3
Assets/UIWidgets/ui/txt/linebreaker.cs.meta


fileFormatVersion: 2
guid: 05dff99bf5a0462da5c4c9c7b7d1b3dc
timeCreated: 1535533476

3
Assets/UIWidgets/ui/txt/paragraph.cs.meta


fileFormatVersion: 2
guid: 8c81399e7e914dedaee84b52748d4ac0
timeCreated: 1535349134

3
Assets/UIWidgets/ui/txt/paragraph_builder.cs.meta


fileFormatVersion: 2
guid: 869d4277d11048c397fc1fdb3abe3c02
timeCreated: 1535349090

161
Assets/UIWidgets/ui/txt/styled_runs.cs


using System;
using System.Collections.Generic;
using UnityEngine;
namespace UIWidgets.ui
{
public class StyledRuns
{
private readonly List<TextStyle> styles = new List<TextStyle>();
private readonly List<IndexedRun> runs = new List<IndexedRun>();
public class RunIterator
{
private int _charIndex;
private int _runIndex;
private StyledRuns _runs;
public void nextTo(int index)
{
if (_charIndex > index)
{
throw new ArgumentException("can to move back");
}
_charIndex = index;
while (_runIndex < _runs.size)
{
var run = _runs.getRun(_runIndex);
if (run.start <= _charIndex && _charIndex < run.end)
{
break;
}
_runIndex++;
}
}
public Run run
{
get { return _runs.getRun(_runIndex); }
}
public int charIndex
{
get { return _charIndex; }
}
public int runIndex
{
get { return _runIndex; }
}
public bool end
{
get
{
return runIndex >= _runs.size;
}
}
internal RunIterator(StyledRuns runs)
{
_charIndex = 0;
_runIndex = 0;
_runs = runs;
}
}
public class Run
{
public readonly TextStyle style;
public readonly int start;
public readonly int end;
public Run(TextStyle style, int start, int end)
{
this.style = style;
this.start = start;
this.end = end;
}
}
public class IndexedRun
{
public readonly int styleIndex = 0;
public readonly int start;
public int end;
public IndexedRun(int styleIndex, int start, int end)
{
this.styleIndex = styleIndex;
this.start = start;
this.end = end;
}
}
public StyledRuns()
{
}
public StyledRuns(StyledRuns other)
{
styles = new List<TextStyle>(other.styles);
runs = new List<IndexedRun>(other.runs);
}
public int addStyle(TextStyle style)
{
var styleIndex = styles.Count;
styles.Add( style);
return styleIndex;
}
public TextStyle getStyle(int index)
{
return styles[index];
}
public void startRun(int styleIndex, int start)
{
endRunIfNeeded(start);
runs.Add(new IndexedRun(styleIndex, start, start));
}
public void endRunIfNeeded(int end)
{
var lastIndex = runs.Count - 1;
if (lastIndex < 0)
{
return;
}
var run = runs[lastIndex];
if (run.start == end)
{
runs.RemoveAt(lastIndex);
}
else
{
run.end = end;
}
}
public Run getRun(int index)
{
var run = runs[index];
return new Run(styles[run.styleIndex], run.start, run.end);
}
public RunIterator iterator()
{
return new RunIterator(this);
}
public int size
{
get { return runs.Count; }
}
}
}

3
Assets/UIWidgets/ui/txt/styled_runs.cs.meta


fileFormatVersion: 2
guid: 3f314adfc2d8498d827e5501599b0f5a
timeCreated: 1535434217

152
Assets/UIWidgets/ui/txt/linebreaker.cs


using System;
using System.Collections.Generic;
using UnityEngine;
namespace UIWidgets.ui
{
public class LineBreaker
{
public class LineInfo
{
public int start;
public double width;
}
private StyledRuns _runs;
public Vector2[] _characterPositions;
public float[] _characterWidth;
private string _text;
private float _width;
private int _lineStart;
private int _wordStart;
private int _spaceCount = 0;
private int tabCount = 4;
private double _lineLength;
private Font[] _styleRunFonts;
private List<LineInfo> _lines;
public void setup(string text, StyledRuns runs, Font[] styleRunFonts, float width, Vector2[] characterPositions, float[] characterWidth)
{
_text = text;
_runs = runs;
_characterPositions = characterPositions;
_characterWidth = characterWidth;
_width = width;
_styleRunFonts = styleRunFonts;
}
public List<LineInfo> getLines()
{
return _lines;
}
public void doBreak(int blockStart, int blockEnd)
{
_lines = new List<LineInfo>();
_lineStart = blockStart;
_wordStart = blockStart;
_spaceCount = 0;
float offsetX = 0.0f;
var runIterator = _runs.iterator();
for (var charIndex = blockStart; charIndex < blockEnd; charIndex++)
{
runIterator.nextTo(charIndex);
var run = runIterator.run;
var font = _styleRunFonts[runIterator.runIndex];
var style = run.style;
CharacterInfo charInfo;
var result = font.GetCharacterInfo(_text[charIndex], out charInfo, 0, run.style.UnityFontStyle);
if (_text[charIndex] == '\t')
{
_spaceCount++;
font.GetCharacterInfo(' ', out charInfo,
style.UnityFontSize, style.UnityFontStyle);
float tabSize = charInfo.advance * tabCount;
var newX = (float)Math.Floor(((offsetX / tabSize) + 1) * tabSize);
if (newX > _width && _lineStart != charIndex)
{
_characterWidth[charIndex] = tabSize;
makeLine(charIndex, charIndex);
}
else
{
_characterWidth[charIndex] = newX - offsetX;
_characterPositions[charIndex].x = offsetX;
}
offsetX = _characterPositions[charIndex].x + _characterWidth[charIndex];
}
else if (_text[charIndex] == ' ')
{
_spaceCount++;
_characterPositions[charIndex].x = offsetX;
_characterWidth[charIndex] = charInfo.advance;
offsetX = _characterPositions[charIndex].x + _characterWidth[charIndex];
// todo no wrap in space ?
}
else
{
if (_spaceCount > 0 || blockStart == charIndex)
{
_wordStart = charIndex;
}
_characterPositions[charIndex].x = offsetX;
_characterWidth[charIndex] = charInfo.advance;
if (offsetX + charInfo.advance > _width && _lineStart != charIndex)
{
if (_lineStart == _wordStart)
{
makeLine(charIndex, charIndex);
_wordStart = charIndex;
}
else
{
makeLine(_wordStart, charIndex);
}
}
offsetX = _characterPositions[charIndex].x + _characterWidth[charIndex];
_spaceCount = 0;
}
}
makeLine(blockEnd, blockEnd);
}
private void makeLine(int end, int last)
{
Debug.Assert(_lineStart < end);
Debug.Assert(end <= last);
_lines.Add(new LineInfo()
{
start = _lineStart,
width = _characterPositions[end - 1].x + _characterWidth[end - 1],
});
_lineStart = end;
if (end >= _characterPositions.Length)
{
return;
}
var offset = new Vector2(-_characterPositions[end].x, 0);
_characterPositions[end].x = 0;
if (end < last)
{
Paragraph.offsetCharacters(offset,
_characterPositions, end + 1, last + 1);
}
}
}
}

490
Assets/UIWidgets/ui/txt/paragraph.cs


using System;
using System.Collections.Generic;
using System.Text;
using JetBrains.Annotations;
using UnityEngine;
using UnityEngine.Assertions;
using UnityEngine.Experimental.UIElements;
namespace UIWidgets.ui
{
public class Paragraph
{
struct Range<T>: IEquatable<Range<T>>
{
public Range(T start, T end)
{
this.start = start;
this.end = end;
}
public bool Equals(Range<T> other)
{
return EqualityComparer<T>.Default.Equals(start, other.start) && EqualityComparer<T>.Default.Equals(end, other.end);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
return obj is Range<T> && Equals((Range<T>) obj);
}
public override int GetHashCode()
{
unchecked
{
return (EqualityComparer<T>.Default.GetHashCode(start) * 397) ^ EqualityComparer<T>.Default.GetHashCode(end);
}
}
public static bool operator ==(Range<T> left, Range<T> right)
{
return left.Equals(right);
}
public static bool operator !=(Range<T> left, Range<T> right)
{
return !left.Equals(right);
}
public T start, end;
}
class LineRange
{
public LineRange(int start, int end, int endExcludingWhitespace, int endIncludingNewLine, bool hardBreak)
{
this.start = start;
this.end = end;
this.endExcludingWhitespace = endExcludingWhitespace;
this.endIncludingNewLine = endIncludingNewLine;
this.hardBreak = hardBreak;
}
public readonly int start;
public readonly int end;
public readonly int endExcludingWhitespace;
public readonly int endIncludingNewLine;
public readonly bool hardBreak;
}
class LayoutContext
{
public int width;
public int index;
public Vector2 offset;
public TextStyle style;
public Font font;
public int wordStart;
public int lineStart;
public int prevWordEnd;
}
private static readonly Shader textShader;
static Paragraph() {
textShader = Shader.Find("UIWidgets/Text Shader");
if (textShader == null) {
throw new Exception("UIWidgets/Text Shader Lines not found");
}
}
private bool _needsLayout = true;
private string _text;
private StyledRuns _runs;
private ParagraphStyle _paragraphStyle;
private List<LineRange> _lineRanges = new List<LineRange>();
private List<double> _lineWidths = new List<double>();
private Vector2[] _characterPositions;
private double _maxIntrinsicWidth;
private double _minIntrinsicWidth;
private double _alphabeticBaseline;
private double _ideographicBaseline;
private Font[] _styleRunFonts;
private float[] _characterWidths;
private List<double> _lineHeights = new List<double>();
private LayoutContext context;
private bool _didExceedMaxLines;
// private double _characterWidth;
private double _width;
public const char CHAR_NBSP = '\u00A0';
public static bool isWordSpace(char ch)
{
return ch == ' ' || ch == CHAR_NBSP;
}
public double height
{
get { return _lineHeights.Count == 0 ? 0 : _lineHeights[_lineHeights.Count - 1]; }
}
public double minIntrinsicWidth
{
get { return _minIntrinsicWidth; }
}
public double maxIntrinsicWidth
{
get { return _maxIntrinsicWidth; }
}
public double width
{
get { return _width; }
}
public double alphabeticBaseline
{
get { return 0.0; }
}
public double ideographicBaseline
{
get { return 0.0; }
}
public bool didExceedMaxLines
{
get { return _didExceedMaxLines; }
}
public void paint(Canvas canvas, double x, double y)
{
for (int runIndex = 0; runIndex < _runs.size; ++runIndex)
{
var run = _runs.getRun(runIndex);
if (run.start < run.end)
{
var font = _styleRunFonts[runIndex];
var mesh = generateMesh(x, y, font, run);
canvas.drawMesh(mesh, font.material);
}
}
}
public void layout(ParagraphConstraints constraints)
{
if (!_needsLayout && _width == constraints.width)
{
return;
}
_needsLayout = false;
_width = Math.Floor(constraints.width);
this.setup();
computeLineBreak();
var maxLines = _paragraphStyle.maxLines ?? 0;
_didExceedMaxLines = maxLines == 0 || _lineRanges.Count <= maxLines;
var lineLimits = maxLines == 0 ? _lineRanges.Count : Math.Min(maxLines, _lineRanges.Count);
layoutLines(lineLimits);
double maxWordWidth = 0;
for (int lineNumber = 0; lineNumber < lineLimits; ++lineNumber)
{
var line = _lineRanges[lineNumber];
var words = findWords(line.start, line.end);
words.ForEach((word) =>
{
Debug.Assert(word.start < word.end);
double wordWidth = _characterPositions[word.end - 1].x - _characterPositions[word.start].x +
_characterWidths[word.end - 1];
if (wordWidth > maxWordWidth)
{
maxWordWidth = wordWidth;
}
});
}
computeWidthMetrics(maxWordWidth);
}
public void setText(string text, StyledRuns runs)
{
_text = text;
_runs = runs;
_needsLayout = true;
_styleRunFonts = null;
}
public void setParagraphStyle(ParagraphStyle style)
{
_needsLayout = true;
_paragraphStyle = style;
_styleRunFonts = null;
}
public static void offsetCharacters(Vector2 offset, Vector2[] characterPos, int start, int end)
{
if (characterPos != null)
{
for (int i = start; i < characterPos.Length && i < end; ++i)
{
characterPos[i] = characterPos[i] + offset;
}
}
}
private void computeWidthMetrics(double maxWordWidth)
{
_maxIntrinsicWidth = 0;
double lineBlockWidth = 0;
for (int i = 0; i < _lineWidths.Count; ++i)
{
var line = _lineRanges[i];
lineBlockWidth += _lineWidths[i];
if (line.hardBreak)
{
_maxIntrinsicWidth = Math.Max(lineBlockWidth, _maxIntrinsicWidth);
lineBlockWidth = 0;
}
}
if (_paragraphStyle.maxLines == 1 || (((_paragraphStyle.maxLines??0) == 0) &&
!string.IsNullOrEmpty(_paragraphStyle.ellipsis)))
{
_minIntrinsicWidth = _maxIntrinsicWidth;
}
else
{
_minIntrinsicWidth = Math.Min(maxWordWidth, _maxIntrinsicWidth);
}
}
private void setup()
{
_characterPositions = new Vector2[_text.Length];
_lineHeights.Clear();
_lineRanges.Clear();
_lineWidths.Clear();
_characterWidths = new float[_text.Length];
if (_styleRunFonts == null)
{
_styleRunFonts = new Font[_runs.size];
for (int i = 0; i < _styleRunFonts.Length; ++i)
{
var run = _runs.getRun(i);
if (run.start < run.end)
{
_styleRunFonts[i] = Font.CreateDynamicFontFromOSFont(run.style.safeFontFamily,
run.style.UnityFontSize);
_styleRunFonts[i].material.shader = textShader;
_styleRunFonts[i].RequestCharactersInTexture(_text.Substring(run.start, run.end - run.start), 0,
run.style.UnityFontStyle);
}
}
}
}
private void layoutLines(int lineLimits)
{
double yOffset = 0;
var runIndex = 0;
double lastDescent = 0.0f;
for (int lineNumber = 0; lineNumber < lineLimits; lineNumber++)
{
var line = _lineRanges[lineNumber];
double maxAscent = 0.0f;
double maxDescent = 0.0f;
for (;;)
{
var run = _runs.getRun(runIndex);
if (run.start < run.end && run.start < line.end && run.end > line.start)
{
var font = _styleRunFonts[runIndex];
var ascent = font.ascent * (run.style.height??1.0);
var descent = (font.lineHeight - font.ascent) * (run.style.height??1.0);
if (ascent > maxAscent)
{
maxAscent = ascent;
}
if (descent > maxDescent)
{
maxDescent = descent;
}
}
if (runIndex + 1 >= _runs.size)
{
break;
}
if (run.end < line.end)
{
runIndex++;
}
else
{
break;
}
}
if (lineNumber == 0)
{
_alphabeticBaseline = maxAscent;
_ideographicBaseline = maxAscent; // todo Properly implement ideographic_baseline
}
lastDescent = maxDescent;
yOffset += maxAscent + lastDescent;
for (var charIndex = line.start; charIndex < line.end; charIndex++)
{
_characterPositions[charIndex].y = (float)yOffset;
}
_lineHeights.Add((_lineHeights.Count == 0 ? 0 : _lineHeights[_lineHeights.Count - 1]) +
Math.Round(maxAscent + maxDescent));
}
}
private void computeLineBreak()
{
var newLinePositions = new List<int>();
for (var i = 0; i < _text.Length; i++)
{
if (_text[i] == '\n')
{
newLinePositions.Add(i);
}
}
newLinePositions.Add(_text.Length);
int runIndex = 0;
StyledRuns.Run lastRun = null;
var lineBreaker = new LineBreaker();
lineBreaker.setup(_text, _runs, _styleRunFonts, (float)_width, _characterPositions, _characterWidths);
for (var newlineIndex = 0; newlineIndex < newLinePositions.Count; ++newlineIndex)
{
var blockStart = newlineIndex > 0 ? newLinePositions[newlineIndex - 1] + 1 : 0;
var blockEnd = newLinePositions[newlineIndex];
var blockSize = blockEnd - blockStart;
if (blockSize == 0)
{
_lineRanges.Add(new LineRange(blockStart, blockEnd, blockEnd, blockEnd + 1, true));
_lineWidths.Add(0);
continue;
}
lineBreaker.doBreak(blockStart, blockEnd);
var lines = lineBreaker.getLines();
for (int i = 0; i < lines.Count; ++i)
{
var line = lines[i];
var end = i + 1 < lines.Count ? lines[i + 1].start : blockEnd;
var nonWhiteSpace = end - 1;
while (nonWhiteSpace >= line.start && _text[nonWhiteSpace] == ' ' || _text[nonWhiteSpace] == '\t')
{
nonWhiteSpace--;
}
_lineRanges.Add(new LineRange(line.start, end, nonWhiteSpace, end + 1, end == blockEnd));
_lineWidths.Add(line.width);
}
}
return;
}
private Mesh generateMesh(double x, double y, Font font, StyledRuns.Run run)
{
var vertices = new Vector3[_text.Length * 4];
var triangles = new int[_text.Length * 6];
var uv = new Vector2[_text.Length * 4];
Vector3 offset = new Vector3((float)x, (float)y, 0);
font.RequestCharactersInTexture(_text.Substring(run.start, run.end - run.start), run.style.UnityFontSize, run.style.UnityFontStyle);
for (int charIndex = run.start; charIndex < run.end; ++charIndex)
{
CharacterInfo charInfo;
var result = font.GetCharacterInfo(_text[charIndex], out charInfo, run.style.UnityFontSize, run.style.UnityFontStyle);
var position = _characterPositions[charIndex];
vertices[4 * charIndex + 0] = offset + new Vector3(position.x + charInfo.minX, position.y - charInfo.maxY, 0);
vertices[4 * charIndex + 1] = offset + new Vector3(position.x + charInfo.maxX, position.y - charInfo.maxY, 0);
vertices[4 * charIndex + 2] = offset + new Vector3(position.x + charInfo.maxX, position.y - charInfo.minY, 0);
vertices[4 * charIndex + 3] = offset + new Vector3(position.x + charInfo.minX, position.y - charInfo.minY, 0);
if (_text[charIndex] != ' ' && _text[charIndex] != '\t' && _text[charIndex] != '\n')
{
uv[4 * charIndex + 0] = charInfo.uvTopLeft;
uv[4 * charIndex + 1] = charInfo.uvTopRight;
uv[4 * charIndex + 2] = charInfo.uvBottomRight;
uv[4 * charIndex + 3] = charInfo.uvBottomLeft;
}
else
{
uv[4 * charIndex + 0] = Vector2.zero;
uv[4 * charIndex + 1] = Vector2.zero;
uv[4 * charIndex + 2] = Vector2.zero;
uv[4 * charIndex + 3] = Vector2.zero;
}
triangles[6 * charIndex + 0] = 4 * charIndex + 0;
triangles[6 * charIndex + 1] = 4 * charIndex + 1;
triangles[6 * charIndex + 2] = 4 * charIndex + 2;
triangles[6 * charIndex + 3] = 4 * charIndex + 0;
triangles[6 * charIndex + 4] = 4 * charIndex + 2;
triangles[6 * charIndex + 5] = 4 * charIndex + 3;
}
var mesh = new Mesh()
{
vertices = vertices,
triangles = triangles,
uv = uv
};
var colors = new UnityEngine.Color[vertices.Length];
for (var i = 0; i < colors.Length; i++)
{
colors[i] = run.style.UnityColor;
}
mesh.colors = colors;
return mesh;
}
private List<Range<int>> findWords(int start, int end)
{
var inWord = false;
int wordStart = 0;
List<Range<int>> words = new List<Range<int>>();
for (int i = start; i < end; ++i) {
bool isSpace = isWordSpace(_text[i]);
if (!inWord && !isSpace) {
wordStart = i;
inWord = true;
} else if (inWord && isSpace) {
words.Add(new Range<int>(wordStart, i));
inWord = false;
}
}
if (inWord) {
words.Add(new Range<int>(wordStart, end));
}
return words;
}
}
}

76
Assets/UIWidgets/ui/txt/paragraph_builder.cs


using System.Collections.Generic;
using System.Text;
namespace UIWidgets.ui
{
public class ParagraphBuilder
{
private StringBuilder _text = new StringBuilder();
private ParagraphStyle _paragraphStyle;
private StyledRuns _runs = new StyledRuns();
private List<int> _styleStack = new List<int>();
private int _paragraph_style_index;
public ParagraphBuilder(ParagraphStyle style)
{
setParagraphStyle(style);
}
public Paragraph build()
{
_runs.endRunIfNeeded(_text.Length);
var paragraph = new Paragraph();
paragraph.setText(_text.ToString(), _runs);
paragraph.setParagraphStyle(_paragraphStyle);
return paragraph;
}
public void pushStyle(TextStyle style)
{
var newStyle = peekStyle().merge(style);
var styleIndex = _runs.addStyle(newStyle);
_styleStack.Add(styleIndex);
_runs.startRun(styleIndex, _text.Length);
}
public void pop()
{
var lastIndex = _styleStack.Count - 1;
if (lastIndex < 0)
{
return;
}
_styleStack.RemoveAt(lastIndex);
_runs.startRun(peekStyleIndex(), _text.Length);
}
public void addText(string text)
{
this._text.Append(text);
}
public TextStyle peekStyle()
{
return _runs.getStyle(peekStyleIndex());
}
public int peekStyleIndex() {
int count = _styleStack.Count;
if (count > 0)
{
return _styleStack[count - 1];
}
return _paragraph_style_index;
}
private void setParagraphStyle(ParagraphStyle style)
{
_paragraphStyle = style;
_paragraph_style_index = _runs.addStyle(style.getTextStyle());
_runs.startRun(_paragraph_style_index, _text.Length);
}
}
}
正在加载...
取消
保存