kg
6 年前
当前提交
c6ad4737
共有 25 个文件被更改,包括 602 次插入 和 177 次删除
-
4Assets/UIWidgets/Tests/CanvasAndLayers.cs
-
28Assets/UIWidgets/editor/editor_window.cs
-
1Assets/UIWidgets/flow/layer.cs
-
16Assets/UIWidgets/flow/layer_builder.cs
-
44Assets/UIWidgets/flow/picture_layer.cs
-
2Assets/UIWidgets/flow/transform_layer.cs
-
2Assets/UIWidgets/painting/decoration_image.cs
-
39Assets/UIWidgets/painting/matrix_utils.cs
-
2Assets/UIWidgets/painting/text_painter.cs
-
4Assets/UIWidgets/rendering/box.cs
-
2Assets/UIWidgets/rendering/object.cs
-
4Assets/UIWidgets/rendering/proxy_box.cs
-
6Assets/UIWidgets/rendering/viewport.cs
-
2Assets/UIWidgets/ui/compositing.cs
-
7Assets/UIWidgets/ui/geometry.cs
-
53Assets/UIWidgets/ui/painting/canvas.cs
-
166Assets/UIWidgets/ui/painting/canvas_impl.cs
-
9Assets/UIWidgets/ui/painting/draw_cmd.cs
-
21Assets/UIWidgets/ui/painting/image.cs
-
10Assets/UIWidgets/ui/painting/picture.cs
-
7Assets/UIWidgets/ui/txt/paragraph.cs
-
112Assets/UIWidgets/flow/matrix_decomposition.cs
-
3Assets/UIWidgets/flow/matrix_decomposition.cs.meta
-
232Assets/UIWidgets/flow/raster_cache.cs
-
3Assets/UIWidgets/flow/raster_cache.cs.meta
|
|||
using UnityEngine; |
|||
|
|||
namespace UIWidgets.flow { |
|||
public class MatrixDecomposition { |
|||
public MatrixDecomposition(Matrix4x4 matrix) { |
|||
if (matrix[3, 3] == 0) { |
|||
return; |
|||
} |
|||
|
|||
for (int i = 0; i < 4; i++) { |
|||
for (int j = 0; j < 4; j++) { |
|||
matrix[j, i] /= matrix[3, 3]; |
|||
} |
|||
} |
|||
|
|||
Matrix4x4 perpectiveMatrix = matrix; |
|||
for (int i = 0; i < 3; i++) { |
|||
perpectiveMatrix[3, i] = 0; |
|||
} |
|||
|
|||
perpectiveMatrix[3, 3] = 1; |
|||
|
|||
|
|||
if (perpectiveMatrix.determinant == 0) { |
|||
return; |
|||
} |
|||
|
|||
if (matrix[3, 0] != 0 || matrix[3, 1] != 0 || matrix[3, 2] != 0) { |
|||
Vector4 rightHandSide = new Vector4(matrix[3, 0], matrix[3, 1], matrix[3, 2], matrix[3, 3]); |
|||
this.perspective = perpectiveMatrix.inverse.transpose * rightHandSide; |
|||
|
|||
matrix[3, 0] = 0; |
|||
matrix[3, 1] = 0; |
|||
matrix[3, 2] = 0; |
|||
matrix[3, 3] = 1; |
|||
} |
|||
|
|||
this.translation = new Vector3(matrix[0, 3], matrix[1, 3], matrix[2, 3]); |
|||
|
|||
matrix[0, 3] = 0; |
|||
matrix[1, 3] = 0; |
|||
matrix[2, 3] = 0; |
|||
|
|||
Vector3[] row = new Vector3[3]; |
|||
for (int i = 0; i < 3; i++) { |
|||
row[i] = matrix.GetRow(i); |
|||
} |
|||
|
|||
this.scale.x = row[0].magnitude; |
|||
row[0] = row[0].normalized; |
|||
|
|||
this.shear.x = Vector3.Dot(row[0], row[1]); |
|||
row[1] += row[0] * -this.shear.x; |
|||
|
|||
this.scale.y = row[1].magnitude; |
|||
row[1] = row[1].normalized; |
|||
this.shear.x /= this.scale.y; |
|||
|
|||
this.shear.y = Vector3.Dot(row[0], row[2]); |
|||
row[2] += row[0] * -this.shear.y; |
|||
|
|||
this.shear.z = Vector3.Dot(row[1], row[2]); |
|||
row[2] += row[1] * -this.shear.z; |
|||
|
|||
this.scale.z = row[2].magnitude; |
|||
row[2] = row[2].normalized; |
|||
|
|||
this.shear.y /= this.scale.z; |
|||
this.shear.z /= this.scale.z; |
|||
|
|||
if (Vector3.Dot(row[0], Vector3.Cross(row[1], row[2])) < 0) { |
|||
this.scale.x *= -1; |
|||
this.scale.y *= -1; |
|||
this.scale.z *= -1; |
|||
|
|||
for (int i = 0; i < 3; i++) { |
|||
row[i].x *= -1; |
|||
row[i].y *= -1; |
|||
row[i].z *= -1; |
|||
} |
|||
} |
|||
|
|||
this.rotation = new Vector4( |
|||
0.5f * Mathf.Sqrt(Mathf.Max(1.0f + row[0].x - row[1].y - row[2].z, 0.0f)), |
|||
0.5f * Mathf.Sqrt(Mathf.Max(1.0f - row[0].x + row[1].y - row[2].z, 0.0f)), |
|||
0.5f * Mathf.Sqrt(Mathf.Max(1.0f - row[0].x - row[1].y + row[2].z, 0.0f)), |
|||
0.5f * Mathf.Sqrt(Mathf.Max(1.0f + row[0].x + row[1].y + row[2].z, 0.0f))); |
|||
|
|||
if (row[2].y > row[1].z) { |
|||
this.rotation.x = -this.rotation.x; |
|||
} |
|||
|
|||
if (row[0].z > row[2].x) { |
|||
this.rotation.y = -this.rotation.y; |
|||
} |
|||
|
|||
if (row[1].x > row[0].y) { |
|||
this.rotation.z = -this.rotation.z; |
|||
} |
|||
|
|||
this.valid = true; |
|||
} |
|||
|
|||
|
|||
public readonly bool valid; |
|||
public readonly Vector3 translation; |
|||
public readonly Vector3 scale; |
|||
public readonly Vector3 shear; |
|||
public readonly Vector4 perspective; |
|||
public readonly Vector4 rotation; |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 215bc2db9a324b0d8a2980dade2db267 |
|||
timeCreated: 1538271597 |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using UIWidgets.foundation; |
|||
using UIWidgets.painting; |
|||
using UIWidgets.ui; |
|||
using UnityEditor; |
|||
using UnityEngine; |
|||
using Canvas = UIWidgets.ui.Canvas; |
|||
using Rect = UIWidgets.ui.Rect; |
|||
|
|||
namespace UIWidgets.flow { |
|||
public class RasterCacheResult { |
|||
public RasterCacheResult(Image image, Rect bounds) { |
|||
D.assert(image != null); |
|||
D.assert(bounds != null); |
|||
|
|||
this.image = image; |
|||
this.bounds = bounds; |
|||
} |
|||
|
|||
public readonly Image image; |
|||
|
|||
public readonly Rect bounds; |
|||
|
|||
public void draw(Canvas canvas) { |
|||
var bounds = canvas.getMatrix().transformRect(this.bounds).roundOut(); |
|||
|
|||
D.assert(() => { |
|||
var textureWidth = (int) Math.Ceiling( |
|||
bounds.width * EditorGUIUtility.pixelsPerPoint); // todo: use window.pixelsPerPoint;
|
|||
var textureHeight = (int) Math.Ceiling( |
|||
bounds.height * EditorGUIUtility.pixelsPerPoint); |
|||
|
|||
D.assert(this.image.width == textureWidth); |
|||
D.assert(this.image.height == textureHeight); |
|||
return true; |
|||
}); |
|||
|
|||
canvas.save(); |
|||
try { |
|||
canvas.setMatrix(Matrix4x4.identity); |
|||
canvas.drawImageRect(this.image, bounds); |
|||
} |
|||
finally { |
|||
canvas.restore(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
class _RasterCacheKey : IEquatable<_RasterCacheKey> { |
|||
internal _RasterCacheKey(Picture picture, ref Matrix4x4 matrix) { |
|||
D.assert(picture != null); |
|||
this.picture = picture; |
|||
this.matrix = matrix; |
|||
this.matrix.m03 = this.matrix.m03 - (int) this.matrix.m03; // x
|
|||
this.matrix.m13 = this.matrix.m13 - (int) this.matrix.m13; // y
|
|||
|
|||
D.assert(this.matrix.m03 == 0); |
|||
D.assert(this.matrix.m13 == 0); |
|||
} |
|||
|
|||
public readonly Picture picture; |
|||
|
|||
public readonly Matrix4x4 matrix; |
|||
|
|||
public bool Equals(_RasterCacheKey other) { |
|||
if (ReferenceEquals(null, other)) return false; |
|||
if (ReferenceEquals(this, other)) return true; |
|||
return this.picture.Equals(other.picture) && this.matrix.Equals(other.matrix); |
|||
} |
|||
|
|||
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 this.Equals((_RasterCacheKey) obj); |
|||
} |
|||
|
|||
public override int GetHashCode() { |
|||
unchecked { |
|||
return (this.picture.GetHashCode() * 397) ^ this.matrix.GetHashCode(); |
|||
} |
|||
} |
|||
|
|||
public static bool operator ==(_RasterCacheKey left, _RasterCacheKey right) { |
|||
return Equals(left, right); |
|||
} |
|||
|
|||
public static bool operator !=(_RasterCacheKey left, _RasterCacheKey right) { |
|||
return !Equals(left, right); |
|||
} |
|||
} |
|||
|
|||
class _RasterCacheEntry { |
|||
public bool usedThisFrame = false; |
|||
public int accessCount = 0; |
|||
public RasterCacheResult image; |
|||
} |
|||
|
|||
public class RasterCache { |
|||
public RasterCache(int threshold = 3) { |
|||
this.threshold = threshold; |
|||
this._cache = new Dictionary<_RasterCacheKey, _RasterCacheEntry>(); |
|||
} |
|||
|
|||
public readonly int threshold; |
|||
|
|||
readonly Dictionary<_RasterCacheKey, _RasterCacheEntry> _cache; |
|||
|
|||
public RasterCacheResult getPrerolledImage( |
|||
Picture picture, ref Matrix4x4 transform, bool isComplex, bool willChange) { |
|||
if (this.threshold == 0) { |
|||
return null; |
|||
} |
|||
|
|||
if (!_isPictureWorthRasterizing(picture, isComplex, willChange)) { |
|||
return null; |
|||
} |
|||
|
|||
if (transform.m33 == 0 || transform.determinant == 0) { |
|||
return null; |
|||
} |
|||
|
|||
_RasterCacheKey cacheKey = new _RasterCacheKey(picture, ref transform); |
|||
|
|||
var entry = this._cache.putIfAbsent(cacheKey, () => new _RasterCacheEntry()); |
|||
|
|||
entry.accessCount = (entry.accessCount + 1).clamp(0, this.threshold); |
|||
entry.usedThisFrame = true; |
|||
|
|||
if (entry.accessCount < this.threshold) { |
|||
return null; |
|||
} |
|||
|
|||
if (entry.image == null) { |
|||
entry.image = this._rasterizePicture(picture, ref transform); |
|||
} |
|||
|
|||
return entry.image; |
|||
} |
|||
|
|||
static bool _isPictureWorthRasterizing(Picture picture, |
|||
bool isComplex, bool willChange) { |
|||
if (willChange) { |
|||
return false; |
|||
} |
|||
|
|||
if (!_canRasterizePicture(picture)) { |
|||
return false; |
|||
} |
|||
|
|||
if (isComplex) { |
|||
return true; |
|||
} |
|||
|
|||
return picture.drawCmds.Count > 10; |
|||
} |
|||
|
|||
static bool _canRasterizePicture(Picture picture) { |
|||
if (picture == null) { |
|||
return false; |
|||
} |
|||
|
|||
var bounds = picture.paintBounds; |
|||
if (bounds.isEmpty) { |
|||
return false; |
|||
} |
|||
|
|||
if (!bounds.isFinite) { |
|||
return false; |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
RasterCacheResult _rasterizePicture(Picture picture, ref Matrix4x4 transform) { |
|||
var bounds = transform.transformRect(picture.paintBounds).roundOut(); |
|||
|
|||
var textureWidth = (int) Math.Ceiling( |
|||
bounds.width * EditorGUIUtility.pixelsPerPoint); // todo: use window.pixelsPerPoint;
|
|||
var textureHeight = (int) Math.Ceiling( |
|||
bounds.height * EditorGUIUtility.pixelsPerPoint); |
|||
|
|||
var texture = RenderTexture.GetTemporary( |
|||
textureWidth, textureHeight, 32, |
|||
RenderTextureFormat.ARGB32, RenderTextureReadWrite.sRGB); |
|||
|
|||
var oldTexture = RenderTexture.active; |
|||
RenderTexture.active = texture; |
|||
|
|||
GL.PushMatrix(); |
|||
GL.LoadPixelMatrix((float) bounds.left, (float) bounds.right, (float) bounds.bottom, (float) bounds.top); |
|||
GL.Clear(true, true, new UnityEngine.Color(0, 0, 0, 0)); |
|||
|
|||
try { |
|||
var canvas = new CanvasImpl(); |
|||
canvas.concat(transform); |
|||
canvas.drawPicture(picture); |
|||
|
|||
Texture2D tex = new Texture2D(textureWidth, textureHeight, TextureFormat.ARGB32, false); |
|||
tex.ReadPixels(new UnityEngine.Rect(0, 0, textureWidth, textureHeight), 0, 0, false); |
|||
tex.Apply(); |
|||
|
|||
return new RasterCacheResult(new Image(texture: tex), picture.paintBounds); |
|||
} |
|||
finally { |
|||
GL.PopMatrix(); |
|||
RenderTexture.active = oldTexture; |
|||
RenderTexture.ReleaseTemporary(texture); |
|||
} |
|||
} |
|||
|
|||
public void sweepAfterFrame() { |
|||
var dead = new List<KeyValuePair<_RasterCacheKey, _RasterCacheEntry>>(); |
|||
foreach (var entry in this._cache) { |
|||
if (!entry.Value.usedThisFrame) { |
|||
dead.Add(entry); |
|||
} else { |
|||
entry.Value.usedThisFrame = false; |
|||
} |
|||
} |
|||
|
|||
foreach (var entry in dead) { |
|||
this._cache.Remove(entry.Key); |
|||
} |
|||
} |
|||
|
|||
public void clear() { |
|||
this._cache.Clear(); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: b65b634b39ec47fe9ae136d615b198c0 |
|||
timeCreated: 1538204893 |
撰写
预览
正在加载...
取消
保存
Reference in new issue