Yuncong Zhang
5 年前
当前提交
eaec41e9
共有 146 个文件被更改,包括 7487 次插入 和 367 次删除
-
1Runtime/editor/rasterizer.cs
-
3Runtime/rendering/view.cs
-
16Runtime/ui/matrix.cs
-
28Runtime/ui/painting/path.cs
-
54Runtime/ui/painting/shader.cs
-
101Runtime/ui/painting/shadow_utils.cs
-
159Runtime/ui/painting/txt/mesh_generator.cs
-
2Runtime/ui/painting/txt/text_blob.cs
-
2Runtime/widgets/binding.cs
-
2Samples/UIWidgetSample/NavigationSample.cs
-
9Samples/UIWidgetSample/TextInput.unity
-
240Runtime/ui/renderer/cmdbufferCanvas/rendering/canvas_shader.cs
-
174Runtime/ui/renderer/cmdbufferCanvas/rendering/canvas_clip.cs
-
2Runtime/ui/renderer/compositeCanvas/compositing.cs
-
3Runtime/ui/renderer/compositeCanvas/flow/clip_path_layer.cs
-
7Runtime/ui/renderer/compositeCanvas/flow/clip_rect_layer.cs
-
5Runtime/ui/renderer/compositeCanvas/flow/clip_rrect_layer.cs
-
5Runtime/ui/renderer/compositeCanvas/flow/container_layer.cs
-
8Runtime/ui/renderer/compositeCanvas/flow/transform_layer.cs
-
5Runtime/ui/renderer/compositeCanvas/flow/texture_layer.cs
-
5Runtime/ui/renderer/compositeCanvas/flow/backdrop_filter_layer.cs
-
21Runtime/ui/renderer/compositeCanvas/flow/opacity_layer.cs
-
15Runtime/ui/renderer/compositeCanvas/flow/picture_layer.cs
-
2Runtime/ui/renderer/compositeCanvas/flow/layer_tree.cs
-
46Runtime/ui/renderer/compositeCanvas/flow/physical_shape_layer.cs
-
1Runtime/ui/renderer/compositeCanvas/flow/raster_cache.cs
-
3Runtime/ui/renderer/compositeCanvas/flow/instrumentation.cs
-
65Runtime/ui/painting/utils.cs
-
11Runtime/ui/painting/utils.cs.meta
-
8Runtime/ui/renderer.meta
-
8Runtime/ui/renderer/allocator.meta
-
11Runtime/ui/renderer/allocator/generic_list.cs.meta
-
11Runtime/ui/renderer/allocator/debug.cs.meta
-
11Runtime/ui/renderer/allocator/pool_object.cs.meta
-
11Runtime/ui/renderer/allocator/uipath_cache_manager.cs.meta
-
78Runtime/ui/renderer/allocator/debug.cs
-
51Runtime/ui/renderer/allocator/generic_list.cs
-
106Runtime/ui/renderer/allocator/pool_object.cs
-
54Runtime/ui/renderer/allocator/uipath_cache_manager.cs
-
8Runtime/ui/renderer/cmdbufferCanvas.meta
-
27Runtime/ui/renderer/cmdbufferCanvas/command_buffer_canvas.cs
-
11Runtime/ui/renderer/cmdbufferCanvas/command_buffer_canvas.cs.meta
-
8Runtime/ui/renderer/cmdbufferCanvas/rendering.meta
-
11Runtime/ui/renderer/cmdbufferCanvas/rendering/canvas_clip.cs.meta
-
1001Runtime/ui/renderer/cmdbufferCanvas/rendering/canvas_impl.cs
-
11Runtime/ui/renderer/cmdbufferCanvas/rendering/canvas_impl.cs.meta
-
11Runtime/ui/renderer/cmdbufferCanvas/rendering/canvas_shader.cs.meta
-
39Runtime/ui/renderer/cmdbufferCanvas/rendering/canvas_shader_utils.cs
-
11Runtime/ui/renderer/cmdbufferCanvas/rendering/canvas_shader_utils.cs.meta
-
232Runtime/ui/renderer/cmdbufferCanvas/rendering/canvas_utils.cs
-
11Runtime/ui/renderer/cmdbufferCanvas/rendering/canvas_utils.cs.meta
-
100Runtime/ui/renderer/cmdbufferCanvas/rendering/render_cmd.cs
-
11Runtime/ui/renderer/cmdbufferCanvas/rendering/render_cmd.cs.meta
-
141Runtime/ui/renderer/cmdbufferCanvas/rendering/render_layer.cs
-
11Runtime/ui/renderer/cmdbufferCanvas/rendering/render_layer.cs.meta
-
8Runtime/ui/renderer/common.meta
-
308Runtime/ui/renderer/common/base_canvas.cs
-
11Runtime/ui/renderer/common/base_canvas.cs.meta
-
80Runtime/ui/renderer/common/color.cs
-
11Runtime/ui/renderer/common/color.cs.meta
-
415Runtime/ui/renderer/common/draw_cmd.cs
-
11Runtime/ui/renderer/common/draw_cmd.cs.meta
-
8Runtime/ui/renderer/common/geometry.meta
-
11Runtime/ui/renderer/common/geometry/offset.cs.meta
-
11Runtime/ui/renderer/common/geometry/rect.cs.meta
-
8Runtime/ui/renderer/common/geometry/matrix.meta
-
11Runtime/ui/renderer/common/geometry/mesh_mesh.cs.meta
-
8Runtime/ui/renderer/common/geometry/path.meta
-
11Runtime/ui/renderer/common/geometry/matrix/ui_matrix.cs.meta
-
11Runtime/ui/renderer/common/geometry/matrix/ui_matrix_utils.cs.meta
-
761Runtime/ui/renderer/common/geometry/matrix/ui_matrix.cs
-
572Runtime/ui/renderer/common/geometry/matrix/ui_matrix_utils.cs
-
147Runtime/ui/renderer/common/geometry/mesh_mesh.cs
-
25Runtime/ui/renderer/common/geometry/offset.cs
-
11Runtime/ui/renderer/common/geometry/path/path.cs.meta
-
11Runtime/ui/renderer/common/geometry/path/path_cache.cs.meta
-
11Runtime/ui/renderer/common/geometry/path/path_utils.cs.meta
-
11Runtime/ui/renderer/common/geometry/path/tessellation_generator.cs.meta
-
422Runtime/ui/renderer/common/geometry/path/path.cs
-
563Runtime/ui/renderer/common/geometry/path/path_cache.cs
-
323Runtime/ui/renderer/common/geometry/path/path_utils.cs
-
261Runtime/ui/renderer/common/geometry/path/tessellation_generator.cs
-
227Runtime/ui/renderer/common/geometry/rect.cs
-
171Runtime/ui/renderer/common/paint.cs
-
11Runtime/ui/renderer/common/paint.cs.meta
-
322Runtime/ui/renderer/common/picture.cs
-
11Runtime/ui/renderer/common/picture.cs.meta
-
53Runtime/ui/renderer/common/utils.cs
-
11Runtime/ui/renderer/common/utils.cs.meta
-
8Runtime/ui/renderer/compositeCanvas.meta
-
11Runtime/ui/renderer/compositeCanvas/compositing.cs.meta
|
|||
using UnityEngine; |
|||
|
|||
namespace Unity.UIWidgets.ui { |
|||
static class XformUtils { |
|||
public static float getAverageScale(Matrix3 matrix) { |
|||
return (getScaleX(matrix) + getScaleY(matrix)) * 0.5f; |
|||
} |
|||
|
|||
public static float getMaxScale(Matrix3 matrix) { |
|||
return Mathf.Max(getScaleX(matrix), getScaleY(matrix)); |
|||
} |
|||
|
|||
public static float getScaleX(Matrix3 matrix) { |
|||
// ignore perspective parameters for now.
|
|||
if (matrix.isIdentity()) { |
|||
return 1.0f; |
|||
} |
|||
|
|||
if (matrix.getSkewY() == 0) { |
|||
return matrix.getScaleX(); |
|||
} |
|||
|
|||
var x = matrix.getScaleX(); |
|||
var y = matrix.getSkewY(); |
|||
|
|||
return Mathf.Sqrt(x * x + y * y); |
|||
} |
|||
|
|||
public static float getScaleY(Matrix3 matrix) { |
|||
// ignore perspective parameters for now.
|
|||
if (matrix.isIdentity()) { |
|||
return 1.0f; |
|||
} |
|||
|
|||
if (matrix.getSkewX() == 0) { |
|||
return matrix.getScaleY(); |
|||
} |
|||
|
|||
var x = matrix.getSkewX(); |
|||
var y = matrix.getScaleY(); |
|||
|
|||
return Mathf.Sqrt(x * x + y * y); |
|||
} |
|||
|
|||
public static float getScale(Matrix3 matrix) { |
|||
var scaleX = getScaleX(matrix); |
|||
var scaleY = getScaleY(matrix); |
|||
|
|||
if (scaleX == 1.0) { |
|||
return scaleY; |
|||
} |
|||
|
|||
if (scaleY == 1.0) { |
|||
return scaleX; |
|||
} |
|||
|
|||
// geometric mean of len0 and len1.
|
|||
return Mathf.Sqrt(scaleX * scaleY); |
|||
} |
|||
|
|||
public static float mapRadius(Matrix3 matrix, float radius) { |
|||
return getScale(matrix) * radius; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: c38089235fcab4985b83cb72b84a9dab |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 959d5ec4ab46f4b269229c6f3872cb77 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 20d8e92bcce4a47289010555ccdb9541 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: eb4160872e9bd4c979becf5c8a3456a4 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 43af7efe5253d4455b10ffc9e5563b02 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 10ca9bb0174ca4dc4a01e1b2f2b45f3d |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 0bdd45ffa400d4d3d815b21cb97b9d66 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System.Collections.Generic; |
|||
using UnityEngine; |
|||
|
|||
namespace Unity.UIWidgets.ui { |
|||
class DebugMeta { |
|||
public string objName; |
|||
public int watermark; |
|||
public int prev_watermark; |
|||
public int borrowed; |
|||
public int allocated; |
|||
|
|||
public void onAlloc(int allocatedCount) { |
|||
this.borrowed++; |
|||
this.watermark = this.borrowed > this.watermark ? this.borrowed : this.watermark; |
|||
this.allocated = allocatedCount; |
|||
} |
|||
|
|||
public void onRelease(int allocatedCount) { |
|||
this.borrowed--; |
|||
this.allocated = allocatedCount; |
|||
} |
|||
} |
|||
|
|||
public static class AllocDebugger { |
|||
public const bool enableDebugging = false; |
|||
|
|||
static int allocCount = 0; |
|||
|
|||
static readonly Dictionary<int, DebugMeta> debugInfos = new Dictionary<int, DebugMeta>(); |
|||
|
|||
public static void onFrameEnd() { |
|||
if (!enableDebugging) { |
|||
return; |
|||
} |
|||
|
|||
allocCount++; |
|||
if (allocCount >= 120) { |
|||
allocCount = 0; |
|||
|
|||
string debugInfo = "Alloc Stats: "; |
|||
foreach (var key in debugInfos.Keys) { |
|||
var item = debugInfos[key]; |
|||
if (item.watermark <= item.prev_watermark) { |
|||
debugInfo += "|" + item.objName + " = " + item.watermark + "," + item.borrowed + "|"; |
|||
continue; |
|||
} |
|||
|
|||
item.prev_watermark = item.watermark; |
|||
debugInfo += "|" + item.objName + " = " + item.watermark + "," + item.borrowed + "|"; |
|||
} |
|||
|
|||
if (debugInfo == "Alloc Stats: ") { |
|||
return; |
|||
} |
|||
|
|||
Debug.Log(debugInfo); |
|||
} |
|||
} |
|||
|
|||
public static void onAlloc(int objKey, string objName, int allocatedCount) { |
|||
if (!debugInfos.ContainsKey(objKey)) { |
|||
debugInfos[objKey] = new DebugMeta { |
|||
objName = objName, |
|||
watermark = 0, |
|||
borrowed = 0, |
|||
allocated = 0 |
|||
}; |
|||
} |
|||
|
|||
debugInfos[objKey].onAlloc(allocatedCount); |
|||
} |
|||
|
|||
public static void onRelease(int objKey, string objName, int allocatedCount) { |
|||
Debug.Assert(debugInfos.ContainsKey(objKey), "An unregistered pool object cannot be released"); |
|||
debugInfos[objKey].onRelease(allocatedCount); |
|||
} |
|||
} |
|||
} |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace Unity.UIWidgets.ui { |
|||
public class uiList<T> : PoolObject { |
|||
List<T> list; |
|||
|
|||
public override void setup() { |
|||
base.setup(); |
|||
this.list = this.list ?? new List<T>(128); |
|||
} |
|||
|
|||
public uiList() { |
|||
} |
|||
|
|||
public List<T> data { |
|||
get { return this.list; } |
|||
} |
|||
|
|||
public void Add(T item) { |
|||
this.list.Add(item); |
|||
} |
|||
|
|||
public void AddRange(IList<T> items) { |
|||
this.list.AddRange(items); |
|||
} |
|||
|
|||
public void Clear() { |
|||
this.list.Clear(); |
|||
} |
|||
|
|||
public override void clear() { |
|||
//clear the list immediately to avoid potential memory leak
|
|||
//otherwise, we may clear it in Setup() for lazy update
|
|||
this.list.Clear(); |
|||
} |
|||
|
|||
public int Count { |
|||
get { return this.list.Count; } |
|||
} |
|||
|
|||
public void SetCapacity(int capacity) { |
|||
this.list.Capacity = Math.Max(capacity, this.list.Capacity); |
|||
} |
|||
|
|||
public T this[int index] { |
|||
get { return this.list[index]; } |
|||
set { this.list[index] = value; } |
|||
} |
|||
} |
|||
} |
|
|||
using System.Collections.Generic; |
|||
using System.Diagnostics; |
|||
|
|||
namespace Unity.UIWidgets.ui { |
|||
public abstract class PoolObject { |
|||
public bool activated_flag; |
|||
|
|||
public virtual void setup() { |
|||
} |
|||
|
|||
public virtual void clear() { |
|||
} |
|||
} |
|||
|
|||
public static class ObjectPool<TObject> where TObject : PoolObject, new() { |
|||
static readonly Stack<TObject> pool = new Stack<TObject>(); |
|||
|
|||
const int POOL_MAX_SIZE = 256; |
|||
const int POOL_BATCH_SIZE = 128; |
|||
|
|||
static int allocatedCount = 0; |
|||
|
|||
public static TObject alloc() { |
|||
if (pool.Count == 0) { |
|||
for (int i = 0; i < POOL_BATCH_SIZE; i++) { |
|||
var obj = new TObject(); |
|||
pool.Push(obj); |
|||
} |
|||
|
|||
allocatedCount += POOL_BATCH_SIZE; |
|||
} |
|||
|
|||
var ret = pool.Pop(); |
|||
ret.setup(); |
|||
|
|||
if (AllocDebugger.enableDebugging) { |
|||
AllocDebugger.onAlloc(debugKey, debugName, allocatedCount); |
|||
ret.activated_flag = true; |
|||
} |
|||
|
|||
return ret; |
|||
} |
|||
|
|||
public static void release(TObject obj) { |
|||
if (obj == null) { |
|||
return; |
|||
} |
|||
|
|||
if (AllocDebugger.enableDebugging) { |
|||
if (!obj.activated_flag) { |
|||
Debug.Assert(false, "an item has been recycled more than once !"); |
|||
} |
|||
|
|||
obj.activated_flag = false; |
|||
|
|||
AllocDebugger.onRelease(debugKey, debugName, allocatedCount); |
|||
} |
|||
|
|||
obj.clear(); |
|||
if (pool.Count > POOL_MAX_SIZE) { |
|||
allocatedCount--; |
|||
//there are enough items in the pool
|
|||
//just release the obj to GC
|
|||
return; |
|||
} |
|||
|
|||
pool.Push(obj); |
|||
} |
|||
|
|||
//For debugger
|
|||
static bool _debugInfoReady = false; |
|||
static string _debugName = null; |
|||
|
|||
static void _generateDebugInfo() { |
|||
var ctype = typeof(TObject); |
|||
_debugName = ctype.ToString(); |
|||
_debugKey = ctype.GetHashCode(); |
|||
|
|||
_debugInfoReady = true; |
|||
} |
|||
|
|||
public static string debugName { |
|||
get { |
|||
if (_debugInfoReady) { |
|||
return _debugName; |
|||
} |
|||
|
|||
_generateDebugInfo(); |
|||
return _debugName; |
|||
} |
|||
} |
|||
|
|||
static int _debugKey = -1; |
|||
|
|||
public static int debugKey { |
|||
get { |
|||
if (_debugInfoReady) { |
|||
return _debugKey; |
|||
} |
|||
|
|||
_generateDebugInfo(); |
|||
return _debugKey; |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
using System.Collections.Generic; |
|||
|
|||
namespace Unity.UIWidgets.ui { |
|||
public static class uiPathCacheManager { |
|||
static readonly Dictionary<uint, uiPath> cache = new Dictionary<uint, uiPath>(256); |
|||
|
|||
//remove unused cache items every 1 frame
|
|||
static readonly Dictionary<uint, bool> touched = new Dictionary<uint, bool>(256); |
|||
|
|||
static float curFrame; |
|||
|
|||
static readonly List<uint> untouched = new List<uint>(); |
|||
|
|||
public static void tickNextFrame() { |
|||
untouched.Clear(); |
|||
foreach (var key in cache.Keys) { |
|||
if (!touched.ContainsKey(key)) { |
|||
untouched.Add(key); |
|||
} |
|||
} |
|||
|
|||
foreach (var key in untouched) { |
|||
ObjectPool<uiPath>.release(cache[key]); |
|||
cache.Remove(key); |
|||
} |
|||
|
|||
touched.Clear(); |
|||
} |
|||
|
|||
public static void putToCache(uiPath uipath) { |
|||
if (!uipath.needCache) { |
|||
ObjectPool<uiPath>.release(uipath); |
|||
} |
|||
} |
|||
|
|||
public static bool tryGetUiPath(uint pathKey, out uiPath outpath) { |
|||
if (cache.ContainsKey(pathKey)) { |
|||
touched[pathKey] = true; |
|||
outpath = cache[pathKey]; |
|||
return true; |
|||
} |
|||
|
|||
var uipath = uiPath.create(); |
|||
cache[pathKey] = uipath; |
|||
touched[pathKey] = true; |
|||
|
|||
uipath.needCache = true; |
|||
uipath.pathKey = pathKey; |
|||
|
|||
outpath = uipath; |
|||
return false; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 59ae365032f57410abbcb34d28138edf |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using UnityEngine; |
|||
|
|||
namespace Unity.UIWidgets.ui { |
|||
public class CommandBufferCanvas : uiRecorderCanvas { |
|||
readonly PictureFlusher _flusher; |
|||
|
|||
public CommandBufferCanvas(RenderTexture renderTexture, float devicePixelRatio, MeshPool meshPool) |
|||
: base(new uiPictureRecorder()) { |
|||
this._flusher = new PictureFlusher(renderTexture, devicePixelRatio, meshPool); |
|||
} |
|||
|
|||
public override float getDevicePixelRatio() { |
|||
return this._flusher.getDevicePixelRatio(); |
|||
} |
|||
|
|||
public override void flush() { |
|||
var picture = this._recorder.endRecording(); |
|||
this._flusher.flush(picture); |
|||
this._recorder.reset(); |
|||
ObjectPool<uiPicture>.release(picture); |
|||
} |
|||
|
|||
public void dispose() { |
|||
this._flusher.dispose(); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: fe2bf6f68e1cf499ab843e5c1d9b8649 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: d6d93fe2039d44a6ca78658b1e59517d |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: aeb41cec5a3df49a8bfb3d548f3ad93d |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
1001
Runtime/ui/renderer/cmdbufferCanvas/rendering/canvas_impl.cs
文件差异内容过多而无法显示
查看文件
文件差异内容过多而无法显示
查看文件
|
|||
fileFormatVersion: 2 |
|||
guid: 4819b50eb486840f29658385ccd9d198 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 7c11a48c082af4e16a8ec27bed8aafbe |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using UnityEngine; |
|||
|
|||
namespace Unity.UIWidgets.ui { |
|||
public class MaterialPropertyBlockWrapper : PoolObject { |
|||
public readonly MaterialPropertyBlock mpb; |
|||
|
|||
public MaterialPropertyBlockWrapper() { |
|||
this.mpb = new MaterialPropertyBlock(); |
|||
} |
|||
|
|||
public override void clear() { |
|||
this.mpb.Clear(); |
|||
} |
|||
|
|||
public void SetVector(int mid, Vector4 vec) { |
|||
this.mpb.SetVector(mid, vec); |
|||
} |
|||
|
|||
public void SetFloat(int mid, float value) { |
|||
this.mpb.SetFloat(mid, value); |
|||
} |
|||
|
|||
public void SetMatrix(int mid, Matrix4x4 mat) { |
|||
this.mpb.SetMatrix(mid, mat); |
|||
} |
|||
|
|||
public void SetTexture(int mid, Texture texture) { |
|||
this.mpb.SetTexture(mid, texture); |
|||
} |
|||
|
|||
public void SetInt(int mid, int value) { |
|||
this.mpb.SetInt(mid, value); |
|||
} |
|||
|
|||
public void SetFloatArray(int mid, float[] array) { |
|||
this.mpb.SetFloatArray(mid, array); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: e765af15bd449426d96889c83da3f18f |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System.Collections.Generic; |
|||
using Unity.UIWidgets.foundation; |
|||
using UnityEngine; |
|||
|
|||
namespace Unity.UIWidgets.ui { |
|||
static class BlurUtils { |
|||
static readonly Dictionary<int, float[]> _gaussianKernels |
|||
= new Dictionary<int, float[]>(); |
|||
|
|||
static float[] calculateKernel(float _cur_gaussian_sigma, int _cur_width, int _cur_radius) { |
|||
var kernel = new float[25]; |
|||
float twoSigmaSqrd = 2.0f * _cur_gaussian_sigma * _cur_gaussian_sigma; |
|||
|
|||
if (ScalarUtils.ScalarNearlyZero(twoSigmaSqrd)) { |
|||
for (int i = 0; i < _cur_width; ++i) { |
|||
kernel[i] = 0.0f; |
|||
} |
|||
|
|||
return kernel; |
|||
} |
|||
|
|||
float denom = 1.0f / twoSigmaSqrd; |
|||
|
|||
float sum = 0.0f; |
|||
for (int i = 0; i < _cur_width; ++i) { |
|||
float x = i - _cur_radius; |
|||
// Note that the constant term (1/(sqrt(2*pi*sigma^2)) of the Gaussian
|
|||
// is dropped here, since we renormalize the kernel below.
|
|||
kernel[i] = Mathf.Exp(-x * x * denom); |
|||
sum += kernel[i]; |
|||
} |
|||
|
|||
// Normalize the kernel
|
|||
float scale = 1.0f / sum; |
|||
for (int i = 0; i < _cur_width; ++i) { |
|||
kernel[i] *= scale; |
|||
} |
|||
|
|||
_cur_gaussian_sigma = -1; |
|||
_cur_radius = -1; |
|||
|
|||
return kernel; |
|||
} |
|||
|
|||
public static float[] get1DGaussianKernel(float gaussianSigma, int radius) { |
|||
var width = 2 * radius + 1; |
|||
D.assert(width <= 25); |
|||
|
|||
//round gaussian sigma to 0.1
|
|||
gaussianSigma = Mathf.Round(gaussianSigma * 10) / 10f; |
|||
//assume radius < 10000
|
|||
D.assert(radius < 10000); |
|||
|
|||
int key = (int) (gaussianSigma * 1000000) + radius; |
|||
|
|||
float[] value; |
|||
if (_gaussianKernels.TryGetValue(key, out value)) { |
|||
return value; |
|||
} |
|||
|
|||
value = calculateKernel(gaussianSigma, width, radius); |
|||
_gaussianKernels[key] = value; |
|||
return value; |
|||
} |
|||
|
|||
public static float adjustSigma(float sigma, out int scaleFactor, out int radius) { |
|||
scaleFactor = 1; |
|||
|
|||
const int maxTextureSize = 16384; |
|||
const float MAX_BLUR_SIGMA = 4.0f; |
|||
|
|||
while (sigma > MAX_BLUR_SIGMA) { |
|||
scaleFactor *= 2; |
|||
sigma *= 0.5f; |
|||
|
|||
if (scaleFactor > maxTextureSize) { |
|||
scaleFactor = maxTextureSize; |
|||
sigma = MAX_BLUR_SIGMA; |
|||
} |
|||
} |
|||
|
|||
radius = Mathf.CeilToInt(sigma * 3.0f); |
|||
D.assert(radius <= 3 * MAX_BLUR_SIGMA); |
|||
return sigma; |
|||
} |
|||
} |
|||
|
|||
static class ImageMeshGenerator { |
|||
static readonly List<int> _imageTriangles = new List<int>(12) { |
|||
0, 1, 2, 0, 2, 1, |
|||
0, 2, 3, 0, 3, 2, |
|||
}; |
|||
|
|||
static readonly List<int> _imageNineTriangles = new List<int> { |
|||
0, 4, 1, 1, 4, 5, |
|||
0, 1, 4, 1, 5, 4, |
|||
1, 5, 2, 2, 5, 6, |
|||
1, 2, 5, 2, 6, 5, |
|||
2, 6, 3, 3, 6, 7, |
|||
2, 3, 6, 3, 7, 6, |
|||
4, 8, 5, 5, 8, 9, |
|||
4, 5, 8, 5, 9, 8, |
|||
5, 9, 6, 6, 9, 10, |
|||
5, 6, 9, 6, 10, 9, |
|||
6, 10, 7, 7, 10, 11, |
|||
6, 7, 10, 7, 11, 10, |
|||
8, 12, 9, 9, 12, 13, |
|||
8, 9, 12, 9, 13, 12, |
|||
9, 13, 10, 10, 13, 14, |
|||
9, 10, 13, 10, 14, 13, |
|||
10, 14, 11, 11, 14, 15, |
|||
10, 11, 14, 11, 15, 14, |
|||
}; |
|||
|
|||
public static uiMeshMesh imageMesh(uiMatrix3? matrix, |
|||
uiOffset srcTL, uiOffset srcBL, uiOffset srcBR, uiOffset srcTR, |
|||
uiRect dst) { |
|||
var vertices = ObjectPool<uiList<Vector3>>.alloc(); |
|||
vertices.SetCapacity(4); |
|||
|
|||
var uv = ObjectPool<uiList<Vector2>>.alloc(); |
|||
uv.SetCapacity(4); |
|||
|
|||
vertices.Add(new Vector2(dst.left, dst.top)); |
|||
uv.Add(new Vector2(srcTL.dx, 1.0f - srcTL.dy)); |
|||
vertices.Add(new Vector2(dst.left, dst.bottom)); |
|||
uv.Add(new Vector2(srcBL.dx, 1.0f - srcBL.dy)); |
|||
vertices.Add(new Vector2(dst.right, dst.bottom)); |
|||
uv.Add(new Vector2(srcBR.dx, 1.0f - srcBR.dy)); |
|||
vertices.Add(new Vector2(dst.right, dst.top)); |
|||
uv.Add(new Vector2(srcTR.dx, 1.0f - srcTR.dy)); |
|||
|
|||
var _triangles = ObjectPool<uiList<int>>.alloc(); |
|||
_triangles.AddRange(_imageTriangles); |
|||
|
|||
return uiMeshMesh.create(matrix, vertices, _triangles, uv); |
|||
} |
|||
|
|||
public static uiMeshMesh imageMesh(uiMatrix3? matrix, uiRect src, uiRect dst) { |
|||
var vertices = ObjectPool<uiList<Vector3>>.alloc(); |
|||
vertices.SetCapacity(4); |
|||
|
|||
var uv = ObjectPool<uiList<Vector2>>.alloc(); |
|||
uv.SetCapacity(4); |
|||
|
|||
float uvx0 = src.left; |
|||
float uvx1 = src.right; |
|||
float uvy0 = 1.0f - src.top; |
|||
float uvy1 = 1.0f - src.bottom; |
|||
|
|||
vertices.Add(new Vector2(dst.left, dst.top)); |
|||
uv.Add(new Vector2(uvx0, uvy0)); |
|||
vertices.Add(new Vector2(dst.left, dst.bottom)); |
|||
uv.Add(new Vector2(uvx0, uvy1)); |
|||
vertices.Add(new Vector2(dst.right, dst.bottom)); |
|||
uv.Add(new Vector2(uvx1, uvy1)); |
|||
vertices.Add(new Vector2(dst.right, dst.top)); |
|||
uv.Add(new Vector2(uvx1, uvy0)); |
|||
|
|||
var _triangles = ObjectPool<uiList<int>>.alloc(); |
|||
_triangles.AddRange(_imageTriangles); |
|||
|
|||
return uiMeshMesh.create(matrix, vertices, _triangles, uv); |
|||
} |
|||
|
|||
public static uiMeshMesh imageNineMesh(uiMatrix3? matrix, uiRect src, uiRect center, int srcWidth, |
|||
int srcHeight, uiRect dst) { |
|||
float x0 = dst.left; |
|||
float x3 = dst.right; |
|||
float x1 = x0 + ((center.left - src.left) * srcWidth); |
|||
float x2 = x3 - ((src.right - center.right) * srcWidth); |
|||
|
|||
float y0 = dst.top; |
|||
float y3 = dst.bottom; |
|||
float y1 = y0 + ((center.top - src.top) * srcHeight); |
|||
float y2 = y3 - ((src.bottom - center.bottom) * srcHeight); |
|||
|
|||
float tx0 = src.left; |
|||
float tx1 = center.left; |
|||
float tx2 = center.right; |
|||
float tx3 = src.right; |
|||
float ty0 = 1 - src.top; |
|||
float ty1 = 1 - center.top; |
|||
float ty2 = 1 - center.bottom; |
|||
float ty3 = 1 - src.bottom; |
|||
|
|||
var vertices = ObjectPool<uiList<Vector3>>.alloc(); |
|||
vertices.SetCapacity(16); |
|||
|
|||
var uv = ObjectPool<uiList<Vector2>>.alloc(); |
|||
uv.SetCapacity(16); |
|||
|
|||
vertices.Add(new Vector2(x0, y0)); |
|||
uv.Add(new Vector2(tx0, ty0)); |
|||
vertices.Add(new Vector2(x1, y0)); |
|||
uv.Add(new Vector2(tx1, ty0)); |
|||
vertices.Add(new Vector2(x2, y0)); |
|||
uv.Add(new Vector2(tx2, ty0)); |
|||
vertices.Add(new Vector2(x3, y0)); |
|||
uv.Add(new Vector2(tx3, ty0)); |
|||
vertices.Add(new Vector2(x0, y1)); |
|||
uv.Add(new Vector2(tx0, ty1)); |
|||
vertices.Add(new Vector2(x1, y1)); |
|||
uv.Add(new Vector2(tx1, ty1)); |
|||
vertices.Add(new Vector2(x2, y1)); |
|||
uv.Add(new Vector2(tx2, ty1)); |
|||
vertices.Add(new Vector2(x3, y1)); |
|||
uv.Add(new Vector2(tx3, ty1)); |
|||
vertices.Add(new Vector2(x0, y2)); |
|||
uv.Add(new Vector2(tx0, ty2)); |
|||
vertices.Add(new Vector2(x1, y2)); |
|||
uv.Add(new Vector2(tx1, ty2)); |
|||
vertices.Add(new Vector2(x2, y2)); |
|||
uv.Add(new Vector2(tx2, ty2)); |
|||
vertices.Add(new Vector2(x3, y2)); |
|||
uv.Add(new Vector2(tx3, ty2)); |
|||
vertices.Add(new Vector2(x0, y3)); |
|||
uv.Add(new Vector2(tx0, ty3)); |
|||
vertices.Add(new Vector2(x1, y3)); |
|||
uv.Add(new Vector2(tx1, ty3)); |
|||
vertices.Add(new Vector2(x2, y3)); |
|||
uv.Add(new Vector2(tx2, ty3)); |
|||
vertices.Add(new Vector2(x3, y3)); |
|||
uv.Add(new Vector2(tx3, ty3)); |
|||
|
|||
var _triangles = ObjectPool<uiList<int>>.alloc(); |
|||
_triangles.AddRange(_imageNineTriangles); |
|||
|
|||
return uiMeshMesh.create(matrix, vertices, _triangles, uv); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 039549b55460f4773b43ddae683ddcd4 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using UnityEngine; |
|||
|
|||
namespace Unity.UIWidgets.ui { |
|||
public partial class PictureFlusher { |
|||
internal abstract class RenderCmd : PoolObject { |
|||
public abstract void release(); |
|||
} |
|||
|
|||
internal class CmdLayer : RenderCmd { |
|||
public RenderLayer layer; |
|||
|
|||
public CmdLayer() { |
|||
} |
|||
|
|||
public override void clear() { |
|||
this.layer = null; |
|||
} |
|||
|
|||
public static CmdLayer create(RenderLayer layer) { |
|||
CmdLayer newCmd = ObjectPool<CmdLayer>.alloc(); |
|||
newCmd.layer = layer; |
|||
return newCmd; |
|||
} |
|||
|
|||
public override void release() { |
|||
ObjectPool<CmdLayer>.release(this); |
|||
} |
|||
} |
|||
|
|||
internal class CmdDraw : RenderCmd { |
|||
public uiMeshMesh mesh; |
|||
public TextBlobMesh textMesh; |
|||
public int pass; |
|||
public MaterialPropertyBlockWrapper properties; |
|||
public int? layerId; |
|||
public Material material; |
|||
public Image image; // just to keep a reference to avoid GC.
|
|||
public Mesh meshObj; |
|||
public bool meshObjCreated; |
|||
|
|||
public static readonly Matrix4x4 idMat = Matrix4x4.identity; |
|||
public static readonly Matrix3 idMat3 = Matrix3.I(); |
|||
public static readonly int texId = Shader.PropertyToID("_tex"); |
|||
public static readonly int matId = Shader.PropertyToID("_mat"); |
|||
|
|||
|
|||
public override void clear() { |
|||
ObjectPool<uiMeshMesh>.release(this.mesh); |
|||
ObjectPool<TextBlobMesh>.release(this.textMesh); |
|||
ObjectPool<MaterialPropertyBlockWrapper>.release(this.properties); |
|||
} |
|||
|
|||
public CmdDraw() { |
|||
} |
|||
|
|||
public static CmdDraw create(uiMeshMesh mesh = null, TextBlobMesh textMesh = null, int pass = 0, |
|||
MaterialPropertyBlockWrapper properties = null, int? layerId = null, Material material = null, |
|||
Image image = null, Mesh meshObj = null, |
|||
bool meshObjCreated = false) { |
|||
CmdDraw newCmd = ObjectPool<CmdDraw>.alloc(); |
|||
newCmd.mesh = mesh; |
|||
newCmd.textMesh = textMesh; |
|||
newCmd.pass = pass; |
|||
newCmd.properties = properties; |
|||
newCmd.layerId = layerId; |
|||
newCmd.material = material; |
|||
newCmd.image = image; |
|||
newCmd.meshObj = meshObj; |
|||
newCmd.meshObjCreated = meshObjCreated; |
|||
|
|||
return newCmd; |
|||
} |
|||
|
|||
public override void release() { |
|||
ObjectPool<CmdDraw>.release(this); |
|||
} |
|||
} |
|||
|
|||
internal class CmdScissor : RenderCmd { |
|||
public uiRect? deviceScissor; |
|||
|
|||
public CmdScissor() { |
|||
} |
|||
|
|||
public override void clear() { |
|||
this.deviceScissor = null; |
|||
} |
|||
|
|||
public static CmdScissor create(uiRect? deviceScissor) { |
|||
CmdScissor newCmd = ObjectPool<CmdScissor>.alloc(); |
|||
newCmd.deviceScissor = deviceScissor; |
|||
return newCmd; |
|||
} |
|||
|
|||
public override void release() { |
|||
ObjectPool<CmdScissor>.release(this); |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: cbfd23f193e6d4e9b86c08ac62694399 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System.Collections.Generic; |
|||
using Unity.UIWidgets.foundation; |
|||
using UnityEngine; |
|||
|
|||
namespace Unity.UIWidgets.ui { |
|||
public partial class PictureFlusher { |
|||
internal class RenderLayer : PoolObject { |
|||
public int rtID; |
|||
public int width; |
|||
public int height; |
|||
public FilterMode filterMode = FilterMode.Bilinear; |
|||
public bool noMSAA = false; |
|||
public uiRect layerBounds; |
|||
public uiPaint? layerPaint; |
|||
public readonly List<RenderCmd> draws = new List<RenderCmd>(128); |
|||
public readonly List<RenderLayer> layers = new List<RenderLayer>(16); |
|||
public readonly List<State> states = new List<State>(16); |
|||
public State currentState; |
|||
public ClipStack clipStack; |
|||
public uint lastClipGenId; |
|||
public uiRect lastClipBounds; |
|||
public bool ignoreClip = true; |
|||
|
|||
Vector4? _viewport; |
|||
|
|||
public Vector4 viewport { |
|||
get { |
|||
if (!this._viewport.HasValue) { |
|||
this._viewport = new Vector4( |
|||
this.layerBounds.left, |
|||
this.layerBounds.top, |
|||
this.layerBounds.width, |
|||
this.layerBounds.height); |
|||
} |
|||
|
|||
return this._viewport.Value; |
|||
} |
|||
} |
|||
|
|||
public static RenderLayer create(int rtID = 0, int width = 0, int height = 0, |
|||
FilterMode filterMode = FilterMode.Bilinear, |
|||
bool noMSAA = false, uiRect? layerBounds = null, uiPaint? layerPaint = null, bool ignoreClip = true) { |
|||
D.assert(layerBounds != null); |
|||
var newLayer = ObjectPool<RenderLayer>.alloc(); |
|||
newLayer.rtID = rtID; |
|||
newLayer.width = width; |
|||
newLayer.height = height; |
|||
newLayer.filterMode = filterMode; |
|||
newLayer.noMSAA = noMSAA; |
|||
newLayer.layerBounds = layerBounds.Value; |
|||
newLayer.layerPaint = layerPaint; |
|||
newLayer.ignoreClip = ignoreClip; |
|||
newLayer.currentState = State.create(); |
|||
newLayer.states.Add(newLayer.currentState); |
|||
newLayer.clipStack = ClipStack.create(); |
|||
|
|||
return newLayer; |
|||
} |
|||
|
|||
public void addLayer(RenderLayer layer) { |
|||
this.layers.Add(layer); |
|||
this.draws.Add(CmdLayer.create(layer: layer)); |
|||
} |
|||
|
|||
public override void clear() { |
|||
//these two list should have been cleared in PictureFlusher._clearLayer
|
|||
D.assert(this.draws.Count == 0); |
|||
D.assert(this.layers.Count == 0); |
|||
this.draws.Clear(); |
|||
this.layers.Clear(); |
|||
|
|||
foreach (var state in this.states) { |
|||
ObjectPool<State>.release(state); |
|||
} |
|||
|
|||
this.states.Clear(); |
|||
ObjectPool<ClipStack>.release(this.clipStack); |
|||
this._viewport = null; |
|||
} |
|||
} |
|||
|
|||
internal class State : PoolObject { |
|||
public State() { |
|||
} |
|||
|
|||
static readonly uiMatrix3 _id = uiMatrix3.I(); |
|||
|
|||
uiMatrix3? _matrix; |
|||
float? _scale; |
|||
uiMatrix3? _invMatrix; |
|||
|
|||
public static State create(uiMatrix3? matrix = null, float? scale = null, uiMatrix3? invMatrix = null) { |
|||
State newState = ObjectPool<State>.alloc(); |
|||
newState._matrix = matrix ?? _id; |
|||
newState._scale = scale; |
|||
newState._invMatrix = invMatrix; |
|||
|
|||
return newState; |
|||
} |
|||
|
|||
public override void clear() { |
|||
this._matrix = null; |
|||
this._scale = null; |
|||
this._invMatrix = null; |
|||
} |
|||
|
|||
public uiMatrix3? matrix { |
|||
get { return this._matrix; } |
|||
set { |
|||
this._matrix = value ?? _id; |
|||
this._scale = null; |
|||
this._invMatrix = null; |
|||
} |
|||
} |
|||
|
|||
public float scale { |
|||
get { |
|||
if (this._scale == null) { |
|||
this._scale = uiXformUtils.getScale(this._matrix.Value); |
|||
} |
|||
|
|||
return this._scale.Value; |
|||
} |
|||
} |
|||
|
|||
public uiMatrix3 invMatrix { |
|||
get { |
|||
if (this._invMatrix == null) { |
|||
this._invMatrix = this._matrix.Value.invert(); |
|||
} |
|||
|
|||
return this._invMatrix.Value; |
|||
} |
|||
} |
|||
|
|||
public State copy() { |
|||
return create(this._matrix, this._scale, this._invMatrix); |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 80db86b2e84084672a0573836aa60f64 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 0f5bbea100d7f4b26b7353f0732299d5 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using Unity.UIWidgets.flow; |
|||
using Unity.UIWidgets.foundation; |
|||
using UnityEngine; |
|||
|
|||
namespace Unity.UIWidgets.ui { |
|||
public class uiRecorderCanvas : Canvas { |
|||
public uiRecorderCanvas(uiPictureRecorder recorder) { |
|||
this._recorder = recorder; |
|||
} |
|||
|
|||
protected readonly uiPictureRecorder _recorder; |
|||
|
|||
int _saveCount = 1; |
|||
|
|||
public void save() { |
|||
this._saveCount++; |
|||
this._recorder.addDrawCmd(uiDrawSave.create()); |
|||
} |
|||
|
|||
public void saveLayer(Rect rect, Paint paint) { |
|||
this._saveCount++; |
|||
this._recorder.addDrawCmd(uiDrawSaveLayer.create( |
|||
rect: uiRectHelper.fromRect(rect), |
|||
paint: uiPaint.fromPaint(paint) |
|||
)); |
|||
} |
|||
|
|||
public void restore() { |
|||
this._saveCount--; |
|||
this._recorder.addDrawCmd(uiDrawRestore.create()); |
|||
} |
|||
|
|||
public int getSaveCount() { |
|||
return this._saveCount; |
|||
} |
|||
|
|||
public void translate(float dx, float dy) { |
|||
this._recorder.addDrawCmd(uiDrawTranslate.create( |
|||
dx: dx, |
|||
dy: dy |
|||
)); |
|||
} |
|||
|
|||
public void scale(float sx, float? sy = null) { |
|||
this._recorder.addDrawCmd(uiDrawScale.create( |
|||
sx: sx, |
|||
sy: sy |
|||
)); |
|||
} |
|||
|
|||
public void rotate(float radians, Offset offset = null) { |
|||
this._recorder.addDrawCmd(uiDrawRotate.create( |
|||
radians: radians, |
|||
offset: uiOffset.fromOffset(offset) |
|||
)); |
|||
} |
|||
|
|||
public void skew(float sx, float sy) { |
|||
this._recorder.addDrawCmd(uiDrawSkew.create( |
|||
sx: sx, |
|||
sy: sy |
|||
)); |
|||
} |
|||
|
|||
public void concat(Matrix3 matrix) { |
|||
this._recorder.addDrawCmd(uiDrawConcat.create( |
|||
matrix: uiMatrix3.fromMatrix3(matrix) |
|||
)); |
|||
} |
|||
|
|||
readonly Matrix3 _totalMatrix = Matrix3.I(); |
|||
|
|||
public Matrix3 getTotalMatrix() { |
|||
var localMatrix = this._recorder.getTotalMatrix(); |
|||
this._totalMatrix.setAll(localMatrix.kMScaleX, localMatrix.kMSkewX, localMatrix.kMTransX, |
|||
localMatrix.kMSkewY, localMatrix.kMScaleY, localMatrix.kMTransY, |
|||
localMatrix.kMPersp0, localMatrix.kMPersp1, localMatrix.kMPersp2); |
|||
|
|||
return this._totalMatrix; |
|||
} |
|||
|
|||
public void resetMatrix() { |
|||
this._recorder.addDrawCmd(uiDrawResetMatrix.create( |
|||
)); |
|||
} |
|||
|
|||
public void setMatrix(Matrix3 matrix) { |
|||
this._recorder.addDrawCmd(uiDrawSetMatrix.create( |
|||
matrix: uiMatrix3.fromMatrix3(matrix) |
|||
)); |
|||
} |
|||
|
|||
public virtual float getDevicePixelRatio() { |
|||
throw new Exception("not available in recorder"); |
|||
} |
|||
|
|||
public void clipRect(Rect rect) { |
|||
this._recorder.addDrawCmd(uiDrawClipRect.create( |
|||
rect: uiRectHelper.fromRect(rect) |
|||
)); |
|||
} |
|||
|
|||
public void clipRRect(RRect rrect) { |
|||
this._recorder.addDrawCmd(uiDrawClipRRect.create( |
|||
rrect: rrect |
|||
)); |
|||
} |
|||
|
|||
public void clipPath(Path path) { |
|||
this._recorder.addDrawCmd(uiDrawClipPath.create( |
|||
path: uiPath.fromPath(path) |
|||
)); |
|||
} |
|||
|
|||
public void drawLine(Offset from, Offset to, Paint paint) { |
|||
var path = uiPath.create(); |
|||
path.moveTo(from.dx, from.dy); |
|||
path.lineTo(to.dx, to.dy); |
|||
|
|||
this._recorder.addDrawCmd(uiDrawPath.create( |
|||
path: path, |
|||
paint: uiPaint.fromPaint(paint) |
|||
)); |
|||
} |
|||
|
|||
public void drawShadow(Path path, Color color, float elevation, bool transparentOccluder) { |
|||
float dpr = Window.instance.devicePixelRatio; |
|||
PhysicalShapeLayer.drawShadow(this, path, color, elevation, transparentOccluder, dpr); |
|||
} |
|||
|
|||
public void drawRect(Rect rect, Paint paint) { |
|||
if (rect.size.isEmpty) { |
|||
return; |
|||
} |
|||
|
|||
var path = uiPath.create(); |
|||
path.addRect(rect); |
|||
|
|||
this._recorder.addDrawCmd(uiDrawPath.create( |
|||
path: path, |
|||
paint: uiPaint.fromPaint(paint) |
|||
)); |
|||
} |
|||
|
|||
public void drawRRect(RRect rrect, Paint paint) { |
|||
var path = uiPath.create(); |
|||
path.addRRect(rrect); |
|||
this._recorder.addDrawCmd(uiDrawPath.create( |
|||
path: path, |
|||
paint: uiPaint.fromPaint(paint) |
|||
)); |
|||
} |
|||
|
|||
public void drawDRRect(RRect outer, RRect inner, Paint paint) { |
|||
var path = uiPath.create(); |
|||
path.addRRect(outer); |
|||
path.addRRect(inner); |
|||
path.winding(PathWinding.clockwise); |
|||
|
|||
this._recorder.addDrawCmd(uiDrawPath.create( |
|||
path: path, |
|||
paint: uiPaint.fromPaint(paint) |
|||
)); |
|||
} |
|||
|
|||
public void drawOval(Rect rect, Paint paint) { |
|||
var w = rect.width / 2; |
|||
var h = rect.height / 2; |
|||
var path = uiPath.create(); |
|||
path.addEllipse(rect.left + w, rect.top + h, w, h); |
|||
|
|||
this._recorder.addDrawCmd(uiDrawPath.create( |
|||
path: path, |
|||
paint: uiPaint.fromPaint(paint) |
|||
)); |
|||
} |
|||
|
|||
public void drawCircle(Offset c, float radius, Paint paint) { |
|||
var path = uiPath.create(); |
|||
path.addCircle(c.dx, c.dy, radius); |
|||
|
|||
this._recorder.addDrawCmd(uiDrawPath.create( |
|||
path: path, |
|||
paint: uiPaint.fromPaint(paint) |
|||
)); |
|||
} |
|||
|
|||
public void drawArc(Rect rect, float startAngle, float sweepAngle, bool useCenter, Paint paint) { |
|||
var path = uiPath.create(); |
|||
|
|||
if (useCenter) { |
|||
var center = rect.center; |
|||
path.moveTo(center.dx, center.dy); |
|||
} |
|||
|
|||
bool forceMoveTo = !useCenter; |
|||
while (sweepAngle <= -Mathf.PI * 2) { |
|||
path.arcTo(rect, startAngle, -Mathf.PI, forceMoveTo); |
|||
startAngle -= Mathf.PI; |
|||
path.arcTo(rect, startAngle, -Mathf.PI, false); |
|||
startAngle -= Mathf.PI; |
|||
forceMoveTo = false; |
|||
sweepAngle += Mathf.PI * 2; |
|||
} |
|||
|
|||
while (sweepAngle >= Mathf.PI * 2) { |
|||
path.arcTo(rect, startAngle, Mathf.PI, forceMoveTo); |
|||
startAngle += Mathf.PI; |
|||
path.arcTo(rect, startAngle, Mathf.PI, false); |
|||
startAngle += Mathf.PI; |
|||
forceMoveTo = false; |
|||
sweepAngle -= Mathf.PI * 2; |
|||
} |
|||
|
|||
path.arcTo(rect, startAngle, sweepAngle, forceMoveTo); |
|||
if (useCenter) { |
|||
path.close(); |
|||
} |
|||
|
|||
this._recorder.addDrawCmd(uiDrawPath.create( |
|||
path: path, |
|||
paint: uiPaint.fromPaint(paint) |
|||
)); |
|||
} |
|||
|
|||
public void drawPath(Path path, Paint paint) { |
|||
this._recorder.addDrawCmd(uiDrawPath.create( |
|||
path: uiPath.fromPath(path), |
|||
paint: uiPaint.fromPaint(paint) |
|||
)); |
|||
} |
|||
|
|||
public void drawImage(Image image, Offset offset, Paint paint) { |
|||
this._recorder.addDrawCmd(uiDrawImage.create( |
|||
image: image, |
|||
offset: uiOffset.fromOffset(offset), |
|||
paint: uiPaint.fromPaint(paint) |
|||
)); |
|||
} |
|||
|
|||
public void drawImageRect(Image image, Rect dst, Paint paint) { |
|||
this._recorder.addDrawCmd(uiDrawImageRect.create( |
|||
image: image, |
|||
src: null, |
|||
dst: uiRectHelper.fromRect(dst), |
|||
paint: uiPaint.fromPaint(paint) |
|||
)); |
|||
} |
|||
|
|||
public void drawImageRect(Image image, Rect src, Rect dst, Paint paint) { |
|||
this._recorder.addDrawCmd(uiDrawImageRect.create( |
|||
image: image, |
|||
src: uiRectHelper.fromRect(src), |
|||
dst: uiRectHelper.fromRect(dst), |
|||
paint: uiPaint.fromPaint(paint) |
|||
)); |
|||
} |
|||
|
|||
public void drawImageNine(Image image, Rect center, Rect dst, Paint paint) { |
|||
this._recorder.addDrawCmd(uiDrawImageNine.create( |
|||
image: image, |
|||
src: null, |
|||
center: uiRectHelper.fromRect(center), |
|||
dst: uiRectHelper.fromRect(dst), |
|||
paint: uiPaint.fromPaint(paint) |
|||
)); |
|||
} |
|||
|
|||
public void drawImageNine(Image image, Rect src, Rect center, Rect dst, Paint paint) { |
|||
this._recorder.addDrawCmd(uiDrawImageNine.create( |
|||
image: image, |
|||
src: uiRectHelper.fromRect(src), |
|||
center: uiRectHelper.fromRect(center), |
|||
dst: uiRectHelper.fromRect(dst), |
|||
paint: uiPaint.fromPaint(paint) |
|||
)); |
|||
} |
|||
|
|||
public void drawPicture(Picture picture) { |
|||
this._recorder.addDrawCmd(uiDrawPicture.create( |
|||
picture: picture |
|||
)); |
|||
} |
|||
|
|||
public void drawTextBlob(TextBlob textBlob, Offset offset, Paint paint) { |
|||
this._recorder.addDrawCmd(uiDrawTextBlob.create( |
|||
textBlob: textBlob, |
|||
offset: uiOffset.fromOffset(offset), |
|||
paint: uiPaint.fromPaint(paint) |
|||
)); |
|||
} |
|||
|
|||
public void drawParagraph(Paragraph paragraph, Offset offset) { |
|||
D.assert(paragraph != null); |
|||
D.assert(PaintingUtils._offsetIsValid(offset)); |
|||
paragraph.paint(this, offset); |
|||
} |
|||
|
|||
public virtual void flush() { |
|||
throw new Exception("not available in recorder"); |
|||
} |
|||
|
|||
public void reset() { |
|||
this._recorder.reset(); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 1859b421a4bfc49c68c7ff6ed3991449 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using UnityEngine; |
|||
|
|||
namespace Unity.UIWidgets.ui { |
|||
public struct uiColor { |
|||
public readonly long value; |
|||
|
|||
public uiColor(long value) { |
|||
this.value = value & 0xFFFFFFFF; |
|||
} |
|||
|
|||
public static readonly uiColor clear = new uiColor(0x00000000); |
|||
|
|||
public static readonly uiColor black = new uiColor(0xFF000000); |
|||
|
|||
public static readonly uiColor white = new uiColor(0xFFFFFFFF); |
|||
|
|||
public int alpha { |
|||
get { return (int) ((0xff000000 & this.value) >> 24); } |
|||
} |
|||
|
|||
public float opacity { |
|||
get { return this.alpha / 255.0f; } |
|||
} |
|||
|
|||
public int red { |
|||
get { return (int) ((0x00ff0000 & this.value) >> 16); } |
|||
} |
|||
|
|||
public int green { |
|||
get { return (int) ((0x0000ff00 & this.value) >> 8); } |
|||
} |
|||
|
|||
public int blue { |
|||
get { return (int) ((0x000000ff & this.value) >> 0); } |
|||
} |
|||
|
|||
public static uiColor fromColor(Color color) { |
|||
return new uiColor(color.value); |
|||
} |
|||
|
|||
public static uiColor fromARGB(int a, int r, int g, int b) { |
|||
return new uiColor( |
|||
(((a & 0xff) << 24) | |
|||
((r & 0xff) << 16) | |
|||
((g & 0xff) << 8) | |
|||
((b & 0xff) << 0)) & 0xFFFFFFFF); |
|||
} |
|||
|
|||
public static uiColor fromRGBO(int r, int g, int b, float opacity) { |
|||
return new uiColor( |
|||
((((int) (opacity * 0xff) & 0xff) << 24) | |
|||
((r & 0xff) << 16) | |
|||
((g & 0xff) << 8) | |
|||
((b & 0xff) << 0)) & 0xFFFFFFFF); |
|||
} |
|||
|
|||
public uiColor withAlpha(int a) { |
|||
return fromARGB(a, this.red, this.green, this.blue); |
|||
} |
|||
|
|||
public uiColor withOpacity(float opacity) { |
|||
return this.withAlpha((int) (opacity * 255)); |
|||
} |
|||
|
|||
static float _linearizeColorComponent(float component) { |
|||
if (component <= 0.03928f) { |
|||
return component / 12.92f; |
|||
} |
|||
|
|||
return Mathf.Pow((component + 0.055f) / 1.055f, 2.4f); |
|||
} |
|||
|
|||
public float computeLuminance() { |
|||
float R = _linearizeColorComponent(this.red / 0xFF); |
|||
float G = _linearizeColorComponent(this.green / 0xFF); |
|||
float B = _linearizeColorComponent(this.blue / 0xFF); |
|||
return 0.2126f * R + 0.7152f * G + 0.0722f * B; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 461310626ee954e13b72c5e70bd4a5f1 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
namespace Unity.UIWidgets.ui { |
|||
public abstract class uiDrawCmd : PoolObject { |
|||
public abstract void release(); |
|||
} |
|||
|
|||
public class uiDrawSave : uiDrawCmd { |
|||
public uiDrawSave() { |
|||
} |
|||
|
|||
public static uiDrawSave create() { |
|||
var drawSave = ObjectPool<uiDrawSave>.alloc(); |
|||
return drawSave; |
|||
} |
|||
|
|||
public override void release() { |
|||
ObjectPool<uiDrawSave>.release(this); |
|||
} |
|||
} |
|||
|
|||
public class uiDrawSaveLayer : uiDrawCmd { |
|||
public uiDrawSaveLayer() { |
|||
} |
|||
|
|||
public static uiDrawSaveLayer create(uiRect? rect, uiPaint paint) { |
|||
var drawSaveLayer = ObjectPool<uiDrawSaveLayer>.alloc(); |
|||
drawSaveLayer.rect = rect; |
|||
drawSaveLayer.paint = paint; |
|||
return drawSaveLayer; |
|||
} |
|||
|
|||
public override void release() { |
|||
ObjectPool<uiDrawSaveLayer>.release(this); |
|||
} |
|||
|
|||
public override void clear() { |
|||
this.rect = null; |
|||
} |
|||
|
|||
public uiRect? rect; |
|||
public uiPaint paint; |
|||
} |
|||
|
|||
public class uiDrawRestore : uiDrawCmd { |
|||
public uiDrawRestore() { |
|||
} |
|||
|
|||
public static uiDrawRestore create() { |
|||
var drawRestore = ObjectPool<uiDrawRestore>.alloc(); |
|||
return drawRestore; |
|||
} |
|||
|
|||
public override void release() { |
|||
ObjectPool<uiDrawRestore>.release(this); |
|||
} |
|||
} |
|||
|
|||
public class uiDrawTranslate : uiDrawCmd { |
|||
public uiDrawTranslate() { |
|||
} |
|||
|
|||
public static uiDrawTranslate create(float dx, float dy) { |
|||
var drawTranslate = ObjectPool<uiDrawTranslate>.alloc(); |
|||
drawTranslate.dx = dx; |
|||
drawTranslate.dy = dy; |
|||
return drawTranslate; |
|||
} |
|||
|
|||
public override void release() { |
|||
ObjectPool<uiDrawTranslate>.release(this); |
|||
} |
|||
|
|||
public float dx; |
|||
public float dy; |
|||
} |
|||
|
|||
public class uiDrawScale : uiDrawCmd { |
|||
public uiDrawScale() { |
|||
} |
|||
|
|||
public static uiDrawScale create(float sx, float? sy) { |
|||
var drawScale = ObjectPool<uiDrawScale>.alloc(); |
|||
drawScale.sx = sx; |
|||
drawScale.sy = sy; |
|||
return drawScale; |
|||
} |
|||
|
|||
public override void release() { |
|||
ObjectPool<uiDrawScale>.release(this); |
|||
} |
|||
|
|||
public float sx; |
|||
public float? sy; |
|||
} |
|||
|
|||
public class uiDrawRotate : uiDrawCmd { |
|||
public uiDrawRotate() { |
|||
} |
|||
|
|||
public static uiDrawRotate create(float radians, uiOffset? offset) { |
|||
var drawRotate = ObjectPool<uiDrawRotate>.alloc(); |
|||
drawRotate.radians = radians; |
|||
drawRotate.offset = offset; |
|||
return drawRotate; |
|||
} |
|||
|
|||
public override void release() { |
|||
ObjectPool<uiDrawRotate>.release(this); |
|||
} |
|||
|
|||
public override void clear() { |
|||
this.offset = null; |
|||
} |
|||
|
|||
public float radians; |
|||
public uiOffset? offset; |
|||
} |
|||
|
|||
public class uiDrawSkew : uiDrawCmd { |
|||
public uiDrawSkew() { |
|||
} |
|||
|
|||
public static uiDrawSkew create(float sx, float sy) { |
|||
var drawSkew = ObjectPool<uiDrawSkew>.alloc(); |
|||
drawSkew.sx = sx; |
|||
drawSkew.sy = sy; |
|||
return drawSkew; |
|||
} |
|||
|
|||
public override void release() { |
|||
ObjectPool<uiDrawSkew>.release(this); |
|||
} |
|||
|
|||
public float sx; |
|||
public float sy; |
|||
} |
|||
|
|||
public class uiDrawConcat : uiDrawCmd { |
|||
public uiDrawConcat() { |
|||
} |
|||
|
|||
public static uiDrawConcat create(uiMatrix3? matrix) { |
|||
var drawConcat = ObjectPool<uiDrawConcat>.alloc(); |
|||
drawConcat.matrix = matrix; |
|||
return drawConcat; |
|||
} |
|||
|
|||
public override void release() { |
|||
ObjectPool<uiDrawConcat>.release(this); |
|||
} |
|||
|
|||
public override void clear() { |
|||
this.matrix = null; |
|||
} |
|||
|
|||
public uiMatrix3? matrix; |
|||
} |
|||
|
|||
public class uiDrawResetMatrix : uiDrawCmd { |
|||
public uiDrawResetMatrix() { |
|||
} |
|||
|
|||
public static uiDrawResetMatrix create() { |
|||
var drawResetMatrix = ObjectPool<uiDrawResetMatrix>.alloc(); |
|||
return drawResetMatrix; |
|||
} |
|||
|
|||
public override void release() { |
|||
ObjectPool<uiDrawResetMatrix>.release(this); |
|||
} |
|||
} |
|||
|
|||
public class uiDrawSetMatrix : uiDrawCmd { |
|||
public uiDrawSetMatrix() { |
|||
} |
|||
|
|||
public static uiDrawSetMatrix create(uiMatrix3? matrix) { |
|||
var drawSetMatrix = ObjectPool<uiDrawSetMatrix>.alloc(); |
|||
drawSetMatrix.matrix = matrix; |
|||
return drawSetMatrix; |
|||
} |
|||
|
|||
public override void release() { |
|||
ObjectPool<uiDrawSetMatrix>.release(this); |
|||
} |
|||
|
|||
public override void clear() { |
|||
this.matrix = null; |
|||
} |
|||
|
|||
public uiMatrix3? matrix; |
|||
} |
|||
|
|||
public class uiDrawClipRect : uiDrawCmd { |
|||
public uiDrawClipRect() { |
|||
} |
|||
|
|||
public static uiDrawClipRect create(uiRect? rect) { |
|||
var drawClipRect = ObjectPool<uiDrawClipRect>.alloc(); |
|||
drawClipRect.rect = rect; |
|||
return drawClipRect; |
|||
} |
|||
|
|||
public override void release() { |
|||
ObjectPool<uiDrawClipRect>.release(this); |
|||
} |
|||
|
|||
public override void clear() { |
|||
this.rect = null; |
|||
} |
|||
|
|||
public uiRect? rect; |
|||
} |
|||
|
|||
public class uiDrawClipRRect : uiDrawCmd { |
|||
public uiDrawClipRRect() { |
|||
} |
|||
|
|||
public static uiDrawClipRRect create(RRect rrect) { |
|||
var drawClipRRect = ObjectPool<uiDrawClipRRect>.alloc(); |
|||
drawClipRRect.rrect = rrect; |
|||
return drawClipRRect; |
|||
} |
|||
|
|||
public override void release() { |
|||
ObjectPool<uiDrawClipRRect>.release(this); |
|||
} |
|||
|
|||
public override void clear() { |
|||
this.rrect = null; |
|||
} |
|||
|
|||
public RRect rrect; |
|||
} |
|||
|
|||
public class uiDrawClipPath : uiDrawCmd { |
|||
public uiDrawClipPath() { |
|||
} |
|||
|
|||
public static uiDrawClipPath create(uiPath path) { |
|||
var drawClipPath = ObjectPool<uiDrawClipPath>.alloc(); |
|||
drawClipPath.path = path; |
|||
return drawClipPath; |
|||
} |
|||
|
|||
public override void release() { |
|||
ObjectPool<uiDrawClipPath>.release(this); |
|||
} |
|||
|
|||
public override void clear() { |
|||
//ObjectPool<uiPath>.release(this.path);
|
|||
uiPathCacheManager.putToCache(this.path); |
|||
this.path = null; |
|||
} |
|||
|
|||
public uiPath path; |
|||
} |
|||
|
|||
public class uiDrawPath : uiDrawCmd { |
|||
public uiDrawPath() { |
|||
} |
|||
|
|||
public static uiDrawPath create(uiPath path, uiPaint paint) { |
|||
var drawPath = ObjectPool<uiDrawPath>.alloc(); |
|||
drawPath.path = path; |
|||
drawPath.paint = paint; |
|||
return drawPath; |
|||
} |
|||
|
|||
public override void release() { |
|||
ObjectPool<uiDrawPath>.release(this); |
|||
} |
|||
|
|||
public override void clear() { |
|||
//ObjectPool<uiPath>.release(this.path);
|
|||
uiPathCacheManager.putToCache(this.path); |
|||
this.path = null; |
|||
} |
|||
|
|||
public uiPath path; |
|||
public uiPaint paint; |
|||
} |
|||
|
|||
public class uiDrawImage : uiDrawCmd { |
|||
public uiDrawImage() { |
|||
} |
|||
|
|||
public static uiDrawImage create(Image image, uiOffset? offset, uiPaint paint) { |
|||
var drawImage = ObjectPool<uiDrawImage>.alloc(); |
|||
drawImage.image = image; |
|||
drawImage.offset = offset; |
|||
drawImage.paint = paint; |
|||
return drawImage; |
|||
} |
|||
|
|||
public override void release() { |
|||
ObjectPool<uiDrawImage>.release(this); |
|||
} |
|||
|
|||
public override void clear() { |
|||
this.image = null; |
|||
this.offset = null; |
|||
} |
|||
|
|||
public Image image; |
|||
public uiOffset? offset; |
|||
public uiPaint paint; |
|||
} |
|||
|
|||
public class uiDrawImageRect : uiDrawCmd { |
|||
public uiDrawImageRect() { |
|||
} |
|||
|
|||
public static uiDrawImageRect create(Image image, uiRect? src, uiRect? dst, uiPaint paint) { |
|||
var drawImageRect = ObjectPool<uiDrawImageRect>.alloc(); |
|||
drawImageRect.image = image; |
|||
drawImageRect.src = src; |
|||
drawImageRect.dst = dst; |
|||
drawImageRect.paint = paint; |
|||
return drawImageRect; |
|||
} |
|||
|
|||
public override void release() { |
|||
ObjectPool<uiDrawImageRect>.release(this); |
|||
} |
|||
|
|||
public override void clear() { |
|||
this.image = null; |
|||
this.src = null; |
|||
this.dst = null; |
|||
} |
|||
|
|||
public Image image; |
|||
public uiRect? src; |
|||
public uiRect? dst; |
|||
public uiPaint paint; |
|||
} |
|||
|
|||
public class uiDrawImageNine : uiDrawCmd { |
|||
public uiDrawImageNine() { |
|||
} |
|||
|
|||
public static uiDrawImageNine create(Image image, uiRect? src, uiRect? center, uiRect? dst, uiPaint paint) { |
|||
var drawImageNine = ObjectPool<uiDrawImageNine>.alloc(); |
|||
drawImageNine.image = image; |
|||
drawImageNine.src = src; |
|||
drawImageNine.center = center; |
|||
drawImageNine.dst = dst; |
|||
drawImageNine.paint = paint; |
|||
return drawImageNine; |
|||
} |
|||
|
|||
public override void release() { |
|||
ObjectPool<uiDrawImageNine>.release(this); |
|||
} |
|||
|
|||
public override void clear() { |
|||
this.image = null; |
|||
this.src = null; |
|||
this.center = null; |
|||
this.dst = null; |
|||
} |
|||
|
|||
public Image image; |
|||
public uiRect? src; |
|||
public uiRect? center; |
|||
public uiRect? dst; |
|||
public uiPaint paint; |
|||
} |
|||
|
|||
public class uiDrawPicture : uiDrawCmd { |
|||
public uiDrawPicture() { |
|||
} |
|||
|
|||
public static uiDrawPicture create(Picture picture) { |
|||
var drawPicture = ObjectPool<uiDrawPicture>.alloc(); |
|||
drawPicture.picture = picture; |
|||
return drawPicture; |
|||
} |
|||
|
|||
public override void release() { |
|||
ObjectPool<uiDrawPicture>.release(this); |
|||
} |
|||
|
|||
public override void clear() { |
|||
this.picture = null; |
|||
} |
|||
|
|||
public Picture picture; |
|||
} |
|||
|
|||
public class uiDrawTextBlob : uiDrawCmd { |
|||
public uiDrawTextBlob() { |
|||
} |
|||
|
|||
public static uiDrawTextBlob create(TextBlob textBlob, uiOffset? offset, uiPaint paint) { |
|||
var drawTextBlob = ObjectPool<uiDrawTextBlob>.alloc(); |
|||
drawTextBlob.textBlob = textBlob; |
|||
drawTextBlob.offset = offset; |
|||
drawTextBlob.paint = paint; |
|||
return drawTextBlob; |
|||
} |
|||
|
|||
public override void release() { |
|||
ObjectPool<uiDrawTextBlob>.release(this); |
|||
} |
|||
|
|||
public override void clear() { |
|||
this.offset = null; |
|||
} |
|||
|
|||
public TextBlob textBlob; |
|||
public uiOffset? offset; |
|||
public uiPaint paint; |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 8b8f342529f264553a2f806b2cad7f32 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 15f29cc8a09164aefb85d8ee18c69ae1 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 4820cc4e3dc2441c8acd09d43ce23e6c |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: cb02ebe9630a944dcbdfb1e1956ea953 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 8bd926580ace74793972a8fe7cb93142 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 5c914278a0e574134bd4550922dfd987 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 9833be88343a54d84b02087b3006b98a |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: f7f9e498efb264ed5b85441a492d89f6 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 9d073f36f6673429ab90abc8c3c469a8 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using Unity.UIWidgets.foundation; |
|||
using UnityEngine; |
|||
|
|||
namespace Unity.UIWidgets.ui { |
|||
public partial struct uiMatrix3 { |
|||
//Constants
|
|||
enum TypeMask { |
|||
kIdentity_Mask = 0, //!< identity SkMatrix; all bits clear
|
|||
kTranslate_Mask = 0x01, //!< translation SkMatrix
|
|||
kScale_Mask = 0x02, //!< scale SkMatrix
|
|||
kAffine_Mask = 0x04, //!< skew or rotate SkMatrix
|
|||
kPerspective_Mask = 0x08, //!< perspective SkMatrix
|
|||
} |
|||
|
|||
const int kRectStaysRect_Mask = 0x10; |
|||
|
|||
const int kOnlyPerspectiveValid_Mask = 0x40; |
|||
|
|||
const int kUnknown_Mask = 0x80; |
|||
|
|||
const int kORableMasks = |
|||
(int) |
|||
(TypeMask.kTranslate_Mask | |
|||
TypeMask.kScale_Mask | |
|||
TypeMask.kAffine_Mask | |
|||
TypeMask.kPerspective_Mask); |
|||
|
|||
const int kAllMasks = |
|||
(int) |
|||
(TypeMask.kTranslate_Mask | |
|||
TypeMask.kScale_Mask | |
|||
TypeMask.kAffine_Mask | |
|||
TypeMask.kPerspective_Mask) | |
|||
kRectStaysRect_Mask; |
|||
|
|||
enum TypeShift { |
|||
kTranslate_Shift, |
|||
kScale_Shift, |
|||
kAffine_Shift, |
|||
kPerspective_Shift, |
|||
kRectStaysRect_Shift |
|||
} |
|||
|
|||
const int kScalar1Int = 0x3f800000; |
|||
} |
|||
|
|||
|
|||
public partial struct uiMatrix3 { |
|||
//Variables
|
|||
public float kMScaleX; //0
|
|||
public float kMSkewX; //1
|
|||
public float kMTransX; //2
|
|||
public float kMSkewY; //3
|
|||
public float kMScaleY; //4
|
|||
public float kMTransY; //5
|
|||
public float kMPersp0; //6
|
|||
public float kMPersp1; //7
|
|||
public float kMPersp2; //8
|
|||
|
|||
public int fTypeMask; |
|||
} |
|||
|
|||
public partial struct uiMatrix3 { |
|||
//private methods
|
|||
void _setScale(float sx, float sy) { |
|||
if (1 == sx && 1 == sy) { |
|||
this.reset(); |
|||
} |
|||
else { |
|||
this.kMScaleX = sx; |
|||
this.kMScaleY = sy; |
|||
this.kMPersp2 = 1; |
|||
|
|||
this.kMTransX = this.kMTransY = this.kMSkewX = |
|||
this.kMSkewY = this.kMPersp0 = this.kMPersp1 = 0; |
|||
|
|||
this._setTypeMask((int) TypeMask.kScale_Mask | kRectStaysRect_Mask); |
|||
} |
|||
} |
|||
|
|||
void _setScale(float sx, float sy, float px, float py) { |
|||
if (1 == sx && 1 == sy) { |
|||
this.reset(); |
|||
} |
|||
else { |
|||
this._setScaleTranslate(sx, sy, px - sx * px, py - sy * py); |
|||
} |
|||
} |
|||
|
|||
int _computeTypeMask() { |
|||
int mask = 0; |
|||
|
|||
if (this.kMPersp0 != 0 || this.kMPersp1 != 0 || |
|||
this.kMPersp2 != 1) { |
|||
// Once it is determined that that this is a perspective transform,
|
|||
// all other flags are moot as far as optimizations are concerned.
|
|||
return kORableMasks; |
|||
} |
|||
|
|||
if (this.kMTransX != 0 || this.kMTransY != 0) { |
|||
mask |= (int) TypeMask.kTranslate_Mask; |
|||
} |
|||
|
|||
int m00 = uiScalarUtils.ScalarAs2sCompliment(this.kMScaleX); |
|||
int m01 = uiScalarUtils.ScalarAs2sCompliment(this.kMSkewX); |
|||
int m10 = uiScalarUtils.ScalarAs2sCompliment(this.kMSkewY); |
|||
int m11 = uiScalarUtils.ScalarAs2sCompliment(this.kMScaleY); |
|||
|
|||
if ((m01 != 0) | (m10 != 0)) { |
|||
mask |= (int) TypeMask.kAffine_Mask | (int) TypeMask.kScale_Mask; |
|||
|
|||
m01 = m01 != 0 ? 1 : 0; |
|||
m10 = m10 != 0 ? 1 : 0; |
|||
|
|||
int dp0 = 0 == (m00 | m11) ? 1 : 0; |
|||
int ds1 = m01 & m10; |
|||
|
|||
mask |= (dp0 & ds1) << (int) TypeShift.kRectStaysRect_Shift; |
|||
} |
|||
else { |
|||
if (((m00 ^ kScalar1Int) | (m11 ^ kScalar1Int)) != 0) { |
|||
mask |= (int) TypeMask.kScale_Mask; |
|||
} |
|||
|
|||
m00 = m00 != 0 ? 1 : 0; |
|||
m11 = m11 != 0 ? 1 : 0; |
|||
|
|||
mask |= (m00 & m11) << (int) TypeShift.kRectStaysRect_Shift; |
|||
} |
|||
|
|||
return mask; |
|||
} |
|||
|
|||
|
|||
TypeMask _getType() { |
|||
if ((this.fTypeMask & kUnknown_Mask) != 0) { |
|||
this.fTypeMask = this._computeTypeMask(); |
|||
} |
|||
|
|||
// only return the public masks
|
|||
return (TypeMask) (this.fTypeMask & 0xF); |
|||
} |
|||
|
|||
public void reset() { |
|||
this.kMScaleX = this.kMScaleY = this.kMPersp2 = 1; |
|||
|
|||
this.kMSkewX = this.kMSkewY = this.kMTransX = |
|||
this.kMTransY = this.kMPersp0 = this.kMPersp1 = 0; |
|||
|
|||
this._setTypeMask((int) TypeMask.kIdentity_Mask | kRectStaysRect_Mask); |
|||
} |
|||
|
|||
bool _isTriviallyIdentity() { |
|||
if ((this.fTypeMask & kUnknown_Mask) != 0) { |
|||
return false; |
|||
} |
|||
|
|||
return (this.fTypeMask & 0xF) == 0; |
|||
} |
|||
|
|||
void _setConcat(uiMatrix3 a, uiMatrix3 b) { |
|||
TypeMask aType = a._getType(); |
|||
TypeMask bType = b._getType(); |
|||
|
|||
if (a._isTriviallyIdentity()) { |
|||
this.copyFrom(b); |
|||
} |
|||
else if (b._isTriviallyIdentity()) { |
|||
this.copyFrom(a); |
|||
} |
|||
else if (_only_scale_and_translate((int) aType | (int) bType)) { |
|||
this._setScaleTranslate(a.kMScaleX * b.kMScaleX, |
|||
a.kMScaleY * b.kMScaleY, |
|||
a.kMScaleX * b.kMTransX + a.kMTransX, |
|||
a.kMScaleY * b.kMTransY + a.kMTransY); |
|||
} |
|||
else { |
|||
uiMatrix3 tmp = new uiMatrix3(); |
|||
|
|||
if (((aType | bType) & TypeMask.kPerspective_Mask) != 0) { |
|||
tmp.kMScaleX = _rowcol3(a, 0, b, 0); |
|||
tmp.kMSkewX = _rowcol3(a, 0, b, 1); |
|||
tmp.kMTransX = _rowcol3(a, 0, b, 2); |
|||
tmp.kMSkewY = _rowcol3(a, 3, b, 0); |
|||
tmp.kMScaleY = _rowcol3(a, 3, b, 1); |
|||
tmp.kMTransY = _rowcol3(a, 3, b, 2); |
|||
tmp.kMPersp0 = _rowcol3(a, 6, b, 0); |
|||
tmp.kMPersp1 = _rowcol3(a, 6, b, 1); |
|||
tmp.kMPersp2 = _rowcol3(a, 6, b, 2); |
|||
|
|||
tmp._setTypeMask(kUnknown_Mask); |
|||
} |
|||
else { |
|||
tmp.kMScaleX = _muladdmul(a.kMScaleX, |
|||
b.kMScaleX, |
|||
a.kMSkewX, |
|||
b.kMSkewY); |
|||
|
|||
tmp.kMSkewX = _muladdmul(a.kMScaleX, |
|||
b.kMSkewX, |
|||
a.kMSkewX, |
|||
b.kMScaleY); |
|||
|
|||
tmp.kMTransX = _muladdmul(a.kMScaleX, |
|||
b.kMTransX, |
|||
a.kMSkewX, |
|||
b.kMTransY) + a.kMTransX; |
|||
|
|||
tmp.kMSkewY = _muladdmul(a.kMSkewY, |
|||
b.kMScaleX, |
|||
a.kMScaleY, |
|||
b.kMSkewY); |
|||
|
|||
tmp.kMScaleY = _muladdmul(a.kMSkewY, |
|||
b.kMSkewX, |
|||
a.kMScaleY, |
|||
b.kMScaleY); |
|||
|
|||
tmp.kMTransY = _muladdmul(a.kMSkewY, |
|||
b.kMTransX, |
|||
a.kMScaleY, |
|||
b.kMTransY) + a.kMTransY; |
|||
|
|||
tmp.kMPersp0 = 0; |
|||
tmp.kMPersp1 = 0; |
|||
tmp.kMPersp2 = 1; |
|||
tmp._setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); |
|||
} |
|||
|
|||
this.copyFrom(tmp); |
|||
} |
|||
} |
|||
|
|||
|
|||
void _setScaleTranslate(float sx, float sy, float tx, float ty) { |
|||
this.kMScaleX = sx; |
|||
this.kMSkewX = 0; |
|||
this.kMTransX = tx; |
|||
|
|||
this.kMSkewY = 0; |
|||
this.kMScaleY = sy; |
|||
this.kMTransY = ty; |
|||
|
|||
this.kMPersp0 = 0; |
|||
this.kMPersp1 = 0; |
|||
this.kMPersp2 = 1; |
|||
|
|||
int mask = 0; |
|||
if (sx != 1 || sy != 1) { |
|||
mask |= (int) TypeMask.kScale_Mask; |
|||
} |
|||
|
|||
if (tx != 0 || ty != 0) { |
|||
mask |= (int) TypeMask.kTranslate_Mask; |
|||
} |
|||
|
|||
this._setTypeMask(mask | kRectStaysRect_Mask); |
|||
} |
|||
|
|||
void _setTypeMask(int mask) { |
|||
D.assert(kUnknown_Mask == mask || (mask & kAllMasks) == mask || |
|||
((kUnknown_Mask | kOnlyPerspectiveValid_Mask) & mask) == |
|||
(kUnknown_Mask | kOnlyPerspectiveValid_Mask)); |
|||
this.fTypeMask = mask; |
|||
} |
|||
|
|||
void _orTypeMask(int mask) { |
|||
D.assert((mask & kORableMasks) == mask); |
|||
this.fTypeMask |= mask; |
|||
} |
|||
|
|||
void _clearTypeMask(int mask) { |
|||
// only allow a valid mask
|
|||
D.assert((mask & kAllMasks) == mask); |
|||
this.fTypeMask &= ~mask; |
|||
} |
|||
|
|||
|
|||
int _computePerspectiveTypeMask() { |
|||
if (this.kMPersp0 != 0 || this.kMPersp1 != 0 || |
|||
this.kMPersp2 != 1) { |
|||
return kORableMasks; |
|||
} |
|||
|
|||
return kOnlyPerspectiveValid_Mask | kUnknown_Mask; |
|||
} |
|||
|
|||
TypeMask _getPerspectiveTypeMaskOnly() { |
|||
if ((this.fTypeMask & kUnknown_Mask) != 0 && |
|||
(this.fTypeMask & kOnlyPerspectiveValid_Mask) == 0) { |
|||
this.fTypeMask = this._computePerspectiveTypeMask(); |
|||
} |
|||
|
|||
return (TypeMask) (this.fTypeMask & 0xF); |
|||
} |
|||
|
|||
bool _hasPerspective() { |
|||
return (this._getPerspectiveTypeMaskOnly() & TypeMask.kPerspective_Mask) != 0; |
|||
} |
|||
|
|||
void _updateTranslateMask() { |
|||
if ((this.kMTransX != 0) | (this.kMTransY != 0)) { |
|||
this.fTypeMask |= (int) TypeMask.kTranslate_Mask; |
|||
} |
|||
else { |
|||
this.fTypeMask &= ~(int) TypeMask.kTranslate_Mask; |
|||
} |
|||
} |
|||
|
|||
public bool _isFinite() { |
|||
return uiScalarUtils.ScalarsAreFinite(this); |
|||
} |
|||
|
|||
uiMatrix3? _invertNonIdentity(bool invertableCheck) { |
|||
D.assert(!this.isIdentity()); |
|||
TypeMask mask = this._getType(); |
|||
|
|||
if (0 == (mask & ~(TypeMask.kScale_Mask | TypeMask.kTranslate_Mask))) { |
|||
bool invertible = true; |
|||
|
|||
if (!invertableCheck) { |
|||
if ((mask & TypeMask.kScale_Mask) != 0) { |
|||
var invX = this.kMScaleX; |
|||
var invY = this.kMScaleY; |
|||
if (0 == invX || 0 == invY) { |
|||
return null; |
|||
} |
|||
|
|||
invX = 1f / invX; |
|||
invY = 1f / invY; |
|||
|
|||
var _inv = I(); |
|||
_inv.kMSkewX = _inv.kMSkewY = |
|||
_inv.kMPersp0 = _inv.kMPersp1 = 0; |
|||
|
|||
_inv.kMScaleX = invX; |
|||
_inv.kMScaleY = invY; |
|||
_inv.kMPersp2 = 1; |
|||
_inv.kMTransX = -this.kMTransX * invX; |
|||
_inv.kMTransY = -this.kMTransY * invY; |
|||
|
|||
_inv._setTypeMask((int) mask | kRectStaysRect_Mask); |
|||
return _inv; |
|||
} |
|||
else { |
|||
var _inv = I(); |
|||
_inv.setTranslate(-this.kMTransX, -this.kMTransY); |
|||
return _inv; |
|||
} |
|||
} |
|||
else { |
|||
if (this.kMScaleX == 0 || this.kMScaleY == 0) { |
|||
return null; |
|||
} |
|||
|
|||
return I(); |
|||
} |
|||
} |
|||
|
|||
int isPersp = (int) (mask & TypeMask.kPerspective_Mask); |
|||
float invDet = uiScalarUtils.inv_determinant(this, isPersp); |
|||
|
|||
if (invDet == 0) { |
|||
// underflow
|
|||
return null; |
|||
} |
|||
|
|||
var inv = ComputeInv(this, invDet, isPersp != 0); |
|||
if (!inv._isFinite()) { |
|||
return null; |
|||
} |
|||
|
|||
inv._setTypeMask(this.fTypeMask); |
|||
return inv; |
|||
} |
|||
|
|||
public bool _isScaleTranslate() { |
|||
return (this._getType() & ~(TypeMask.kScale_Mask | TypeMask.kTranslate_Mask)) == 0; |
|||
} |
|||
|
|||
public uiRect _mapRectScaleTranslate(uiRect src) { |
|||
D.assert(this._isScaleTranslate()); |
|||
|
|||
var sx = this.kMScaleX; |
|||
var sy = this.kMScaleY; |
|||
var tx = this.kMTransX; |
|||
var ty = this.kMTransY; |
|||
|
|||
var dst = uiRectHelper.fromLTRB( |
|||
src.left * sx + tx, |
|||
src.top * sy + ty, |
|||
src.right * sx + tx, |
|||
src.bottom * sy + ty |
|||
); |
|||
|
|||
dst = uiRectHelper.normalize(dst); |
|||
return dst; |
|||
} |
|||
} |
|||
|
|||
|
|||
public partial struct uiMatrix3 { |
|||
//public methods
|
|||
public uiMatrix3(uiMatrix3 other) { |
|||
this.kMScaleX = other.kMScaleX; |
|||
this.kMSkewX = other.kMSkewX; |
|||
this.kMTransX = other.kMTransX; |
|||
this.kMSkewY = other.kMSkewY; |
|||
this.kMScaleY = other.kMScaleY; |
|||
|
|||
this.kMTransY = other.kMTransY; |
|||
|
|||
this.kMPersp0 = other.kMPersp0; |
|||
|
|||
this.kMPersp1 = other.kMPersp1; |
|||
this.kMPersp2 = other.kMPersp2; |
|||
this.fTypeMask = other.fTypeMask; |
|||
} |
|||
|
|||
|
|||
public void copyFrom(uiMatrix3 other) { |
|||
this.kMScaleX = other.kMScaleX; |
|||
this.kMSkewX = other.kMSkewX; |
|||
this.kMTransX = other.kMTransX; |
|||
this.kMSkewY = other.kMSkewY; |
|||
this.kMScaleY = other.kMScaleY; |
|||
|
|||
this.kMTransY = other.kMTransY; |
|||
|
|||
this.kMPersp0 = other.kMPersp0; |
|||
|
|||
this.kMPersp1 = other.kMPersp1; |
|||
|
|||
this.kMPersp2 = other.kMPersp2; |
|||
this.fTypeMask = other.fTypeMask; |
|||
} |
|||
|
|||
|
|||
public bool isIdentity() { |
|||
return this._getType() == 0; |
|||
} |
|||
|
|||
public float getScaleX() { |
|||
return this.kMScaleX; |
|||
} |
|||
|
|||
public float getScaleY() { |
|||
return this.kMScaleY; |
|||
} |
|||
|
|||
public float getSkewY() { |
|||
return this.kMSkewY; |
|||
} |
|||
|
|||
public float getSkewX() { |
|||
return this.kMSkewX; |
|||
} |
|||
|
|||
public float getTranslateX() { |
|||
return this.kMTransX; |
|||
} |
|||
|
|||
public float getTranslateY() { |
|||
return this.kMTransY; |
|||
} |
|||
|
|||
public float getPerspX() { |
|||
return this.kMPersp0; |
|||
} |
|||
|
|||
public float getPerspY() { |
|||
return this.kMPersp1; |
|||
} |
|||
|
|||
public void postConcat(uiMatrix3 mat) { |
|||
if (!mat.isIdentity()) { |
|||
this._setConcat(mat, this); |
|||
} |
|||
} |
|||
|
|||
public void setSinCos(float sinV, float cosV, float px, float py) { |
|||
var oneMinusCosV = 1 - cosV; |
|||
|
|||
this.kMScaleX = cosV; |
|||
this.kMSkewX = -sinV; |
|||
this.kMTransX = uiScalarUtils.sdot(sinV, py, oneMinusCosV, px); |
|||
|
|||
this.kMSkewY = sinV; |
|||
this.kMScaleY = cosV; |
|||
this.kMTransY = uiScalarUtils.sdot(-sinV, px, oneMinusCosV, py); |
|||
|
|||
this.kMPersp0 = this.kMPersp1 = 0; |
|||
this.kMPersp2 = 1; |
|||
|
|||
this._setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); |
|||
} |
|||
|
|||
public void setSinCos(float sinV, float cosV) { |
|||
this.kMScaleX = cosV; |
|||
this.kMSkewX = -sinV; |
|||
this.kMTransX = 0; |
|||
|
|||
this.kMSkewY = sinV; |
|||
this.kMScaleY = cosV; |
|||
this.kMTransY = 0; |
|||
|
|||
this.kMPersp0 = this.kMPersp1 = 0; |
|||
this.kMPersp2 = 1; |
|||
|
|||
this._setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); |
|||
} |
|||
|
|||
public void setTranslate(float dx, float dy) { |
|||
if ((dx != 0) | (dy != 0)) { |
|||
this.kMTransX = dx; |
|||
this.kMTransY = dy; |
|||
|
|||
this.kMScaleX = this.kMScaleY = this.kMPersp2 = 1; |
|||
this.kMSkewX = this.kMSkewY = |
|||
this.kMPersp0 = this.kMPersp1 = 0; |
|||
|
|||
this._setTypeMask((int) TypeMask.kTranslate_Mask | kRectStaysRect_Mask); |
|||
} |
|||
else { |
|||
this.reset(); |
|||
} |
|||
} |
|||
|
|||
|
|||
public void postTranslate(float dx, float dy) { |
|||
if (this._hasPerspective()) { |
|||
var m = new uiMatrix3(); |
|||
m.setTranslate(dx, dy); |
|||
this.postConcat(m); |
|||
} |
|||
else { |
|||
this.kMTransX += dx; |
|||
this.kMTransY += dy; |
|||
this._updateTranslateMask(); |
|||
} |
|||
} |
|||
|
|||
public void postScale(float sx, float sy) { |
|||
if (1 == sx && 1 == sy) { |
|||
return; |
|||
} |
|||
|
|||
var m = new uiMatrix3(); |
|||
m._setScale(sx, sy); |
|||
this.postConcat(m); |
|||
} |
|||
|
|||
public bool rectStaysRect() { |
|||
if ((this.fTypeMask & kUnknown_Mask) != 0) { |
|||
this.fTypeMask = this._computeTypeMask(); |
|||
} |
|||
|
|||
return (this.fTypeMask & kRectStaysRect_Mask) != 0; |
|||
} |
|||
|
|||
public uiMatrix3? invert(bool invertableCheck = false) { |
|||
if (this.isIdentity()) { |
|||
return I(); |
|||
} |
|||
|
|||
return this._invertNonIdentity(invertableCheck); |
|||
} |
|||
|
|||
public uiRect mapRect(uiRect src) { |
|||
if (this._getType() <= TypeMask.kTranslate_Mask) { |
|||
var tx = this.kMTransX; |
|||
var ty = this.kMTransY; |
|||
|
|||
var dst = uiRectHelper.fromLTRB( |
|||
src.left + tx, |
|||
src.top + ty, |
|||
src.right + tx, |
|||
src.bottom + ty |
|||
); |
|||
dst = uiRectHelper.normalize(dst); |
|||
return dst; |
|||
} |
|||
|
|||
if (this._isScaleTranslate()) { |
|||
return this._mapRectScaleTranslate(src); |
|||
} |
|||
else { |
|||
float x1, y1, x2, y2, x3, y3, x4, y4; |
|||
this.mapXY(src.left, src.top, out x1, out y1); |
|||
this.mapXY(src.right, src.top, out x2, out y2); |
|||
this.mapXY(src.right, src.bottom, out x3, out y3); |
|||
this.mapXY(src.left, src.bottom, out x4, out y4); |
|||
|
|||
var minX = x1; |
|||
var minY = y1; |
|||
var maxX = x1; |
|||
var maxY = y1; |
|||
|
|||
if (x2 < minX) { |
|||
minX = x2; |
|||
} |
|||
|
|||
if (x2 > maxX) { |
|||
maxX = x2; |
|||
} |
|||
|
|||
if (y2 < minY) { |
|||
minY = y2; |
|||
} |
|||
|
|||
if (y2 > maxY) { |
|||
maxY = y2; |
|||
} |
|||
|
|||
if (x3 < minX) { |
|||
minX = x3; |
|||
} |
|||
|
|||
if (x3 > maxX) { |
|||
maxX = x3; |
|||
} |
|||
|
|||
if (y3 < minY) { |
|||
minY = y3; |
|||
} |
|||
|
|||
if (y3 > maxY) { |
|||
maxY = y3; |
|||
} |
|||
|
|||
if (x4 < minX) { |
|||
minX = x4; |
|||
} |
|||
|
|||
if (x4 > maxX) { |
|||
maxX = x4; |
|||
} |
|||
|
|||
if (y4 < minY) { |
|||
minY = y4; |
|||
} |
|||
|
|||
if (y4 > maxY) { |
|||
maxY = y4; |
|||
} |
|||
|
|||
var dst = uiRectHelper.fromLTRB(minX, minY, maxX, maxY); |
|||
return dst; |
|||
} |
|||
} |
|||
|
|||
public void mapXY(float x, float y, out float x1, out float y1) { |
|||
this._getMapXYProc()(this, x, y, out x1, out y1); |
|||
} |
|||
|
|||
public Matrix4x4 toMatrix4x4() { |
|||
var matrix = Matrix4x4.identity; |
|||
|
|||
matrix[0, 0] = this.kMScaleX; // row 0
|
|||
matrix[0, 1] = this.kMSkewX; |
|||
matrix[0, 3] = this.kMTransX; |
|||
|
|||
matrix[1, 0] = this.kMSkewY; // row 1
|
|||
matrix[1, 1] = this.kMScaleY; |
|||
matrix[1, 3] = this.kMTransY; |
|||
|
|||
matrix[3, 0] = this.kMPersp0; // row 2
|
|||
matrix[3, 1] = this.kMPersp1; |
|||
matrix[3, 3] = this.kMPersp2; |
|||
|
|||
return matrix; |
|||
} |
|||
|
|||
public void preTranslate(float dx, float dy) { |
|||
var mask = this._getType(); |
|||
|
|||
if (mask <= TypeMask.kTranslate_Mask) { |
|||
this.kMTransX += dx; |
|||
this.kMTransY += dy; |
|||
} |
|||
else if ((mask & TypeMask.kPerspective_Mask) != 0) { |
|||
var m = new uiMatrix3(); |
|||
m.setTranslate(dx, dy); |
|||
this.preConcat(m); |
|||
return; |
|||
} |
|||
else { |
|||
this.kMTransX += this.kMScaleX * dx + this.kMSkewX * dy; |
|||
this.kMTransY += this.kMSkewY * dx + this.kMScaleY * dy; |
|||
} |
|||
|
|||
this._updateTranslateMask(); |
|||
} |
|||
|
|||
public void preConcat(uiMatrix3 other) { |
|||
if (!other.isIdentity()) { |
|||
this._setConcat(this, other); |
|||
} |
|||
} |
|||
|
|||
public void preScale(float sx, float sy, float px, float py) { |
|||
if (1 == sx && 1 == sy) { |
|||
return; |
|||
} |
|||
|
|||
var m = new uiMatrix3(); |
|||
m.setScale(sx, sy, px, py); |
|||
this.preConcat(m); |
|||
} |
|||
|
|||
public void preScale(float sx, float sy) { |
|||
if (1 == sx && 1 == sy) { |
|||
return; |
|||
} |
|||
|
|||
this.kMScaleX *= sx; |
|||
this.kMSkewY *= sx; |
|||
this.kMPersp0 *= sx; |
|||
|
|||
this.kMSkewX *= sy; |
|||
this.kMScaleY *= sy; |
|||
this.kMPersp1 *= sy; |
|||
|
|||
if (this.kMScaleX == 1 && this.kMScaleY == 1 && (this.fTypeMask & |
|||
(int) (TypeMask.kPerspective_Mask | TypeMask.kAffine_Mask) |
|||
) == 0) { |
|||
this._clearTypeMask((int) TypeMask.kScale_Mask); |
|||
} |
|||
else { |
|||
this._orTypeMask((int) TypeMask.kScale_Mask); |
|||
} |
|||
} |
|||
|
|||
public void preRotate(float radians, float px, float py) { |
|||
var m = new uiMatrix3(); |
|||
m.setRotate(radians, px, py); |
|||
this.preConcat(m); |
|||
} |
|||
|
|||
public void preRotate(float radians) { |
|||
var m = new uiMatrix3(); |
|||
m.setRotate(radians); |
|||
this.preConcat(m); |
|||
} |
|||
|
|||
public void preSkew(float kx, float ky) { |
|||
var m = new uiMatrix3(); |
|||
m.setSkew(kx, ky); |
|||
this.preConcat(m); |
|||
} |
|||
|
|||
public void setScale(float sx, float sy, float px, float py) { |
|||
if (1 == sx && 1 == sy) { |
|||
this.reset(); |
|||
} |
|||
else { |
|||
this._setScaleTranslate(sx, sy, px - sx * px, py - sy * py); |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
using System; |
|||
using Unity.UIWidgets.foundation; |
|||
using UnityEngine; |
|||
|
|||
namespace Unity.UIWidgets.ui { |
|||
public partial struct uiMatrix3 { |
|||
public void mapPoints(uiOffset[] dst, uiOffset[] src) { |
|||
D.assert(dst != null && src != null && dst.Length == src.Length); |
|||
this._getMapPtsProc()(this, dst, src, src.Length); |
|||
} |
|||
|
|||
public void mapPoints(uiOffset[] pts) { |
|||
this.mapPoints(pts, pts); |
|||
} |
|||
|
|||
delegate void MapPtsProc(uiMatrix3 mat, uiOffset[] dst, uiOffset[] src, int count); |
|||
|
|||
static readonly MapPtsProc[] gMapPtsProcs = { |
|||
Identity_pts, Trans_pts, |
|||
Scale_pts, Scale_pts, |
|||
Affine_pts, Affine_pts, |
|||
Affine_pts, Affine_pts, |
|||
// repeat the persp proc 8 times
|
|||
Persp_pts, Persp_pts, |
|||
Persp_pts, Persp_pts, |
|||
Persp_pts, Persp_pts, |
|||
Persp_pts, Persp_pts |
|||
}; |
|||
|
|||
static MapPtsProc GetMapPtsProc(TypeMask mask) { |
|||
D.assert(((int) mask & ~kAllMasks) == 0); |
|||
return gMapPtsProcs[(int) mask & kAllMasks]; |
|||
} |
|||
|
|||
MapPtsProc _getMapPtsProc() { |
|||
return GetMapPtsProc(this._getType()); |
|||
} |
|||
|
|||
static void Identity_pts(uiMatrix3 m, uiOffset[] dst, uiOffset[] src, int count) { |
|||
D.assert(m._getType() == 0); |
|||
|
|||
if (dst != src && count > 0) { |
|||
Array.Copy(src, dst, count); |
|||
} |
|||
} |
|||
|
|||
static void Trans_pts(uiMatrix3 m, uiOffset[] dst, uiOffset[] src, int count) { |
|||
D.assert(m._getType() <= TypeMask.kTranslate_Mask); |
|||
if (count > 0) { |
|||
var tx = m.getTranslateX(); |
|||
var ty = m.getTranslateY(); |
|||
for (int i = 0; i < count; ++i) { |
|||
dst[i] = new uiOffset(src[i].dx + tx, src[i].dy + ty); |
|||
} |
|||
} |
|||
} |
|||
|
|||
static void Scale_pts(uiMatrix3 m, uiOffset[] dst, uiOffset[] src, int count) { |
|||
D.assert(m._getType() <= (TypeMask.kScale_Mask | TypeMask.kTranslate_Mask)); |
|||
if (count > 0) { |
|||
var tx = m.getTranslateX(); |
|||
var ty = m.getTranslateY(); |
|||
var sx = m.getScaleX(); |
|||
var sy = m.getScaleY(); |
|||
|
|||
for (int i = 0; i < count; ++i) { |
|||
dst[i] = new uiOffset(src[i].dx * sx + tx, src[i].dy * sy + ty); |
|||
} |
|||
} |
|||
} |
|||
|
|||
static void Persp_pts(uiMatrix3 m, uiOffset[] dst, uiOffset[] src, int count) { |
|||
D.assert(m._hasPerspective()); |
|||
|
|||
if (count > 0) { |
|||
for (int i = 0; i < count; ++i) { |
|||
var sy = src[i].dy; |
|||
var sx = src[i].dx; |
|||
var x = uiScalarUtils.sdot(sx, m.kMScaleX, sy, m.kMSkewX) + |
|||
m.kMTransX; |
|||
var y = uiScalarUtils.sdot(sx, m.kMSkewY, sy, m.kMScaleY) + |
|||
m.kMTransY; |
|||
var z = uiScalarUtils.sdot(sx, m.kMPersp0, sy, m.kMPersp1) + |
|||
m.kMPersp2; |
|||
if (z != 0) { |
|||
z = 1 / z; |
|||
} |
|||
|
|||
dst[i] = new uiOffset(x * z, y * z); |
|||
} |
|||
} |
|||
} |
|||
|
|||
static void Affine_pts(uiMatrix3 m, uiOffset[] dst, uiOffset[] src, int count) { |
|||
D.assert(m._getType() != TypeMask.kPerspective_Mask); |
|||
if (count > 0) { |
|||
var tx = m.getTranslateX(); |
|||
var ty = m.getTranslateY(); |
|||
var sx = m.getScaleX(); |
|||
var sy = m.getScaleY(); |
|||
var kx = m.getSkewX(); |
|||
var ky = m.getSkewY(); |
|||
|
|||
for (int i = 0; i < count; ++i) { |
|||
dst[i] = new uiOffset( |
|||
src[i].dx * sx + src[i].dy * kx + tx, |
|||
src[i].dx * ky + src[i].dy * sy + ty); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
public partial struct uiMatrix3 { |
|||
delegate void MapXYProc(uiMatrix3 mat, float x, float y, out float x1, out float y1); |
|||
|
|||
static readonly MapXYProc[] gMapXYProcs = { |
|||
Identity_xy, Trans_xy, |
|||
Scale_xy, ScaleTrans_xy, |
|||
Rot_xy, RotTrans_xy, |
|||
Rot_xy, RotTrans_xy, |
|||
// repeat the persp proc 8 times
|
|||
Persp_xy, Persp_xy, |
|||
Persp_xy, Persp_xy, |
|||
Persp_xy, Persp_xy, |
|||
Persp_xy, Persp_xy |
|||
}; |
|||
|
|||
static MapXYProc GetMapXYProc(TypeMask mask) { |
|||
D.assert(((int) mask & ~kAllMasks) == 0); |
|||
return gMapXYProcs[(int) mask & kAllMasks]; |
|||
} |
|||
|
|||
MapXYProc _getMapXYProc() { |
|||
return GetMapXYProc(this._getType()); |
|||
} |
|||
|
|||
static void Identity_xy(uiMatrix3 m, float sx, float sy, out float resX, out float resY) { |
|||
D.assert(0 == m._getType()); |
|||
|
|||
resX = sx; |
|||
resY = sy; |
|||
} |
|||
|
|||
static void Trans_xy(uiMatrix3 m, float sx, float sy, out float resX, out float resY) { |
|||
D.assert(m._getType() == TypeMask.kTranslate_Mask); |
|||
|
|||
resX = sx + m.kMTransX; |
|||
resY = sy + m.kMTransY; |
|||
} |
|||
|
|||
static void Scale_xy(uiMatrix3 m, float sx, float sy, out float resX, out float resY) { |
|||
D.assert((m._getType() & (TypeMask.kScale_Mask | TypeMask.kAffine_Mask | TypeMask.kPerspective_Mask)) |
|||
== TypeMask.kScale_Mask); |
|||
D.assert(0 == m.kMTransX); |
|||
D.assert(0 == m.kMTransY); |
|||
|
|||
resX = sx * m.kMScaleX; |
|||
resY = sy * m.kMScaleY; |
|||
} |
|||
|
|||
static void ScaleTrans_xy(uiMatrix3 m, float sx, float sy, out float resX, out float resY) { |
|||
D.assert((m._getType() & (TypeMask.kScale_Mask | TypeMask.kAffine_Mask | TypeMask.kPerspective_Mask)) |
|||
== TypeMask.kScale_Mask); |
|||
|
|||
resX = sx * m.kMScaleX + m.kMTransX; |
|||
resY = sy * m.kMScaleY + m.kMTransY; |
|||
} |
|||
|
|||
static void Rot_xy(uiMatrix3 m, float sx, float sy, out float resX, out float resY) { |
|||
D.assert((m._getType() & (TypeMask.kAffine_Mask | TypeMask.kPerspective_Mask)) == TypeMask.kAffine_Mask); |
|||
D.assert(0 == m.kMTransX); |
|||
D.assert(0 == m.kMTransY); |
|||
|
|||
resX = uiScalarUtils.sdot(sx, m.kMScaleX, sy, m.kMSkewX); |
|||
resY = uiScalarUtils.sdot(sx, m.kMSkewY, sy, m.kMScaleY); |
|||
} |
|||
|
|||
static void RotTrans_xy(uiMatrix3 m, float sx, float sy, out float resX, out float resY) { |
|||
D.assert((m._getType() & (TypeMask.kAffine_Mask | TypeMask.kPerspective_Mask)) == TypeMask.kAffine_Mask); |
|||
|
|||
resX = uiScalarUtils.sdot(sx, m.kMScaleX, sy, m.kMSkewX) + m.kMTransX; |
|||
resY = uiScalarUtils.sdot(sx, m.kMSkewY, sy, m.kMScaleY) + m.kMTransY; |
|||
} |
|||
|
|||
static void Persp_xy(uiMatrix3 m, float sx, float sy, out float resX, out float resY) { |
|||
D.assert(m._hasPerspective()); |
|||
|
|||
float x = uiScalarUtils.sdot(sx, m.kMScaleX, sy, m.kMSkewX) + |
|||
m.kMTransX; |
|||
float y = uiScalarUtils.sdot(sx, m.kMSkewY, sy, m.kMScaleY) + |
|||
m.kMTransY; |
|||
float z = uiScalarUtils.sdot(sx, m.kMPersp0, sy, m.kMPersp1) + |
|||
m.kMPersp2; |
|||
if (z != 0) { |
|||
z = 1 / z; |
|||
} |
|||
|
|||
resX = x * z; |
|||
resY = y * z; |
|||
} |
|||
} |
|||
|
|||
|
|||
public partial struct uiMatrix3 { |
|||
//static methods
|
|||
public static uiMatrix3 I() { |
|||
var m = new uiMatrix3(); |
|||
m.reset(); |
|||
return m; |
|||
} |
|||
|
|||
public static uiMatrix3 makeTrans(float dx, float dy) { |
|||
var m = new uiMatrix3(); |
|||
m.setTranslate(dx, dy); |
|||
return m; |
|||
} |
|||
|
|||
public static uiMatrix3 makeScale(float sx, float sy) { |
|||
var m = new uiMatrix3(); |
|||
m._setScale(sx, sy); |
|||
return m; |
|||
} |
|||
|
|||
public static uiMatrix3 makeRotate(float radians) { |
|||
var m = new uiMatrix3(); |
|||
m.setRotate(radians); |
|||
return m; |
|||
} |
|||
|
|||
public static uiMatrix3 makeRotate(float radians, float px, float py) { |
|||
var m = new uiMatrix3(); |
|||
m.setRotate(radians, px, py); |
|||
return m; |
|||
} |
|||
|
|||
public static uiMatrix3 makeTrans(uiOffset offset) { |
|||
var m = new uiMatrix3(); |
|||
m.setTranslate(offset.dx, offset.dy); |
|||
return m; |
|||
} |
|||
|
|||
public static uiMatrix3 makeSkew(float dx, float dy) { |
|||
var m = new uiMatrix3(); |
|||
m.setSkew(dx, dy); |
|||
return m; |
|||
} |
|||
|
|||
public static uiMatrix3 concat(uiMatrix3 a, uiMatrix3 b) { |
|||
uiMatrix3 result = I(); |
|||
result._setConcat(a, b); |
|||
return result; |
|||
} |
|||
|
|||
public void setRotate(float radians, float px, float py) { |
|||
float sinV, cosV; |
|||
sinV = uiScalarUtils.ScalarSinCos(radians, out cosV); |
|||
this.setSinCos(sinV, cosV, px, py); |
|||
} |
|||
|
|||
public void setRotate(float radians) { |
|||
float sinV, cosV; |
|||
sinV = uiScalarUtils.ScalarSinCos(radians, out cosV); |
|||
this.setSinCos(sinV, cosV); |
|||
} |
|||
|
|||
public void setSkew(float kx, float ky, float px, float py) { |
|||
this.kMScaleX = 1; |
|||
this.kMSkewX = kx; |
|||
this.kMTransX = -kx * py; |
|||
|
|||
this.kMSkewY = ky; |
|||
this.kMScaleY = 1; |
|||
this.kMTransY = -ky * px; |
|||
|
|||
this.kMPersp0 = this.kMPersp1 = 0; |
|||
this.kMPersp2 = 1; |
|||
|
|||
this._setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); |
|||
} |
|||
|
|||
public void setSkew(float kx, float ky) { |
|||
this.kMScaleX = 1; |
|||
this.kMSkewX = kx; |
|||
this.kMTransX = 0; |
|||
|
|||
this.kMSkewY = ky; |
|||
this.kMScaleY = 1; |
|||
this.kMTransY = 0; |
|||
|
|||
this.kMPersp0 = this.kMPersp1 = 0; |
|||
this.kMPersp2 = 1; |
|||
|
|||
this._setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); |
|||
} |
|||
|
|||
public static bool equals(uiMatrix3? a, uiMatrix3? b) { |
|||
if (ReferenceEquals(a, null) && ReferenceEquals(b, null)) { |
|||
return true; |
|||
} |
|||
|
|||
if (ReferenceEquals(a, b)) { |
|||
return true; |
|||
} |
|||
|
|||
if (ReferenceEquals(a, null) || ReferenceEquals(b, null)) { |
|||
return false; |
|||
} |
|||
|
|||
var ma = a.Value; |
|||
var mb = b.Value; |
|||
|
|||
return ma.kMScaleX == mb.kMScaleX && ma.kMSkewX == mb.kMSkewX && ma.kMTransX == mb.kMTransX && |
|||
ma.kMSkewY == mb.kMSkewY && ma.kMScaleY == mb.kMScaleY && ma.kMTransY == mb.kMTransY && |
|||
ma.kMPersp0 == mb.kMPersp0 && ma.kMPersp1 == mb.kMPersp1 && ma.kMPersp2 == mb.kMPersp2; |
|||
} |
|||
} |
|||
|
|||
|
|||
public partial struct uiMatrix3 { |
|||
public static uiMatrix3 fromMatrix3(Matrix3 mat3) { |
|||
var uiMat3 = I(); |
|||
|
|||
|
|||
uiMat3.kMScaleX = mat3[0]; |
|||
uiMat3.kMSkewX = mat3[1]; |
|||
uiMat3.kMTransX = mat3[2]; |
|||
uiMat3.kMSkewY = mat3[3]; |
|||
uiMat3.kMScaleY = mat3[4]; |
|||
uiMat3.kMTransY = mat3[5]; |
|||
uiMat3.kMPersp0 = mat3[6]; |
|||
uiMat3.kMPersp1 = mat3[7]; |
|||
uiMat3.kMPersp2 = mat3[8]; |
|||
|
|||
uiMat3._setTypeMask(kUnknown_Mask); |
|||
return uiMat3; |
|||
} |
|||
|
|||
static bool _only_scale_and_translate(int mask) { |
|||
return 0 == (mask & (int) (TypeMask.kAffine_Mask | TypeMask.kPerspective_Mask)); |
|||
} |
|||
|
|||
static float _getitem(uiMatrix3 mat, int i) { |
|||
switch (i) { |
|||
case 0: |
|||
return mat.kMScaleX; |
|||
case 1: |
|||
return mat.kMSkewX; |
|||
case 2: |
|||
return mat.kMTransX; |
|||
case 3: |
|||
return mat.kMSkewY; |
|||
case 4: |
|||
return mat.kMScaleY; |
|||
case 5: |
|||
return mat.kMTransY; |
|||
case 6: |
|||
return mat.kMPersp0; |
|||
case 7: |
|||
return mat.kMPersp1; |
|||
case 8: |
|||
return mat.kMPersp2; |
|||
default: { |
|||
return -1; |
|||
} |
|||
} |
|||
} |
|||
|
|||
static float _rowcol3(uiMatrix3 row, int i, uiMatrix3 col, int j) { |
|||
return _getitem(row, i) * _getitem(col, j) + _getitem(row, i + 1) * _getitem(col, j + 3) + |
|||
_getitem(row, i + 2) * _getitem(col, j + 6); |
|||
} |
|||
|
|||
static float _muladdmul(float a, float b, float c, float d) { |
|||
return (float) ((double) a * b + (double) c * d); |
|||
} |
|||
|
|||
static uiMatrix3 ComputeInv(uiMatrix3 src, float invDet, bool isPersp) { |
|||
uiMatrix3 dst = I(); |
|||
if (isPersp) { |
|||
dst.kMScaleX = |
|||
uiScalarUtils.scross_dscale(src.kMScaleY, src.kMPersp2, src.kMTransY, |
|||
src.kMPersp1, invDet); |
|||
dst.kMSkewX = |
|||
uiScalarUtils.scross_dscale(src.kMTransX, src.kMPersp1, src.kMSkewX, |
|||
src.kMPersp2, invDet); |
|||
dst.kMTransX = |
|||
uiScalarUtils.scross_dscale(src.kMSkewX, src.kMTransY, src.kMTransX, |
|||
src.kMScaleY, invDet); |
|||
|
|||
dst.kMSkewY = |
|||
uiScalarUtils.scross_dscale(src.kMTransY, src.kMPersp0, src.kMSkewY, |
|||
src.kMPersp2, invDet); |
|||
dst.kMScaleY = |
|||
uiScalarUtils.scross_dscale(src.kMScaleX, src.kMPersp2, src.kMTransX, |
|||
src.kMPersp0, invDet); |
|||
dst.kMTransY = |
|||
uiScalarUtils.scross_dscale(src.kMTransX, src.kMSkewY, src.kMScaleX, |
|||
src.kMTransY, invDet); |
|||
|
|||
dst.kMPersp0 = |
|||
uiScalarUtils.scross_dscale(src.kMSkewY, src.kMPersp1, src.kMScaleY, |
|||
src.kMPersp0, invDet); |
|||
dst.kMPersp1 = |
|||
uiScalarUtils.scross_dscale(src.kMSkewX, src.kMPersp0, src.kMScaleX, |
|||
src.kMPersp1, invDet); |
|||
dst.kMPersp2 = |
|||
uiScalarUtils.scross_dscale(src.kMScaleX, src.kMScaleY, src.kMSkewX, |
|||
src.kMSkewY, invDet); |
|||
} |
|||
else { |
|||
// not perspective
|
|||
dst.kMScaleX = src.kMScaleY * invDet; |
|||
dst.kMSkewX = -src.kMSkewX * invDet; |
|||
dst.kMTransX = |
|||
uiScalarUtils.dcross_dscale(src.kMSkewX, src.kMTransY, src.kMScaleY, |
|||
src.kMTransX, invDet); |
|||
|
|||
dst.kMSkewY = -src.kMSkewY * invDet; |
|||
dst.kMScaleY = src.kMScaleX * invDet; |
|||
dst.kMTransY = |
|||
uiScalarUtils.dcross_dscale(src.kMSkewY, src.kMTransX, src.kMScaleX, |
|||
src.kMTransY, invDet); |
|||
|
|||
dst.kMPersp0 = 0; |
|||
dst.kMPersp1 = 0; |
|||
dst.kMPersp2 = 1; |
|||
} |
|||
|
|||
return dst; |
|||
} |
|||
|
|||
//utils
|
|||
class uiScalarUtils { |
|||
public const float kScalarNearlyZero = 1f / (1 << 12); |
|||
|
|||
public static bool ScalarNearlyZero(float x, float tolerance = kScalarNearlyZero) { |
|||
D.assert(tolerance >= 0); |
|||
return Mathf.Abs(x) <= tolerance; |
|||
} |
|||
|
|||
public static bool ScalarNearlyEqual(float x, float y, float tolerance = kScalarNearlyZero) { |
|||
D.assert(tolerance >= 0); |
|||
return Mathf.Abs(x - y) <= tolerance; |
|||
} |
|||
|
|||
public static bool ScalarIsInteger(float scalar) { |
|||
return scalar == Mathf.FloorToInt(scalar); |
|||
} |
|||
|
|||
public static float DegreesToRadians(float degrees) { |
|||
return degrees * (Mathf.PI / 180); |
|||
} |
|||
|
|||
public static float RadiansToDegrees(float radians) { |
|||
return radians * (180 / Mathf.PI); |
|||
} |
|||
|
|||
public static float ScalarSinCos(float radians, out float cosValue) { |
|||
float sinValue = Mathf.Sin(radians); |
|||
|
|||
cosValue = Mathf.Cos(radians); |
|||
if (ScalarNearlyZero(cosValue)) { |
|||
cosValue = 0; |
|||
} |
|||
|
|||
if (ScalarNearlyZero(sinValue)) { |
|||
sinValue = 0; |
|||
} |
|||
|
|||
return sinValue; |
|||
} |
|||
|
|||
public static bool ScalarsAreFinite(uiMatrix3 m) { |
|||
float prod = m.kMScaleX * m.kMSkewX * m.kMTransX * m.kMSkewY * m.kMScaleY * m.kMTransY * m.kMPersp0 * |
|||
m.kMPersp1 * m.kMPersp2; |
|||
// At this point, prod will either be NaN or 0
|
|||
return prod == 0; // if prod is NaN, this check will return false
|
|||
} |
|||
|
|||
static byte[] _scalar_as_2s_compliment_vars = new byte[4]; |
|||
|
|||
|
|||
static unsafe int GetBytesToInt32(float value) { |
|||
var intVal = *(int*) &value; |
|||
fixed (byte* b = _scalar_as_2s_compliment_vars) { |
|||
*((int*) b) = intVal; |
|||
} |
|||
|
|||
fixed (byte* pbyte = &_scalar_as_2s_compliment_vars[0]) { |
|||
return *((int*) pbyte); |
|||
} |
|||
} |
|||
|
|||
public static int ScalarAs2sCompliment(float x) { |
|||
var result = GetBytesToInt32(x); |
|||
if (result < 0) { |
|||
result &= 0x7FFFFFFF; |
|||
result = -result; |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
public static float sdot(float a, float b, float c, float d) { |
|||
return a * b + c * d; |
|||
} |
|||
|
|||
public static float sdot(float a, float b, float c, float d, float e, float f) { |
|||
return a * b + c * d + e * f; |
|||
} |
|||
|
|||
public static float scross(float a, float b, float c, float d) { |
|||
return a * b - c * d; |
|||
} |
|||
|
|||
public static double dcross(double a, double b, double c, double d) { |
|||
return a * b - c * d; |
|||
} |
|||
|
|||
public static float scross_dscale(float a, float b, |
|||
float c, float d, double scale) { |
|||
return (float) (scross(a, b, c, d) * scale); |
|||
} |
|||
|
|||
public static float dcross_dscale(double a, double b, |
|||
double c, double d, double scale) { |
|||
return (float) (dcross(a, b, c, d) * scale); |
|||
} |
|||
|
|||
public static bool is_degenerate_2x2( |
|||
float scaleX, float skewX, |
|||
float skewY, float scaleY) { |
|||
float perp_dot = scaleX * scaleY - skewX * skewY; |
|||
return ScalarNearlyZero(perp_dot, |
|||
kScalarNearlyZero * kScalarNearlyZero); |
|||
} |
|||
|
|||
public static float inv_determinant(uiMatrix3 mat, int isPerspective) { |
|||
double det; |
|||
|
|||
if (isPerspective != 0) { |
|||
det = mat.kMScaleX * |
|||
dcross(mat.kMScaleY, mat.kMPersp2, |
|||
mat.kMTransY, mat.kMPersp1) |
|||
+ |
|||
mat.kMSkewX * |
|||
dcross(mat.kMTransY, mat.kMPersp0, |
|||
mat.kMSkewY, mat.kMPersp2) |
|||
+ |
|||
mat.kMTransX * |
|||
dcross(mat.kMSkewY, mat.kMPersp1, |
|||
mat.kMScaleY, mat.kMPersp0); |
|||
} |
|||
else { |
|||
det = dcross(mat.kMScaleX, mat.kMScaleY, |
|||
mat.kMSkewX, mat.kMSkewY); |
|||
} |
|||
|
|||
// Since the determinant is on the order of the cube of the matrix members,
|
|||
// compare to the cube of the default nearly-zero constant (although an
|
|||
// estimate of the condition number would be better if it wasn't so expensive).
|
|||
if (ScalarNearlyZero((float) det, |
|||
kScalarNearlyZero * kScalarNearlyZero * kScalarNearlyZero)) { |
|||
return 0; |
|||
} |
|||
|
|||
return 1.0f / (float) det; |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
using System.Collections.Generic; |
|||
using Unity.UIWidgets.foundation; |
|||
using UnityEngine; |
|||
|
|||
namespace Unity.UIWidgets.ui { |
|||
class uiMeshMesh : PoolObject { |
|||
public uiList<Vector3> vertices; |
|||
public uiList<int> triangles; |
|||
public uiList<Vector2> uv; |
|||
public uiMatrix3? matrix; |
|||
public uiRect rawBounds; |
|||
|
|||
uiRect? _bounds; |
|||
|
|||
public uiRect bounds { |
|||
get { |
|||
if (this._bounds == null) { |
|||
this._bounds = this.matrix != null ? this.matrix.Value.mapRect(this.rawBounds) : this.rawBounds; |
|||
} |
|||
|
|||
return this._bounds.Value; |
|||
} |
|||
} |
|||
|
|||
static readonly List<int> _boundsTriangles = new List<int>(6) { |
|||
0, 2, 1, 1, 2, 3 |
|||
}; |
|||
|
|||
public uiMeshMesh boundsMesh { |
|||
get { return create(this.bounds); } |
|||
} |
|||
|
|||
public uiMeshMesh() { |
|||
} |
|||
|
|||
public override void clear() { |
|||
ObjectPool<uiList<Vector3>>.release(this.vertices); |
|||
ObjectPool<uiList<int>>.release(this.triangles); |
|||
ObjectPool<uiList<Vector2>>.release(this.uv); |
|||
this.vertices = null; |
|||
this.triangles = null; |
|||
this.uv = null; |
|||
this.matrix = null; |
|||
this._bounds = null; |
|||
} |
|||
|
|||
public static uiMeshMesh create(uiRect rect) { |
|||
uiMeshMesh newMesh = ObjectPool<uiMeshMesh>.alloc(); |
|||
|
|||
newMesh.vertices = ObjectPool<uiList<Vector3>>.alloc(); |
|||
newMesh.vertices.Add(new Vector3(rect.right, rect.bottom)); |
|||
newMesh.vertices.Add(new Vector3(rect.right, rect.top)); |
|||
newMesh.vertices.Add(new Vector3(rect.left, rect.bottom)); |
|||
newMesh.vertices.Add(new Vector3(rect.left, rect.top)); |
|||
|
|||
newMesh.triangles = ObjectPool<uiList<int>>.alloc(); |
|||
newMesh.triangles.AddRange(_boundsTriangles); |
|||
newMesh.rawBounds = rect; |
|||
|
|||
newMesh._bounds = newMesh.rawBounds; |
|||
|
|||
return newMesh; |
|||
} |
|||
|
|||
public static uiMeshMesh create(uiMatrix3? matrix, uiList<Vector3> vertices, uiList<int> triangles, |
|||
uiList<Vector2> uv = null, |
|||
uiRect? rawBounds = null) { |
|||
D.assert(vertices != null); |
|||
D.assert(vertices.Count >= 0); |
|||
D.assert(triangles != null); |
|||
D.assert(triangles.Count >= 0); |
|||
D.assert(uv == null || uv.Count == vertices.Count); |
|||
|
|||
uiMeshMesh newMesh = ObjectPool<uiMeshMesh>.alloc(); |
|||
newMesh.matrix = matrix; |
|||
newMesh.vertices = vertices; |
|||
newMesh.triangles = triangles; |
|||
if (uv != null) { |
|||
newMesh.uv = uv; |
|||
} |
|||
|
|||
if (rawBounds == null) { |
|||
if (vertices.Count > 0) { |
|||
float minX = vertices[0].x; |
|||
float maxX = vertices[0].x; |
|||
float minY = vertices[0].y; |
|||
float maxY = vertices[0].y; |
|||
|
|||
for (int i = 1; i < vertices.Count; i++) { |
|||
var vertex = vertices[i]; |
|||
if (vertex.x < minX) { |
|||
minX = vertex.x; |
|||
} |
|||
|
|||
if (vertex.x > maxX) { |
|||
maxX = vertex.x; |
|||
} |
|||
|
|||
if (vertex.y < minY) { |
|||
minY = vertex.y; |
|||
} |
|||
|
|||
if (vertex.y > maxY) { |
|||
maxY = vertex.y; |
|||
} |
|||
} |
|||
|
|||
rawBounds = uiRectHelper.fromLTRB(minX, minY, maxX, maxY); |
|||
} |
|||
else { |
|||
rawBounds = uiRectHelper.zero; |
|||
} |
|||
} |
|||
|
|||
newMesh.rawBounds = rawBounds.Value; |
|||
|
|||
return newMesh; |
|||
} |
|||
|
|||
public uiMeshMesh duplicate() { |
|||
return this.transform(this.matrix); |
|||
} |
|||
|
|||
public uiMeshMesh transform(uiMatrix3? matrix) { |
|||
var vertices = ObjectPool<uiList<Vector3>>.alloc(); |
|||
vertices.SetCapacity(this.vertices.Count); |
|||
vertices.AddRange(this.vertices.data); |
|||
|
|||
var triangles = ObjectPool<uiList<int>>.alloc(); |
|||
triangles.SetCapacity(this.triangles.Count); |
|||
triangles.AddRange(this.triangles.data); |
|||
|
|||
|
|||
uiList<Vector2> uv = null; |
|||
|
|||
if (this.uv != null) { |
|||
uv = ObjectPool<uiList<Vector2>>.alloc(); |
|||
uv.SetCapacity(this.uv.Count); |
|||
uv.AddRange(this.uv.data); |
|||
} |
|||
|
|||
|
|||
var ret = create(matrix, vertices, triangles, uv, this.rawBounds); |
|||
return ret; |
|||
} |
|||
} |
|||
} |
|
|||
namespace Unity.UIWidgets.ui { |
|||
public struct uiOffset { |
|||
public uiOffset(float dx, float dy) { |
|||
this.dx = dx; |
|||
this.dy = dy; |
|||
} |
|||
|
|||
public readonly float dx; |
|||
public readonly float dy; |
|||
|
|||
public static uiOffset? fromOffset(Offset offset) { |
|||
if (offset == null) { |
|||
return null; |
|||
} |
|||
|
|||
var newOffset = new uiOffset(offset.dx, offset.dy); |
|||
return newOffset; |
|||
} |
|||
|
|||
|
|||
public static uiOffset operator -(uiOffset a) { |
|||
return new uiOffset(-a.dx, -a.dy); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 474119e5987c445ec9c091013283edf4 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 56917523cf9a4442e9f6ab6f24772946 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 5d69fe5c05f3d4bd69d76f795f95964d |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: c40e07520bc854d85b57d0021c9bfba6 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using Unity.UIWidgets.foundation; |
|||
using UnityEngine; |
|||
|
|||
namespace Unity.UIWidgets.ui { |
|||
public class uiPath : PoolObject { |
|||
const float _KAPPA90 = 0.5522847493f; |
|||
|
|||
uiList<float> _commands; |
|||
float _commandx; |
|||
float _commandy; |
|||
float _minX, _minY; |
|||
float _maxX, _maxY; |
|||
|
|||
uiPathCache _cache; |
|||
|
|||
public uint pathKey = 0; |
|||
public bool needCache = false; |
|||
|
|||
public static uiPath create(int capacity = 128) { |
|||
uiPath newPath = ObjectPool<uiPath>.alloc(); |
|||
newPath._reset(); |
|||
return newPath; |
|||
} |
|||
|
|||
public uiPath() { |
|||
} |
|||
|
|||
public override void clear() { |
|||
ObjectPool<uiList<float>>.release(this._commands); |
|||
ObjectPool<uiPathCache>.release(this._cache); |
|||
this._cache = null; |
|||
this._commands = null; |
|||
|
|||
this.needCache = false; |
|||
this.pathKey = 0; |
|||
} |
|||
|
|||
void _reset() { |
|||
this._commands = ObjectPool<uiList<float>>.alloc(); |
|||
this._commandx = 0; |
|||
this._commandy = 0; |
|||
this._minX = float.MaxValue; |
|||
this._minY = float.MaxValue; |
|||
this._maxX = float.MinValue; |
|||
this._maxY = float.MinValue; |
|||
ObjectPool<uiPathCache>.release(this._cache); |
|||
this._cache = null; |
|||
} |
|||
|
|||
internal uiPathCache flatten(float scale) { |
|||
scale = Mathf.Round(scale * 2.0f) / 2.0f; // round to 0.5f
|
|||
|
|||
if (this._cache != null && this._cache.canReuse(scale)) { |
|||
return this._cache; |
|||
} |
|||
|
|||
var _cache = uiPathCache.create(scale); |
|||
|
|||
var i = 0; |
|||
while (i < this._commands.Count) { |
|||
var cmd = (uiPathCommand) this._commands[i]; |
|||
switch (cmd) { |
|||
case uiPathCommand.moveTo: |
|||
_cache.addPath(); |
|||
_cache.addPoint(this._commands[i + 1], this._commands[i + 2], uiPointFlags.corner); |
|||
i += 3; |
|||
break; |
|||
case uiPathCommand.lineTo: |
|||
_cache.addPoint(this._commands[i + 1], this._commands[i + 2], uiPointFlags.corner); |
|||
i += 3; |
|||
break; |
|||
case uiPathCommand.bezierTo: |
|||
_cache.tessellateBezier( |
|||
this._commands[i + 1], this._commands[i + 2], |
|||
this._commands[i + 3], this._commands[i + 4], |
|||
this._commands[i + 5], this._commands[i + 6], uiPointFlags.corner); |
|||
i += 7; |
|||
break; |
|||
case uiPathCommand.close: |
|||
_cache.closePath(); |
|||
i++; |
|||
break; |
|||
case uiPathCommand.winding: |
|||
_cache.pathWinding((uiPathWinding) this._commands[i + 1]); |
|||
i += 2; |
|||
break; |
|||
default: |
|||
D.assert(false, () => "unknown cmd: " + cmd); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
_cache.normalize(); |
|||
ObjectPool<uiPathCache>.release(this._cache); |
|||
this._cache = _cache; |
|||
return _cache; |
|||
} |
|||
|
|||
void _expandBounds(float x, float y) { |
|||
if (x < this._minX) { |
|||
this._minX = x; |
|||
} |
|||
|
|||
if (y < this._minY) { |
|||
this._minY = y; |
|||
} |
|||
|
|||
if (x > this._maxX) { |
|||
this._maxX = x; |
|||
} |
|||
|
|||
if (y > this._maxY) { |
|||
this._maxY = y; |
|||
} |
|||
} |
|||
|
|||
void _appendMoveTo(float x, float y) { |
|||
this._commands.Add((float) uiPathCommand.moveTo); |
|||
this._commands.Add(x); |
|||
this._commands.Add(y); |
|||
|
|||
this._commandx = x; |
|||
this._commandy = y; |
|||
|
|||
ObjectPool<uiPathCache>.release(this._cache); |
|||
this._cache = null; |
|||
} |
|||
|
|||
void _appendLineTo(float x, float y) { |
|||
this._expandBounds(this._commandx, this._commandy); |
|||
this._expandBounds(x, y); |
|||
|
|||
this._commands.Add((float) uiPathCommand.lineTo); |
|||
this._commands.Add(x); |
|||
this._commands.Add(y); |
|||
|
|||
this._commandx = x; |
|||
this._commandy = y; |
|||
|
|||
ObjectPool<uiPathCache>.release(this._cache); |
|||
this._cache = null; |
|||
} |
|||
|
|||
void _appendBezierTo(float x1, float y1, float x2, float y2, float x3, float y3) { |
|||
this._expandBounds(this._commandx, this._commandy); |
|||
this._expandBounds(x1, y1); |
|||
this._expandBounds(x2, y2); |
|||
this._expandBounds(x3, y3); |
|||
|
|||
this._commands.Add((float) uiPathCommand.bezierTo); |
|||
this._commands.Add(x1); |
|||
this._commands.Add(y1); |
|||
this._commands.Add(x2); |
|||
this._commands.Add(y2); |
|||
this._commands.Add(x3); |
|||
this._commands.Add(y3); |
|||
|
|||
this._commandx = x3; |
|||
this._commandy = y3; |
|||
|
|||
ObjectPool<uiPathCache>.release(this._cache); |
|||
this._cache = null; |
|||
} |
|||
|
|||
void _appendClose() { |
|||
this._commands.Add((float) uiPathCommand.close); |
|||
|
|||
ObjectPool<uiPathCache>.release(this._cache); |
|||
this._cache = null; |
|||
} |
|||
|
|||
void _appendWinding(float winding) { |
|||
this._commands.Add((float) uiPathCommand.winding); |
|||
this._commands.Add(winding); |
|||
|
|||
ObjectPool<uiPathCache>.release(this._cache); |
|||
this._cache = null; |
|||
} |
|||
|
|||
public void addRect(uiRect rect) { |
|||
this._appendMoveTo(rect.left, rect.top); |
|||
this._appendLineTo(rect.left, rect.bottom); |
|||
this._appendLineTo(rect.right, rect.bottom); |
|||
this._appendLineTo(rect.right, rect.top); |
|||
this._appendClose(); |
|||
} |
|||
|
|||
public void addRect(Rect rect) { |
|||
this._appendMoveTo(rect.left, rect.top); |
|||
this._appendLineTo(rect.left, rect.bottom); |
|||
this._appendLineTo(rect.right, rect.bottom); |
|||
this._appendLineTo(rect.right, rect.top); |
|||
this._appendClose(); |
|||
} |
|||
|
|||
public void addRRect(RRect rrect) { |
|||
float w = rrect.width; |
|||
float h = rrect.height; |
|||
float halfw = Mathf.Abs(w) * 0.5f; |
|||
float halfh = Mathf.Abs(h) * 0.5f; |
|||
float signW = Mathf.Sign(w); |
|||
float signH = Mathf.Sign(h); |
|||
|
|||
float rxBL = Mathf.Min(rrect.blRadiusX, halfw) * signW; |
|||
float ryBL = Mathf.Min(rrect.blRadiusY, halfh) * signH; |
|||
float rxBR = Mathf.Min(rrect.brRadiusX, halfw) * signW; |
|||
float ryBR = Mathf.Min(rrect.brRadiusY, halfh) * signH; |
|||
float rxTR = Mathf.Min(rrect.trRadiusX, halfw) * signW; |
|||
float ryTR = Mathf.Min(rrect.trRadiusY, halfh) * signH; |
|||
float rxTL = Mathf.Min(rrect.tlRadiusX, halfw) * signW; |
|||
float ryTL = Mathf.Min(rrect.tlRadiusY, halfh) * signH; |
|||
float x = rrect.left; |
|||
float y = rrect.top; |
|||
|
|||
this._appendMoveTo(x, y + ryTL); |
|||
this._appendLineTo(x, y + h - ryBL); |
|||
this._appendBezierTo(x, y + h - ryBL * (1 - _KAPPA90), |
|||
x + rxBL * (1 - _KAPPA90), y + h, x + rxBL, y + h); |
|||
this._appendLineTo(x + w - rxBR, y + h); |
|||
this._appendBezierTo(x + w - rxBR * (1 - _KAPPA90), y + h, |
|||
x + w, y + h - ryBR * (1 - _KAPPA90), x + w, y + h - ryBR); |
|||
this._appendLineTo(x + w, y + ryTR); |
|||
this._appendBezierTo(x + w, y + ryTR * (1 - _KAPPA90), |
|||
x + w - rxTR * (1 - _KAPPA90), y, x + w - rxTR, y); |
|||
this._appendLineTo(x + rxTL, y); |
|||
this._appendBezierTo(x + rxTL * (1 - _KAPPA90), y, |
|||
x, y + ryTL * (1 - _KAPPA90), x, y + ryTL); |
|||
this._appendClose(); |
|||
} |
|||
|
|||
public void moveTo(float x, float y) { |
|||
this._appendMoveTo(x, y); |
|||
} |
|||
|
|||
public void lineTo(float x, float y) { |
|||
this._appendLineTo(x, y); |
|||
} |
|||
|
|||
public void winding(PathWinding dir) { |
|||
this._appendWinding((float) dir); |
|||
} |
|||
|
|||
public void addEllipse(float cx, float cy, float rx, float ry) { |
|||
this._appendMoveTo(cx - rx, cy); |
|||
this._appendBezierTo(cx - rx, cy + ry * _KAPPA90, |
|||
cx - rx * _KAPPA90, cy + ry, cx, cy + ry); |
|||
this._appendBezierTo(cx + rx * _KAPPA90, cy + ry, |
|||
cx + rx, cy + ry * _KAPPA90, cx + rx, cy); |
|||
this._appendBezierTo(cx + rx, cy - ry * _KAPPA90, |
|||
cx + rx * _KAPPA90, cy - ry, cx, cy - ry); |
|||
this._appendBezierTo(cx - rx * _KAPPA90, cy - ry, |
|||
cx - rx, cy - ry * _KAPPA90, cx - rx, cy); |
|||
this._appendClose(); |
|||
} |
|||
|
|||
public void addCircle(float cx, float cy, float r) { |
|||
this.addEllipse(cx, cy, r, r); |
|||
} |
|||
|
|||
public void arcTo(Rect rect, float startAngle, float sweepAngle, bool forceMoveTo = true) { |
|||
var mat = Matrix3.makeScale(rect.width / 2, rect.height / 2); |
|||
var center = rect.center; |
|||
mat.postTranslate(center.dx, center.dy); |
|||
|
|||
this._addArcCommands(0, 0, 1, startAngle, startAngle + sweepAngle, |
|||
sweepAngle >= 0 ? PathWinding.clockwise : PathWinding.counterClockwise, forceMoveTo, mat); |
|||
} |
|||
|
|||
public void close() { |
|||
this._appendClose(); |
|||
} |
|||
|
|||
void _addArcCommands( |
|||
float cx, float cy, float r, float a0, float a1, |
|||
PathWinding dir, bool forceMoveTo, Matrix3 transform = null) { |
|||
// Clamp angles
|
|||
float da = a1 - a0; |
|||
if (dir == PathWinding.clockwise) { |
|||
if (Mathf.Abs(da) >= Mathf.PI * 2) { |
|||
da = Mathf.PI * 2; |
|||
} |
|||
else { |
|||
while (da < 0.0f) { |
|||
da += Mathf.PI * 2; |
|||
} |
|||
|
|||
if (da <= 1e-5) { |
|||
return; |
|||
} |
|||
} |
|||
} |
|||
else { |
|||
if (Mathf.Abs(da) >= Mathf.PI * 2) { |
|||
da = -Mathf.PI * 2; |
|||
} |
|||
else { |
|||
while (da > 0.0f) { |
|||
da -= Mathf.PI * 2; |
|||
} |
|||
|
|||
if (da >= -1e-5) { |
|||
return; |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Split arc into max 90 degree segments.
|
|||
int ndivs = Mathf.Max(1, Mathf.Min((int) (Mathf.Abs(da) / (Mathf.PI * 0.5f) + 0.5f), 5)); |
|||
float hda = (da / ndivs) / 2.0f; |
|||
float kappa = Mathf.Abs(4.0f / 3.0f * (1.0f - Mathf.Cos(hda)) / Mathf.Sin(hda)); |
|||
|
|||
if (dir == PathWinding.counterClockwise) { |
|||
kappa = -kappa; |
|||
} |
|||
|
|||
PathCommand move = (forceMoveTo || this._commands.Count == 0) ? PathCommand.moveTo : PathCommand.lineTo; |
|||
float px = 0, py = 0, ptanx = 0, ptany = 0; |
|||
|
|||
for (int i = 0; i <= ndivs; i++) { |
|||
float a = a0 + da * (i / (float) ndivs); |
|||
float dx = Mathf.Cos(a); |
|||
float dy = Mathf.Sin(a); |
|||
float x = cx + dx * r; |
|||
float y = cy + dy * r; |
|||
float tanx = -dy * r * kappa; |
|||
float tany = dx * r * kappa; |
|||
|
|||
if (i == 0) { |
|||
float x1 = x, y1 = y; |
|||
if (transform != null) { |
|||
transform.mapXY(x1, y1, out x1, out y1); |
|||
} |
|||
|
|||
if (move == PathCommand.moveTo) { |
|||
this._appendMoveTo(x1, y1); |
|||
} |
|||
else { |
|||
this._appendLineTo(x1, y1); |
|||
} |
|||
} |
|||
else { |
|||
float c1x = px + ptanx; |
|||
float c1y = py + ptany; |
|||
float c2x = x - tanx; |
|||
float c2y = y - tany; |
|||
float x1 = x; |
|||
float y1 = y; |
|||
if (transform != null) { |
|||
transform.mapXY(c1x, c1y, out c1x, out c1y); |
|||
transform.mapXY(c2x, c2y, out c2x, out c2y); |
|||
transform.mapXY(x1, y1, out x1, out y1); |
|||
} |
|||
|
|||
this._appendBezierTo(c1x, c1y, c2x, c2y, x1, y1); |
|||
} |
|||
|
|||
px = x; |
|||
py = y; |
|||
ptanx = tanx; |
|||
ptany = tany; |
|||
} |
|||
} |
|||
|
|||
public static uiPath fromPath(Path path) { |
|||
D.assert(path != null); |
|||
|
|||
uiPath uipath; |
|||
bool exists = uiPathCacheManager.tryGetUiPath(path.pathKey, out uipath); |
|||
if (exists) { |
|||
return uipath; |
|||
} |
|||
|
|||
var i = 0; |
|||
var _commands = path.commands; |
|||
while (i < _commands.Count) { |
|||
var cmd = (uiPathCommand) _commands[i]; |
|||
switch (cmd) { |
|||
case uiPathCommand.moveTo: { |
|||
float x = _commands[i + 1]; |
|||
float y = _commands[i + 2]; |
|||
uipath._appendMoveTo(x, y); |
|||
} |
|||
i += 3; |
|||
break; |
|||
case uiPathCommand.lineTo: { |
|||
float x = _commands[i + 1]; |
|||
float y = _commands[i + 2]; |
|||
|
|||
uipath._appendLineTo(x, y); |
|||
} |
|||
i += 3; |
|||
break; |
|||
case uiPathCommand.bezierTo: { |
|||
float c1x = _commands[i + 1]; |
|||
float c1y = _commands[i + 2]; |
|||
float c2x = _commands[i + 3]; |
|||
float c2y = _commands[i + 4]; |
|||
float x1 = _commands[i + 5]; |
|||
float y1 = _commands[i + 6]; |
|||
|
|||
uipath._appendBezierTo(c1x, c1y, c2x, c2y, x1, y1); |
|||
} |
|||
i += 7; |
|||
break; |
|||
case uiPathCommand.close: |
|||
uipath._appendClose(); |
|||
i++; |
|||
break; |
|||
case uiPathCommand.winding: |
|||
uipath._appendWinding(_commands[i + 1]); |
|||
i += 2; |
|||
break; |
|||
default: |
|||
D.assert(false, () => "unknown cmd: " + cmd); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
return uipath; |
|||
} |
|||
} |
|||
} |
|
|||
using System.Collections.Generic; |
|||
using Unity.UIWidgets.foundation; |
|||
using UnityEngine; |
|||
|
|||
namespace Unity.UIWidgets.ui { |
|||
class uiPathCache : PoolObject { |
|||
float _distTol; |
|||
float _tessTol; |
|||
|
|||
List<uiPathPath> _paths = new List<uiPathPath>(); |
|||
List<uiPathPoint> _points = new List<uiPathPoint>(); |
|||
|
|||
float _scale; |
|||
|
|||
//mesh cache
|
|||
uiMeshMesh _fillMesh; |
|||
bool _fillConvex; |
|||
|
|||
uiMeshMesh _strokeMesh; |
|||
float _strokeWidth; |
|||
StrokeCap _lineCap; |
|||
StrokeJoin _lineJoin; |
|||
float _miterLimit; |
|||
|
|||
public static uiPathCache create(float scale) { |
|||
uiPathCache newPathCache = ObjectPool<uiPathCache>.alloc(); |
|||
newPathCache._distTol = 0.01f / scale; |
|||
newPathCache._tessTol = 0.25f / scale; |
|||
newPathCache._scale = scale; |
|||
return newPathCache; |
|||
} |
|||
|
|||
public bool canReuse(float scale) { |
|||
if (this._scale != scale) { |
|||
return false; |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
public override void clear() { |
|||
this._paths.Clear(); |
|||
this._points.Clear(); |
|||
ObjectPool<uiMeshMesh>.release(this._fillMesh); |
|||
this._fillMesh = null; |
|||
|
|||
ObjectPool<uiMeshMesh>.release(this._strokeMesh); |
|||
this._strokeMesh = null; |
|||
} |
|||
|
|||
public uiPathCache() { |
|||
} |
|||
|
|||
public void addPath() { |
|||
this._paths.Add(uiPathPath.create( |
|||
first: this._points.Count, |
|||
winding: uiPathWinding.counterClockwise |
|||
)); |
|||
} |
|||
|
|||
public void addPoint(float x, float y, uiPointFlags flags) { |
|||
this._addPoint(uiPathPoint.create(x: x, y: y, flags: flags)); |
|||
} |
|||
|
|||
void _addPoint(uiPathPoint point) { |
|||
if (this._paths.Count == 0) { |
|||
this.addPath(); |
|||
this.addPoint(0, 0, uiPointFlags.corner); |
|||
} |
|||
|
|||
var path = this._paths[this._paths.Count - 1]; |
|||
if (path.count > 0) { |
|||
var pt = this._points[this._points.Count - 1]; |
|||
if (uiPathUtils.ptEquals(pt.x, pt.y, point.x, point.y, this._distTol)) { |
|||
pt.flags |= point.flags; |
|||
this._points[this._points.Count - 1] = pt; |
|||
return; |
|||
} |
|||
} |
|||
|
|||
this._points.Add(point); |
|||
path.count++; |
|||
this._paths[this._paths.Count - 1] = path; |
|||
} |
|||
|
|||
public void tessellateBezier( |
|||
float x2, float y2, |
|||
float x3, float y3, float x4, float y4, |
|||
uiPointFlags flags) { |
|||
float x1, y1; |
|||
if (this._points.Count == 0) { |
|||
x1 = 0; |
|||
y1 = 0; |
|||
} |
|||
else { |
|||
var pt = this._points[this._points.Count - 1]; |
|||
x1 = pt.x; |
|||
y1 = pt.y; |
|||
} |
|||
|
|||
if (x1 == x2 && x1 == x3 && x1 == x4 && |
|||
y1 == y2 && y1 == y3 && y1 == y4) { |
|||
return; |
|||
} |
|||
|
|||
var points = uiTessellationGenerator.tessellateBezier(x1, y1, x2, y2, x3, y3, x4, y4, this._tessTol); |
|||
D.assert(points.Count > 0); |
|||
for (int i = 0; i < points.Count; i++) { |
|||
var point = points[i]; |
|||
if (i == points.Count - 1) { |
|||
this._addPoint(uiPathPoint.create( |
|||
x: point.x + x1, |
|||
y: point.y + y1, |
|||
flags: flags |
|||
)); |
|||
} |
|||
else { |
|||
this._addPoint(uiPathPoint.create( |
|||
x: point.x + x1, |
|||
y: point.y + y1 |
|||
)); |
|||
} |
|||
} |
|||
} |
|||
|
|||
public void closePath() { |
|||
if (this._paths.Count == 0) { |
|||
return; |
|||
} |
|||
|
|||
var path = this._paths[this._paths.Count - 1]; |
|||
path.closed = true; |
|||
this._paths[this._paths.Count - 1] = path; |
|||
} |
|||
|
|||
public void pathWinding(uiPathWinding winding) { |
|||
if (this._paths.Count == 0) { |
|||
return; |
|||
} |
|||
|
|||
var path = this._paths[this._paths.Count - 1]; |
|||
path.winding = winding; |
|||
this._paths[this._paths.Count - 1] = path; |
|||
} |
|||
|
|||
public void normalize() { |
|||
var points = this._points; |
|||
var paths = this._paths; |
|||
for (var j = 0; j < paths.Count; j++) { |
|||
var path = paths[j]; |
|||
if (path.count <= 1) { |
|||
continue; |
|||
} |
|||
|
|||
var ip0 = path.first + path.count - 1; |
|||
var ip1 = path.first; |
|||
|
|||
var p0 = points[ip0]; |
|||
var p1 = points[ip1]; |
|||
if (uiPathUtils.ptEquals(p0.x, p0.y, p1.x, p1.y, this._distTol)) { |
|||
path.count--; |
|||
path.closed = true; |
|||
paths[j] = path; |
|||
} |
|||
|
|||
if (path.count > 2) { |
|||
if (path.winding == uiPathWinding.clockwise) { |
|||
uiPathUtils.polyReverse(points, path.first, path.count); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
uiList<Vector3> _expandFill() { |
|||
var points = this._points; |
|||
var paths = this._paths; |
|||
for (var j = 0; j < paths.Count; j++) { |
|||
var path = paths[j]; |
|||
if (path.count <= 2) { |
|||
continue; |
|||
} |
|||
|
|||
var ip0 = path.first + path.count - 1; |
|||
var ip1 = path.first; |
|||
for (var i = 0; i < path.count; i++) { |
|||
var p0 = points[ip0]; |
|||
var p1 = points[ip1]; |
|||
p0.dx = p1.x - p0.x; // no need to normalize
|
|||
p0.dy = p1.y - p0.y; |
|||
points[ip0] = p0; |
|||
ip0 = ip1++; |
|||
} |
|||
|
|||
path.convex = true; |
|||
|
|||
ip0 = path.first + path.count - 1; |
|||
ip1 = path.first; |
|||
for (var i = 0; i < path.count; i++) { |
|||
var p0 = points[ip0]; |
|||
var p1 = points[ip1]; |
|||
|
|||
float cross = p1.dx * p0.dy - p0.dx * p1.dy; |
|||
if (cross < 0.0f) { |
|||
path.convex = false; |
|||
} |
|||
|
|||
ip0 = ip1++; |
|||
} |
|||
|
|||
paths[j] = path; |
|||
} |
|||
|
|||
|
|||
var cvertices = 0; |
|||
for (var i = 0; i < paths.Count; i++) { |
|||
var path = paths[i]; |
|||
if (path.count <= 2) { |
|||
continue; |
|||
} |
|||
|
|||
cvertices += path.count; |
|||
} |
|||
|
|||
var _vertices = ObjectPool<uiList<Vector3>>.alloc(); |
|||
_vertices.SetCapacity(cvertices); |
|||
for (var i = 0; i < paths.Count; i++) { |
|||
var path = paths[i]; |
|||
if (path.count <= 2) { |
|||
continue; |
|||
} |
|||
|
|||
path.ifill = _vertices.Count; |
|||
for (var j = 0; j < path.count; j++) { |
|||
var p = points[path.first + j]; |
|||
_vertices.Add(new Vector2(p.x, p.y)); |
|||
} |
|||
|
|||
path.nfill = _vertices.Count - path.ifill; |
|||
paths[i] = path; |
|||
} |
|||
|
|||
return _vertices; |
|||
} |
|||
|
|||
public uiMeshMesh getFillMesh(out bool convex) { |
|||
if (this._fillMesh != null) { |
|||
convex = this._fillConvex; |
|||
return this._fillMesh; |
|||
} |
|||
|
|||
var vertices = this._expandFill(); |
|||
|
|||
var paths = this._paths; |
|||
|
|||
var cindices = 0; |
|||
for (var i = 0; i < paths.Count; i++) { |
|||
var path = paths[i]; |
|||
if (path.count <= 2) { |
|||
continue; |
|||
} |
|||
|
|||
if (path.nfill > 0) { |
|||
D.assert(path.nfill >= 2); |
|||
cindices += (path.nfill - 2) * 3; |
|||
} |
|||
} |
|||
|
|||
var indices = ObjectPool<uiList<int>>.alloc(); |
|||
indices.SetCapacity(cindices); |
|||
for (var i = 0; i < paths.Count; i++) { |
|||
var path = paths[i]; |
|||
if (path.count <= 2) { |
|||
continue; |
|||
} |
|||
|
|||
if (path.nfill > 0) { |
|||
for (var j = 2; j < path.nfill; j++) { |
|||
indices.Add(path.ifill); |
|||
indices.Add(path.ifill + j); |
|||
indices.Add(path.ifill + j - 1); |
|||
} |
|||
} |
|||
} |
|||
|
|||
D.assert(indices.Count == cindices); |
|||
|
|||
var mesh = uiMeshMesh.create(null, vertices, indices); |
|||
this._fillMesh = mesh; |
|||
|
|||
this._fillConvex = false; |
|||
for (var i = 0; i < paths.Count; i++) { |
|||
var path = paths[i]; |
|||
if (path.count <= 2) { |
|||
continue; |
|||
} |
|||
|
|||
if (this._fillConvex) { |
|||
// if more than two paths, convex is false.
|
|||
this._fillConvex = false; |
|||
break; |
|||
} |
|||
|
|||
if (!path.convex) { |
|||
// if not convex, convex is false.
|
|||
break; |
|||
} |
|||
|
|||
this._fillConvex = true; |
|||
} |
|||
|
|||
convex = this._fillConvex; |
|||
return this._fillMesh; |
|||
} |
|||
|
|||
void _calculateJoins(float w, StrokeJoin lineJoin, float miterLimit) { |
|||
float iw = w > 0.0f ? 1.0f / w : 0.0f; |
|||
|
|||
var points = this._points; |
|||
var paths = this._paths; |
|||
for (var i = 0; i < paths.Count; i++) { |
|||
var path = paths[i]; |
|||
if (path.count <= 1) { |
|||
continue; |
|||
} |
|||
|
|||
var ip0 = path.first + path.count - 1; |
|||
var ip1 = path.first; |
|||
|
|||
for (var j = 0; j < path.count; j++) { |
|||
var p0 = points[ip0]; |
|||
var p1 = points[ip1]; |
|||
p0.dx = p1.x - p0.x; |
|||
p0.dy = p1.y - p0.y; |
|||
p0.len = uiPathUtils.normalize(ref p0.dx, ref p0.dy); |
|||
points[ip0] = p0; |
|||
ip0 = ip1++; |
|||
} |
|||
|
|||
ip0 = path.first + path.count - 1; |
|||
ip1 = path.first; |
|||
for (var j = 0; j < path.count; j++) { |
|||
var p0 = points[ip0]; |
|||
var p1 = points[ip1]; |
|||
float dlx0 = p0.dy; |
|||
float dly0 = -p0.dx; |
|||
float dlx1 = p1.dy; |
|||
float dly1 = -p1.dx; |
|||
|
|||
// Calculate extrusions
|
|||
p1.dmx = (dlx0 + dlx1) * 0.5f; |
|||
p1.dmy = (dly0 + dly1) * 0.5f; |
|||
float dmr2 = p1.dmx * p1.dmx + p1.dmy * p1.dmy; |
|||
if (dmr2 > 0.000001f) { |
|||
float scale = 1.0f / dmr2; |
|||
if (scale > 600.0f) { |
|||
scale = 600.0f; |
|||
} |
|||
|
|||
p1.dmx *= scale; |
|||
p1.dmy *= scale; |
|||
} |
|||
|
|||
// Clear flags, but keep the corner.
|
|||
p1.flags &= uiPointFlags.corner; |
|||
|
|||
// Keep track of left turns.
|
|||
float cross = p1.dx * p0.dy - p0.dx * p1.dy; |
|||
if (cross > 0.0f) { |
|||
p1.flags |= uiPointFlags.left; |
|||
} |
|||
|
|||
// Calculate if we should use bevel or miter for inner join.
|
|||
float limit = Mathf.Max(1.01f, Mathf.Min(p0.len, p1.len) * iw); |
|||
if (dmr2 * limit * limit < 1.0f) { |
|||
p1.flags |= uiPointFlags.innerBevel; |
|||
} |
|||
|
|||
// Check to see if the corner needs to be beveled.
|
|||
if ((p1.flags & uiPointFlags.corner) != 0) { |
|||
if (lineJoin == StrokeJoin.bevel || |
|||
lineJoin == StrokeJoin.round || dmr2 * miterLimit * miterLimit < 1.0f) { |
|||
p1.flags |= uiPointFlags.bevel; |
|||
} |
|||
} |
|||
|
|||
points[ip0] = p0; |
|||
points[ip1] = p1; |
|||
|
|||
ip0 = ip1++; |
|||
} |
|||
} |
|||
} |
|||
|
|||
uiList<Vector3> _expandStroke(float w, StrokeCap lineCap, StrokeJoin lineJoin, float miterLimit) { |
|||
this._calculateJoins(w, lineJoin, miterLimit); |
|||
|
|||
int ncap = 0; |
|||
if (lineCap == StrokeCap.round || lineJoin == StrokeJoin.round) { |
|||
ncap = uiPathUtils.curveDivs(w, Mathf.PI, this._tessTol); |
|||
} |
|||
|
|||
var points = this._points; |
|||
var paths = this._paths; |
|||
|
|||
var cvertices = 0; |
|||
for (var i = 0; i < paths.Count; i++) { |
|||
var path = paths[i]; |
|||
if (path.count <= 1) { |
|||
continue; |
|||
} |
|||
|
|||
cvertices += path.count * 2; |
|||
cvertices += 4; |
|||
} |
|||
|
|||
var _vertices = ObjectPool<uiList<Vector3>>.alloc(); |
|||
_vertices.SetCapacity(cvertices); |
|||
for (var i = 0; i < paths.Count; i++) { |
|||
var path = paths[i]; |
|||
if (path.count <= 1) { |
|||
continue; |
|||
} |
|||
|
|||
path.istroke = _vertices.Count; |
|||
|
|||
int s, e, ip0, ip1; |
|||
if (path.closed) { |
|||
ip0 = path.first + path.count - 1; |
|||
ip1 = path.first; |
|||
s = 0; |
|||
e = path.count; |
|||
} |
|||
else { |
|||
ip0 = path.first; |
|||
ip1 = path.first + 1; |
|||
s = 1; |
|||
e = path.count - 1; |
|||
} |
|||
|
|||
var p0 = points[ip0]; |
|||
var p1 = points[ip1]; |
|||
|
|||
if (!path.closed) { |
|||
if (lineCap == StrokeCap.butt) { |
|||
_vertices.buttCapStart(p0, p0.dx, p0.dy, w, 0.0f); |
|||
} |
|||
else if (lineCap == StrokeCap.square) { |
|||
_vertices.buttCapStart(p0, p0.dx, p0.dy, w, w); |
|||
} |
|||
else { |
|||
// round
|
|||
_vertices.roundCapStart(p0, p0.dx, p0.dy, w, ncap); |
|||
} |
|||
} |
|||
|
|||
for (var j = s; j < e; j++) { |
|||
p0 = points[ip0]; |
|||
p1 = points[ip1]; |
|||
|
|||
if ((p1.flags & (uiPointFlags.bevel | uiPointFlags.innerBevel)) != 0) { |
|||
if (lineJoin == StrokeJoin.round) { |
|||
_vertices.roundJoin(p0, p1, w, w, ncap); |
|||
} |
|||
else { |
|||
_vertices.bevelJoin(p0, p1, w, w); |
|||
} |
|||
} |
|||
else { |
|||
_vertices.Add(new Vector2(p1.x + p1.dmx * w, p1.y + p1.dmy * w)); |
|||
_vertices.Add(new Vector2(p1.x - p1.dmx * w, p1.y - p1.dmy * w)); |
|||
} |
|||
|
|||
ip0 = ip1++; |
|||
} |
|||
|
|||
if (!path.closed) { |
|||
p0 = points[ip0]; |
|||
p1 = points[ip1]; |
|||
if (lineCap == StrokeCap.butt) { |
|||
_vertices.buttCapEnd(p1, p0.dx, p0.dy, w, 0.0f); |
|||
} |
|||
else if (lineCap == StrokeCap.square) { |
|||
_vertices.buttCapEnd(p1, p0.dx, p0.dy, w, w); |
|||
} |
|||
else { |
|||
// round
|
|||
_vertices.roundCapEnd(p1, p0.dx, p0.dy, w, ncap); |
|||
} |
|||
} |
|||
else { |
|||
_vertices.Add(_vertices[path.istroke]); |
|||
_vertices.Add(_vertices[path.istroke + 1]); |
|||
} |
|||
|
|||
path.nstroke = _vertices.Count - path.istroke; |
|||
paths[i] = path; |
|||
} |
|||
|
|||
return _vertices; |
|||
} |
|||
|
|||
public uiMeshMesh getStrokeMesh(float strokeWidth, StrokeCap lineCap, StrokeJoin lineJoin, float miterLimit) { |
|||
if (this._strokeMesh != null && |
|||
this._strokeWidth == strokeWidth && |
|||
this._lineCap == lineCap && |
|||
this._lineJoin == lineJoin && |
|||
this._miterLimit == miterLimit) { |
|||
return this._strokeMesh; |
|||
} |
|||
|
|||
var vertices = this._expandStroke(strokeWidth, lineCap, lineJoin, miterLimit); |
|||
|
|||
var paths = this._paths; |
|||
|
|||
var cindices = 0; |
|||
for (var i = 0; i < paths.Count; i++) { |
|||
var path = paths[i]; |
|||
if (path.count <= 1) { |
|||
continue; |
|||
} |
|||
|
|||
if (path.nstroke > 0) { |
|||
D.assert(path.nstroke >= 2); |
|||
cindices += (path.nstroke - 2) * 3; |
|||
} |
|||
} |
|||
|
|||
var indices = ObjectPool<uiList<int>>.alloc(); |
|||
indices.SetCapacity(cindices); |
|||
for (var i = 0; i < paths.Count; i++) { |
|||
var path = paths[i]; |
|||
if (path.count <= 1) { |
|||
continue; |
|||
} |
|||
|
|||
if (path.nstroke > 0) { |
|||
for (var j = 2; j < path.nstroke; j++) { |
|||
if ((j & 1) == 0) { |
|||
indices.Add(path.istroke + j - 1); |
|||
indices.Add(path.istroke + j - 2); |
|||
indices.Add(path.istroke + j); |
|||
} |
|||
else { |
|||
indices.Add(path.istroke + j - 2); |
|||
indices.Add(path.istroke + j - 1); |
|||
indices.Add(path.istroke + j); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
D.assert(indices.Count == cindices); |
|||
|
|||
ObjectPool<uiMeshMesh>.release(this._strokeMesh); |
|||
this._strokeMesh = uiMeshMesh.create(null, vertices, indices); |
|||
this._strokeWidth = strokeWidth; |
|||
this._lineCap = lineCap; |
|||
this._lineJoin = lineJoin; |
|||
this._miterLimit = miterLimit; |
|||
return this._strokeMesh; |
|||
} |
|||
} |
|||
} |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using UnityEngine; |
|||
|
|||
namespace Unity.UIWidgets.ui { |
|||
public enum uiPathWinding { |
|||
counterClockwise = 1, // which just means the order as the input is.
|
|||
clockwise = 2, // which just means the reversed order.
|
|||
} |
|||
|
|||
enum uiPathCommand { |
|||
moveTo, |
|||
lineTo, |
|||
bezierTo, |
|||
close, |
|||
winding, |
|||
} |
|||
|
|||
[Flags] |
|||
enum uiPointFlags { |
|||
corner = 0x01, |
|||
left = 0x02, |
|||
bevel = 0x04, |
|||
innerBevel = 0x08, |
|||
} |
|||
|
|||
struct uiPathPoint { |
|||
public float x, y; |
|||
public float dx, dy; |
|||
public float len; |
|||
public float dmx, dmy; |
|||
public uiPointFlags flags; |
|||
|
|||
public static uiPathPoint create(float x = 0, float y = 0, float dx = 0, float dy = 0, float len = 0, |
|||
float dmx = 0, float dmy = 0, |
|||
uiPointFlags flags = uiPointFlags.corner) { |
|||
uiPathPoint newPoint = new uiPathPoint(); |
|||
newPoint.x = x; |
|||
newPoint.y = y; |
|||
newPoint.dx = dx; |
|||
newPoint.dy = dy; |
|||
newPoint.len = len; |
|||
newPoint.dmx = dmx; |
|||
newPoint.dmy = dmy; |
|||
newPoint.flags = flags; |
|||
return newPoint; |
|||
} |
|||
} |
|||
|
|||
struct uiPathPath { |
|||
public int first; |
|||
public int count; |
|||
public bool closed; |
|||
public int ifill; |
|||
public int nfill; |
|||
public int istroke; |
|||
public int nstroke; |
|||
public uiPathWinding winding; |
|||
public bool convex; |
|||
|
|||
public static uiPathPath create(int first = 0, int count = 0, bool closed = false, int ifill = 0, int nfill = 0, |
|||
int istroke = 0, |
|||
int nstroke = 0, uiPathWinding winding = uiPathWinding.counterClockwise, bool convex = false) { |
|||
uiPathPath newPath = new uiPathPath(); |
|||
newPath.first = first; |
|||
newPath.count = count; |
|||
newPath.closed = closed; |
|||
newPath.ifill = ifill; |
|||
newPath.nfill = nfill; |
|||
newPath.istroke = istroke; |
|||
newPath.nstroke = nstroke; |
|||
newPath.winding = winding; |
|||
newPath.convex = convex; |
|||
|
|||
return newPath; |
|||
} |
|||
} |
|||
|
|||
static class uiPathUtils { |
|||
public static bool ptEquals(float x1, float y1, float x2, float y2, float tol) { |
|||
float dx = x2 - x1; |
|||
float dy = y2 - y1; |
|||
|
|||
if (dx <= -tol || dx >= tol || dy <= -tol || dy >= tol) { |
|||
return false; |
|||
} |
|||
|
|||
return dx * dx + dy * dy < tol * tol; |
|||
} |
|||
|
|||
public static void polyReverse(List<uiPathPoint> pts, int s, int npts) { |
|||
int i = s, j = s + npts - 1; |
|||
while (i < j) { |
|||
var tmp = pts[i]; |
|||
pts[i] = pts[j]; |
|||
pts[j] = tmp; |
|||
i++; |
|||
j--; |
|||
} |
|||
} |
|||
|
|||
public static float normalize(ref float x, ref float y) { |
|||
float d = Mathf.Sqrt(x * x + y * y); |
|||
if (d > 1e-6f) { |
|||
float id = 1.0f / d; |
|||
x *= id; |
|||
y *= id; |
|||
} |
|||
|
|||
return d; |
|||
} |
|||
|
|||
public static void buttCapStart(this uiList<Vector3> dst, uiPathPoint p, |
|||
float dx, float dy, float w, float d) { |
|||
float px = p.x - dx * d; |
|||
float py = p.y - dy * d; |
|||
float dlx = dy; |
|||
float dly = -dx; |
|||
|
|||
dst.Add(new Vector2(px + dlx * w, py + dly * w)); |
|||
dst.Add(new Vector2(px - dlx * w, py - dly * w)); |
|||
} |
|||
|
|||
public static void buttCapEnd(this uiList<Vector3> dst, uiPathPoint p, |
|||
float dx, float dy, float w, float d) { |
|||
float px = p.x + dx * d; |
|||
float py = p.y + dy * d; |
|||
float dlx = dy; |
|||
float dly = -dx; |
|||
|
|||
dst.Add(new Vector2(px + dlx * w, py + dly * w)); |
|||
dst.Add(new Vector2(px - dlx * w, py - dly * w)); |
|||
} |
|||
|
|||
public static void roundCapStart(this uiList<Vector3> dst, uiPathPoint p, |
|||
float dx, float dy, float w, int ncap) { |
|||
float px = p.x; |
|||
float py = p.y; |
|||
float dlx = dy; |
|||
float dly = -dx; |
|||
|
|||
for (var i = 0; i < ncap; i++) { |
|||
float a = (float) i / (ncap - 1) * Mathf.PI; |
|||
float ax = Mathf.Cos(a) * w, ay = Mathf.Sin(a) * w; |
|||
dst.Add(new Vector2(px - dlx * ax - dx * ay, py - dly * ax - dy * ay)); |
|||
dst.Add(new Vector2(px, py)); |
|||
} |
|||
|
|||
dst.Add(new Vector2(px + dlx * w, py + dly * w)); |
|||
dst.Add(new Vector2(px - dlx * w, py - dly * w)); |
|||
} |
|||
|
|||
public static void roundCapEnd(this uiList<Vector3> dst, uiPathPoint p, |
|||
float dx, float dy, float w, int ncap) { |
|||
float px = p.x; |
|||
float py = p.y; |
|||
float dlx = dy; |
|||
float dly = -dx; |
|||
|
|||
dst.Add(new Vector2(px + dlx * w, py + dly * w)); |
|||
dst.Add(new Vector2(px - dlx * w, py - dly * w)); |
|||
|
|||
for (var i = 0; i < ncap; i++) { |
|||
float a = (float) i / (ncap - 1) * Mathf.PI; |
|||
float ax = Mathf.Cos(a) * w, ay = Mathf.Sin(a) * w; |
|||
dst.Add(new Vector2(px, py)); |
|||
dst.Add(new Vector2(px - dlx * ax + dx * ay, py - dly * ax + dy * ay)); |
|||
} |
|||
} |
|||
|
|||
public static void chooseBevel(bool bevel, uiPathPoint p0, uiPathPoint p1, float w, |
|||
out float x0, out float y0, out float x1, out float y1) { |
|||
if (bevel) { |
|||
x0 = p1.x + p0.dy * w; |
|||
y0 = p1.y - p0.dx * w; |
|||
x1 = p1.x + p1.dy * w; |
|||
y1 = p1.y - p1.dx * w; |
|||
} |
|||
else { |
|||
x0 = p1.x + p1.dmx * w; |
|||
y0 = p1.y + p1.dmy * w; |
|||
x1 = p1.x + p1.dmx * w; |
|||
y1 = p1.y + p1.dmy * w; |
|||
} |
|||
} |
|||
|
|||
public static int curveDivs(float r, float arc, float tol) { |
|||
float da = Mathf.Acos(r / (r + tol)) * 2.0f; |
|||
return Mathf.Max(2, Mathf.CeilToInt(arc / da)); |
|||
} |
|||
|
|||
public static void roundJoin(this uiList<Vector3> dst, uiPathPoint p0, uiPathPoint p1, |
|||
float lw, float rw, int ncap) { |
|||
float dlx0 = p0.dy; |
|||
float dly0 = -p0.dx; |
|||
float dlx1 = p1.dy; |
|||
float dly1 = -p1.dx; |
|||
|
|||
if ((p1.flags & uiPointFlags.left) != 0) { |
|||
float lx0, ly0, lx1, ly1; |
|||
chooseBevel((p1.flags & uiPointFlags.innerBevel) != 0, p0, p1, lw, |
|||
out lx0, out ly0, out lx1, out ly1); |
|||
|
|||
float a0 = Mathf.Atan2(-dly0, -dlx0); |
|||
float a1 = Mathf.Atan2(-dly1, -dlx1); |
|||
if (a1 > a0) { |
|||
a1 -= Mathf.PI * 2; |
|||
} |
|||
|
|||
dst.Add(new Vector2(lx0, ly0)); |
|||
dst.Add(new Vector2(p1.x - dlx0 * rw, p1.y - dly0 * rw)); |
|||
|
|||
var n = Mathf.CeilToInt((a0 - a1) / Mathf.PI * ncap).clamp(2, ncap); |
|||
for (var i = 0; i < n; i++) { |
|||
float u = (float) i / (n - 1); |
|||
float a = a0 + u * (a1 - a0); |
|||
float rx = p1.x + Mathf.Cos(a) * rw; |
|||
float ry = p1.y + Mathf.Sin(a) * rw; |
|||
|
|||
dst.Add(new Vector2(p1.x, p1.y)); |
|||
dst.Add(new Vector2(rx, ry)); |
|||
} |
|||
|
|||
dst.Add(new Vector2(lx1, ly1)); |
|||
dst.Add(new Vector2(p1.x - dlx1 * rw, p1.y - dly1 * rw)); |
|||
} |
|||
else { |
|||
float rx0, ry0, rx1, ry1; |
|||
chooseBevel((p1.flags & uiPointFlags.innerBevel) != 0, p0, p1, -rw, |
|||
out rx0, out ry0, out rx1, out ry1); |
|||
|
|||
float a0 = Mathf.Atan2(dly0, dlx0); |
|||
float a1 = Mathf.Atan2(dly1, dlx1); |
|||
if (a1 < a0) { |
|||
a1 += Mathf.PI * 2; |
|||
} |
|||
|
|||
dst.Add(new Vector2(p1.x + dlx0 * lw, p1.y + dly0 * lw)); |
|||
dst.Add(new Vector2(rx0, ry0)); |
|||
|
|||
var n = Mathf.CeilToInt((a1 - a0) / Mathf.PI * ncap).clamp(2, ncap); |
|||
for (var i = 0; i < n; i++) { |
|||
float u = (float) i / (n - 1); |
|||
float a = a0 + u * (a1 - a0); |
|||
float lx = p1.x + Mathf.Cos(a) * lw; |
|||
float ly = p1.y + Mathf.Sin(a) * lw; |
|||
|
|||
dst.Add(new Vector2(lx, ly)); |
|||
dst.Add(new Vector2(p1.x, p1.y)); |
|||
} |
|||
|
|||
dst.Add(new Vector2(p1.x + dlx1 * lw, p1.y + dly1 * lw)); |
|||
dst.Add(new Vector2(rx1, ry1)); |
|||
} |
|||
} |
|||
|
|||
public static void bevelJoin(this uiList<Vector3> dst, uiPathPoint p0, uiPathPoint p1, |
|||
float lw, float rw) { |
|||
float rx0, ry0, rx1, ry1; |
|||
float lx0, ly0, lx1, ly1; |
|||
|
|||
float dlx0 = p0.dy; |
|||
float dly0 = -p0.dx; |
|||
float dlx1 = p1.dy; |
|||
float dly1 = -p1.dx; |
|||
|
|||
if ((p1.flags & uiPointFlags.left) != 0) { |
|||
chooseBevel((p1.flags & uiPointFlags.innerBevel) != 0, p0, p1, lw, |
|||
out lx0, out ly0, out lx1, out ly1); |
|||
|
|||
dst.Add(new Vector2 {x = lx0, y = ly0}); |
|||
dst.Add(new Vector2 {x = p1.x - dlx0 * rw, y = p1.y - dly0 * rw}); |
|||
|
|||
if ((p1.flags & uiPointFlags.bevel) != 0) { |
|||
dst.Add(new Vector2(lx0, ly0)); |
|||
dst.Add(new Vector2(p1.x - dlx0 * rw, p1.y - dly0 * rw)); |
|||
dst.Add(new Vector2(lx1, ly1)); |
|||
dst.Add(new Vector2(p1.x - dlx1 * rw, p1.y - dly1 * rw)); |
|||
} |
|||
else { |
|||
rx0 = p1.x - p1.dmx * rw; |
|||
ry0 = p1.y - p1.dmy * rw; |
|||
dst.Add(new Vector2(p1.x, p1.y)); |
|||
dst.Add(new Vector2(p1.x - dlx0 * rw, p1.y - dly0 * rw)); |
|||
dst.Add(new Vector2(rx0, ry0)); |
|||
dst.Add(new Vector2(rx0, ry0)); |
|||
dst.Add(new Vector2(p1.x, p1.y)); |
|||
dst.Add(new Vector2(p1.x - dlx1 * rw, p1.y - dly1 * rw)); |
|||
} |
|||
|
|||
dst.Add(new Vector2(lx1, ly1)); |
|||
dst.Add(new Vector2(p1.x - dlx1 * rw, p1.y - dly1 * rw)); |
|||
} |
|||
else { |
|||
chooseBevel((p1.flags & uiPointFlags.innerBevel) != 0, p0, p1, -rw, |
|||
out rx0, out ry0, out rx1, out ry1); |
|||
|
|||
dst.Add(new Vector2(p1.x + dlx0 * lw, p1.y + dly0 * lw)); |
|||
dst.Add(new Vector2(rx0, ry0)); |
|||
|
|||
if ((p1.flags & uiPointFlags.bevel) != 0) { |
|||
dst.Add(new Vector2(p1.x + dlx0 * lw, p1.y + dly0 * lw)); |
|||
dst.Add(new Vector2(rx0, ry0)); |
|||
dst.Add(new Vector2(p1.x + dlx1 * lw, p1.y + dly1 * lw)); |
|||
dst.Add(new Vector2(rx1, ry1)); |
|||
} |
|||
else { |
|||
lx0 = p1.x + p1.dmx * lw; |
|||
ly0 = p1.y + p1.dmy * lw; |
|||
dst.Add(new Vector2(p1.x + dlx0 * lw, p1.y + dly0 * lw)); |
|||
dst.Add(new Vector2(p1.x, p1.y)); |
|||
dst.Add(new Vector2(lx0, ly0)); |
|||
dst.Add(new Vector2(lx0, ly0)); |
|||
dst.Add(new Vector2(p1.x + dlx1 * lw, p1.y + dly1 * lw)); |
|||
dst.Add(new Vector2(p1.x, p1.y)); |
|||
} |
|||
|
|||
dst.Add(new Vector2(p1.x + dlx1 * lw, p1.y + dly1 * lw)); |
|||
dst.Add(new Vector2(rx1, ry1)); |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using UnityEngine; |
|||
|
|||
namespace Unity.UIWidgets.ui { |
|||
class uiTessellationKey : PoolObject, IEquatable<uiTessellationKey> { |
|||
public float x2; |
|||
public float y2; |
|||
public float x3; |
|||
public float y3; |
|||
public float x4; |
|||
public float y4; |
|||
public float tessTol; |
|||
|
|||
public static uiTessellationKey create(float x1, float y1, float x2, float y2, float x3, float y3, float x4, |
|||
float y4, |
|||
float tessTol) { |
|||
var newKey = ObjectPool<uiTessellationKey>.alloc(); |
|||
newKey.x2 = x2 - x1; |
|||
newKey.y2 = y2 - y1; |
|||
newKey.x3 = x3 - x1; |
|||
newKey.y3 = y3 - y1; |
|||
newKey.x4 = x4 - x1; |
|||
newKey.y4 = y4 - y1; |
|||
newKey.tessTol = tessTol; |
|||
|
|||
return newKey; |
|||
} |
|||
|
|||
public uiTessellationKey() { |
|||
} |
|||
|
|||
public bool Equals(uiTessellationKey other) { |
|||
if (ReferenceEquals(null, other)) { |
|||
return false; |
|||
} |
|||
|
|||
if (ReferenceEquals(this, other)) { |
|||
return true; |
|||
} |
|||
|
|||
return this.x2 == other.x2 && this.y2 == other.y2 && this.x3 == other.x3 && |
|||
this.y3 == other.y3 && this.x4 == other.x4 && this.y4 == other.y4 && |
|||
this.tessTol == other.tessTol; |
|||
} |
|||
|
|||
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((uiTessellationKey) obj); |
|||
} |
|||
|
|||
public override unsafe int GetHashCode() { |
|||
unchecked { |
|||
var hashCode = 0; |
|||
float x = this.x2; |
|||
hashCode ^= *(int*) &x; |
|||
x = this.y2; |
|||
hashCode = (hashCode * 13) ^ *(int*) &x; |
|||
x = this.x3; |
|||
hashCode = (hashCode * 13) ^ *(int*) &x; |
|||
x = this.y3; |
|||
hashCode = (hashCode * 13) ^ *(int*) &x; |
|||
x = this.x4; |
|||
hashCode = (hashCode * 13) ^ *(int*) &x; |
|||
x = this.y4; |
|||
hashCode = (hashCode * 13) ^ *(int*) &x; |
|||
x = this.tessTol; |
|||
hashCode = (hashCode * 13) ^ *(int*) &x; |
|||
return hashCode; |
|||
} |
|||
} |
|||
|
|||
public static bool operator ==(uiTessellationKey left, uiTessellationKey right) { |
|||
return Equals(left, right); |
|||
} |
|||
|
|||
public static bool operator !=(uiTessellationKey left, uiTessellationKey right) { |
|||
return !Equals(left, right); |
|||
} |
|||
|
|||
public override string ToString() { |
|||
return $"uiTessellationKey(" + |
|||
$"x2: {this.x2}, " + |
|||
$"y2: {this.y2}, " + |
|||
$"x3: {this.x3}, " + |
|||
$"y3: {this.y3}, " + |
|||
$"x4: {this.x4}, " + |
|||
$"y4: {this.y4}, " + |
|||
$"tessTol: {this.tessTol})"; |
|||
} |
|||
} |
|||
|
|||
class uiTessellationInfo : PoolObject { |
|||
public uiTessellationKey key; |
|||
public uiList<Vector2> points; |
|||
long _timeToLive; |
|||
|
|||
public static uiTessellationInfo create(uiTessellationKey key, uiList<Vector2> points, int timeToLive = 5) { |
|||
var newInfo = ObjectPool<uiTessellationInfo>.alloc(); |
|||
newInfo.points = points; |
|||
newInfo.key = key; |
|||
newInfo.touch(timeToLive); |
|||
|
|||
return newInfo; |
|||
} |
|||
|
|||
public uiTessellationInfo() { |
|||
} |
|||
|
|||
public override void clear() { |
|||
ObjectPool<uiList<Vector2>>.release(this.points); |
|||
} |
|||
|
|||
public long timeToLive { |
|||
get { return this._timeToLive; } |
|||
} |
|||
|
|||
public void touch(long timeTolive = 5) { |
|||
this._timeToLive = timeTolive + TextBlobMesh.frameCount; |
|||
} |
|||
} |
|||
|
|||
|
|||
static class uiTessellationGenerator { |
|||
static readonly Dictionary<uiTessellationKey, uiTessellationInfo> _tessellations = |
|||
new Dictionary<uiTessellationKey, uiTessellationInfo>(); |
|||
|
|||
static long _frameCount = 0; |
|||
|
|||
public static long frameCount { |
|||
get { return _frameCount; } |
|||
} |
|||
|
|||
public static int tessellationCount { |
|||
get { return _tessellations.Count; } |
|||
} |
|||
|
|||
public static void tickNextFrame() { |
|||
_frameCount++; |
|||
|
|||
var keysToRemove = _tessellations.Values.Where(info => info.timeToLive < _frameCount) |
|||
.Select(info => info.key).ToList(); |
|||
foreach (var key in keysToRemove) { |
|||
ObjectPool<uiTessellationKey>.release(key); |
|||
ObjectPool<uiTessellationInfo>.release(_tessellations[key]); |
|||
_tessellations.Remove(key); |
|||
} |
|||
} |
|||
|
|||
public static uiList<Vector2> tessellateBezier(float x1, float y1, float x2, float y2, |
|||
float x3, float y3, float x4, float y4, float tessTol) { |
|||
var key = uiTessellationKey.create(x1, y1, x2, y2, x3, y3, x4, y4, tessTol); |
|||
|
|||
_tessellations.TryGetValue(key, out var uiTessellationInfo); |
|||
if (uiTessellationInfo != null) { |
|||
ObjectPool<uiTessellationKey>.release(key); |
|||
uiTessellationInfo.touch(); |
|||
return uiTessellationInfo.points; |
|||
} |
|||
|
|||
var points = _tessellateBezier(x1, y1, x2, y2, x3, y3, x4, y4, tessTol); |
|||
_tessellations[key] = uiTessellationInfo.create(key, points); |
|||
|
|||
return points; |
|||
} |
|||
|
|||
struct _StackData { |
|||
public float x1; |
|||
public float y1; |
|||
public float x2; |
|||
public float y2; |
|||
public float x3; |
|||
public float y3; |
|||
public float x4; |
|||
public float y4; |
|||
public int level; |
|||
} |
|||
|
|||
static readonly Stack<_StackData> _stack = new Stack<_StackData>(); |
|||
|
|||
static uiList<Vector2> _tessellateBezier( |
|||
float x1, float y1, float x2, float y2, |
|||
float x3, float y3, float x4, float y4, |
|||
float tessTol) { |
|||
x2 = x2 - x1; |
|||
y2 = y2 - y1; |
|||
x3 = x3 - x1; |
|||
y3 = y3 - y1; |
|||
x4 = x4 - x1; |
|||
y4 = y4 - y1; |
|||
|
|||
var points = ObjectPool<uiList<Vector2>>.alloc(); |
|||
|
|||
_stack.Clear(); |
|||
_stack.Push(new _StackData { |
|||
x1 = 0, y1 = 0, x2 = x2, y2 = y2, x3 = x3, y3 = y3, x4 = x4, y4 = y4, level = 0, |
|||
}); |
|||
|
|||
while (_stack.Count > 0) { |
|||
var stackData = _stack.Pop(); |
|||
x1 = stackData.x1; |
|||
y1 = stackData.y1; |
|||
x2 = stackData.x2; |
|||
y2 = stackData.y2; |
|||
x3 = stackData.x3; |
|||
y3 = stackData.y3; |
|||
x4 = stackData.x4; |
|||
y4 = stackData.y4; |
|||
int level = stackData.level; |
|||
|
|||
float dx = x4 - x1; |
|||
float dy = y4 - y1; |
|||
float d2 = Mathf.Abs((x2 - x4) * dy - (y2 - y4) * dx); |
|||
float d3 = Mathf.Abs((x3 - x4) * dy - (y3 - y4) * dx); |
|||
|
|||
if ((d2 + d3) * (d2 + d3) <= tessTol * (dx * dx + dy * dy)) { |
|||
points.Add(new Vector2(x4, y4)); |
|||
continue; |
|||
} |
|||
|
|||
float x12 = (x1 + x2) * 0.5f; |
|||
float y12 = (y1 + y2) * 0.5f; |
|||
float x23 = (x2 + x3) * 0.5f; |
|||
float y23 = (y2 + y3) * 0.5f; |
|||
float x34 = (x3 + x4) * 0.5f; |
|||
float y34 = (y3 + y4) * 0.5f; |
|||
float x123 = (x12 + x23) * 0.5f; |
|||
float y123 = (y12 + y23) * 0.5f; |
|||
float x234 = (x23 + x34) * 0.5f; |
|||
float y234 = (y23 + y34) * 0.5f; |
|||
float x1234 = (x123 + x234) * 0.5f; |
|||
float y1234 = (y123 + y234) * 0.5f; |
|||
|
|||
if (level < 10) { |
|||
_stack.Push(new _StackData { |
|||
x1 = x1234, y1 = y1234, x2 = x234, y2 = y234, x3 = x34, y3 = y34, x4 = x4, y4 = y4, |
|||
level = level + 1, |
|||
}); |
|||
_stack.Push(new _StackData { |
|||
x1 = x1, y1 = y1, x2 = x12, y2 = y12, x3 = x123, y3 = y123, x4 = x1234, y4 = y1234, |
|||
level = level + 1, |
|||
}); |
|||
} |
|||
} |
|||
|
|||
return points; |
|||
} |
|||
} |
|||
} |
|
|||
using UnityEngine; |
|||
|
|||
namespace Unity.UIWidgets.ui { |
|||
public struct uiRect { |
|||
public uiRect(float left, float top, float right, float bottom) { |
|||
this.left = left; |
|||
this.top = top; |
|||
this.right = right; |
|||
this.bottom = bottom; |
|||
} |
|||
|
|||
public readonly float left; |
|||
public readonly float top; |
|||
public readonly float right; |
|||
public readonly float bottom; |
|||
|
|||
public bool isEmpty { |
|||
get { return this.left >= this.right || this.top >= this.bottom; } |
|||
} |
|||
|
|||
public float width { |
|||
get { return this.right - this.left; } |
|||
} |
|||
|
|||
public float height { |
|||
get { return this.bottom - this.top; } |
|||
} |
|||
|
|||
public uiOffset topLeft { |
|||
get { return new uiOffset(this.left, this.top); } |
|||
} |
|||
|
|||
public uiOffset topCenter { |
|||
get { return new uiOffset(this.left + this.width / 2.0f, this.top); } |
|||
} |
|||
|
|||
public uiOffset topRight { |
|||
get { return new uiOffset(this.right, this.top); } |
|||
} |
|||
|
|||
public uiOffset centerLeft { |
|||
get { return new uiOffset(this.left, this.top + this.height / 2.0f); } |
|||
} |
|||
|
|||
public uiOffset center { |
|||
get { return new uiOffset(this.left + this.width / 2.0f, this.top + this.height / 2.0f); } |
|||
} |
|||
|
|||
public uiOffset centerRight { |
|||
get { return new uiOffset(this.right, this.bottom); } |
|||
} |
|||
|
|||
public uiOffset bottomLeft { |
|||
get { return new uiOffset(this.left, this.bottom); } |
|||
} |
|||
|
|||
public uiOffset bottomCenter { |
|||
get { return new uiOffset(this.left + this.width / 2.0f, this.bottom); } |
|||
} |
|||
|
|||
public uiOffset bottomRight { |
|||
get { return new uiOffset(this.right, this.bottom); } |
|||
} |
|||
|
|||
public uiRect shift(uiOffset offset) { |
|||
return uiRectHelper.fromLTRB(this.left + offset.dx, this.top + offset.dy, this.right + offset.dx, |
|||
this.bottom + offset.dy); |
|||
} |
|||
|
|||
public uiRect intersect(uiRect other) { |
|||
return uiRectHelper.fromLTRB( |
|||
Mathf.Max(this.left, other.left), |
|||
Mathf.Max(this.top, other.top), |
|||
Mathf.Min(this.right, other.right), |
|||
Mathf.Min(this.bottom, other.bottom) |
|||
); |
|||
} |
|||
|
|||
public uiRect expandToInclude(uiRect? other) { |
|||
if (this.isEmpty) { |
|||
return other.Value; |
|||
} |
|||
|
|||
if (other == null || other.Value.isEmpty) { |
|||
return this; |
|||
} |
|||
|
|||
return uiRectHelper.fromLTRB( |
|||
Mathf.Min(this.left, other.Value.left), |
|||
Mathf.Min(this.top, other.Value.top), |
|||
Mathf.Max(this.right, other.Value.right), |
|||
Mathf.Max(this.bottom, other.Value.bottom) |
|||
); |
|||
} |
|||
} |
|||
|
|||
public static class uiRectHelper { |
|||
public static uiRect fromRect(Rect rect) { |
|||
return new uiRect(rect.left, rect.top, rect.right, rect.bottom); |
|||
} |
|||
|
|||
public static uiRect fromLTRB(float left, float top, float right, float bottom) { |
|||
return new uiRect(left, top, right, bottom); |
|||
} |
|||
|
|||
public static uiRect fromLTWH(float left, float top, float width, float height) { |
|||
return new uiRect(left, top, left + width, top + height); |
|||
} |
|||
|
|||
public static readonly uiRect zero = new uiRect(0, 0, 0, 0); |
|||
|
|||
public static readonly uiRect one = new uiRect(0, 0, 1, 1); |
|||
|
|||
public static bool equals(uiRect? a, uiRect? b) { |
|||
if (a == null && b == null) { |
|||
return true; |
|||
} |
|||
|
|||
if (a == null || b == null) { |
|||
return false; |
|||
} |
|||
|
|||
var aval = a.Value; |
|||
var bval = b.Value; |
|||
|
|||
return aval.left == bval.left && aval.right == bval.right && aval.top == bval.top && |
|||
aval.bottom == bval.bottom; |
|||
} |
|||
|
|||
public static uiRect scale(uiRect a, float scaleX, float? scaleY = null) { |
|||
scaleY = scaleY ?? scaleX; |
|||
return fromLTRB( |
|||
a.left * scaleX, a.top * scaleY.Value, |
|||
a.right * scaleX, a.bottom * scaleY.Value); |
|||
} |
|||
|
|||
public static uiRect inflate(uiRect a, float delta) { |
|||
return fromLTRB(a.left - delta, a.top - delta, a.right + delta, a.bottom + delta); |
|||
} |
|||
|
|||
public static uiRect deflate(uiRect a, float delta) { |
|||
return inflate(a, -delta); |
|||
} |
|||
|
|||
public static uiRect intersect(uiRect a, uiRect other) { |
|||
return fromLTRB( |
|||
Mathf.Max(a.left, other.left), |
|||
Mathf.Max(a.top, other.top), |
|||
Mathf.Min(a.right, other.right), |
|||
Mathf.Min(a.bottom, other.bottom) |
|||
); |
|||
} |
|||
|
|||
public static uiRect round(uiRect a) { |
|||
return fromLTRB( |
|||
Mathf.Round(a.left), Mathf.Round(a.top), |
|||
Mathf.Round(a.right), Mathf.Round(a.bottom)); |
|||
} |
|||
|
|||
public static uiRect roundOut(uiRect a) { |
|||
return fromLTRB( |
|||
Mathf.Floor(a.left), Mathf.Floor(a.top), |
|||
Mathf.Ceil(a.right), Mathf.Ceil(a.bottom)); |
|||
} |
|||
|
|||
public static uiRect roundOut(uiRect a, float devicePixelRatio) { |
|||
return fromLTRB( |
|||
Mathf.Floor(a.left * devicePixelRatio) / devicePixelRatio, |
|||
Mathf.Floor(a.top * devicePixelRatio) / devicePixelRatio, |
|||
Mathf.Ceil(a.right * devicePixelRatio) / devicePixelRatio, |
|||
Mathf.Ceil(a.bottom * devicePixelRatio) / devicePixelRatio); |
|||
} |
|||
|
|||
public static uiRect roundIn(uiRect a) { |
|||
return fromLTRB( |
|||
Mathf.Ceil(a.left), Mathf.Ceil(a.top), |
|||
Mathf.Floor(a.right), Mathf.Floor(a.bottom)); |
|||
} |
|||
|
|||
public static uiRect normalize(uiRect a) { |
|||
if (a.left <= a.right && a.top <= a.bottom) { |
|||
return a; |
|||
} |
|||
|
|||
return fromLTRB( |
|||
Mathf.Min(a.left, a.right), |
|||
Mathf.Min(a.top, a.bottom), |
|||
Mathf.Max(a.left, a.right), |
|||
Mathf.Max(a.top, a.bottom) |
|||
); |
|||
} |
|||
|
|||
|
|||
public static uiOffset[] toQuad(uiRect a) { |
|||
uiOffset[] dst = new uiOffset[4]; |
|||
dst[0] = new uiOffset(a.left, a.top); |
|||
dst[1] = new uiOffset(a.right, a.top); |
|||
dst[2] = new uiOffset(a.right, a.bottom); |
|||
dst[3] = new uiOffset(a.left, a.bottom); |
|||
return dst; |
|||
} |
|||
|
|||
public static bool contains(uiRect a, uiOffset offset) { |
|||
return offset.dx >= a.left && offset.dx < a.right && offset.dy >= a.top && offset.dy < a.bottom; |
|||
} |
|||
|
|||
public static bool contains(uiRect a, uiRect rect) { |
|||
return contains(a, rect.topLeft) && contains(a, rect.bottomRight); |
|||
} |
|||
|
|||
public static bool overlaps(uiRect a, uiRect other) { |
|||
if (a.right <= other.left || other.right <= a.left) { |
|||
return false; |
|||
} |
|||
|
|||
if (a.bottom <= other.top || other.bottom <= a.top) { |
|||
return false; |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
public static UnityEngine.Rect toRect(uiRect rect) { |
|||
return new UnityEngine.Rect(rect.left, rect.top, rect.width, rect.height); |
|||
} |
|||
} |
|||
} |
|
|||
using UnityEngine; |
|||
|
|||
namespace Unity.UIWidgets.ui { |
|||
public struct uiMaskFilter { |
|||
uiMaskFilter(BlurStyle style, float sigma) { |
|||
this.style = style; |
|||
this.sigma = sigma; |
|||
} |
|||
|
|||
public static uiMaskFilter blur(BlurStyle style, float sigma) { |
|||
return new uiMaskFilter(style, sigma); |
|||
} |
|||
|
|||
public readonly BlurStyle style; |
|||
public readonly float sigma; |
|||
} |
|||
|
|||
public struct uiColorFilter { |
|||
uiColorFilter(uiColor color, BlendMode blendMode) { |
|||
this.color = color; |
|||
this.blendMode = blendMode; |
|||
} |
|||
|
|||
public static uiColorFilter mode(uiColor color, BlendMode blendMode) { |
|||
return new uiColorFilter(color, blendMode); |
|||
} |
|||
|
|||
public readonly uiColor color; |
|||
public readonly BlendMode blendMode; |
|||
} |
|||
|
|||
public interface uiImageFilter { |
|||
} |
|||
|
|||
public static class uiImageFilterHelper { |
|||
public static uiImageFilter blur(float sigmaX = 0.0f, float sigmaY = 0.0f) { |
|||
return new _uiBlurImageFilter(sigmaX, sigmaY); |
|||
} |
|||
|
|||
public static uiImageFilter matrix(uiMatrix3 transform, FilterMode filterMode = FilterMode.Bilinear) { |
|||
return new _uiMatrixImageFilter(transform, filterMode); |
|||
} |
|||
} |
|||
|
|||
struct _uiBlurImageFilter : uiImageFilter { |
|||
public _uiBlurImageFilter(float sigmaX, float sigmaY) { |
|||
this.sigmaX = sigmaX; |
|||
this.sigmaY = sigmaY; |
|||
} |
|||
|
|||
public readonly float sigmaX; |
|||
public readonly float sigmaY; |
|||
} |
|||
|
|||
struct _uiMatrixImageFilter : uiImageFilter { |
|||
public _uiMatrixImageFilter(uiMatrix3 transform, FilterMode filterMode) { |
|||
this.transform = transform; |
|||
this.filterMode = filterMode; |
|||
} |
|||
|
|||
public readonly uiMatrix3 transform; |
|||
public readonly FilterMode filterMode; |
|||
} |
|||
|
|||
public struct uiPaint { |
|||
static readonly uiColor _kColorDefault = new uiColor(0xFFFFFFFF); |
|||
|
|||
public uiColor color; |
|||
public BlendMode blendMode; |
|||
public PaintingStyle style; |
|||
public float strokeWidth; |
|||
public StrokeCap strokeCap; |
|||
public StrokeJoin strokeJoin; |
|||
public float strokeMiterLimit; |
|||
public FilterMode filterMode; |
|||
public uiColorFilter? colorFilter; |
|||
public uiMaskFilter? maskFilter; |
|||
public uiImageFilter backdrop; |
|||
public PaintShader shader; |
|||
public bool invertColors; |
|||
|
|||
public uiPaint( |
|||
uiColor? color = null, |
|||
BlendMode blendMode = BlendMode.srcOver, |
|||
PaintingStyle style = PaintingStyle.fill, |
|||
float strokeWidth = 0f, |
|||
StrokeCap strokeCap = StrokeCap.butt, |
|||
StrokeJoin strokeJoin = StrokeJoin.miter, |
|||
float strokeMiterLimit = 4.0f, |
|||
FilterMode filterMode = FilterMode.Bilinear, |
|||
uiColorFilter? colorFilter = null, |
|||
uiMaskFilter? maskFilter = null, |
|||
uiImageFilter backdrop = null, |
|||
PaintShader shader = null, |
|||
bool invertColors = false |
|||
) { |
|||
this.color = color ?? _kColorDefault; |
|||
this.blendMode = blendMode; |
|||
this.style = style; |
|||
this.strokeWidth = strokeWidth; |
|||
this.strokeCap = strokeCap; |
|||
this.strokeJoin = strokeJoin; |
|||
this.strokeMiterLimit = strokeMiterLimit; |
|||
this.filterMode = filterMode; |
|||
this.colorFilter = colorFilter; |
|||
this.maskFilter = maskFilter; |
|||
this.backdrop = backdrop; |
|||
this.shader = shader; |
|||
this.invertColors = invertColors; |
|||
} |
|||
|
|||
public uiPaint(uiPaint paint) { |
|||
this.color = paint.color; |
|||
this.blendMode = paint.blendMode; |
|||
this.style = paint.style; |
|||
this.strokeWidth = paint.strokeWidth; |
|||
this.strokeCap = paint.strokeCap; |
|||
this.strokeJoin = paint.strokeJoin; |
|||
this.strokeMiterLimit = paint.strokeMiterLimit; |
|||
this.filterMode = paint.filterMode; |
|||
this.colorFilter = paint.colorFilter; |
|||
this.maskFilter = paint.maskFilter; |
|||
this.backdrop = paint.backdrop; |
|||
this.shader = paint.shader; |
|||
this.invertColors = paint.invertColors; |
|||
} |
|||
|
|||
public static uiPaint shapeOnly(uiPaint paint) { |
|||
return new uiPaint( |
|||
style: paint.style, |
|||
strokeWidth: paint.strokeWidth, |
|||
strokeCap: paint.strokeCap, |
|||
strokeJoin: paint.strokeJoin, |
|||
strokeMiterLimit: paint.strokeMiterLimit |
|||
); |
|||
} |
|||
|
|||
public static uiPaint fromPaint(Paint paint) { |
|||
uiImageFilter filter = null; |
|||
if (paint.backdrop is _BlurImageFilter) { |
|||
var blurFilter = (_BlurImageFilter) paint.backdrop; |
|||
filter = uiImageFilterHelper.blur(blurFilter.sigmaX, blurFilter.sigmaY); |
|||
} |
|||
else if (paint.backdrop is _MatrixImageFilter) { |
|||
var matrixFilter = (_MatrixImageFilter) paint.backdrop; |
|||
filter = uiImageFilterHelper.matrix(uiMatrix3.fromMatrix3(matrixFilter.transform), |
|||
matrixFilter.filterMode); |
|||
} |
|||
|
|||
return new uiPaint( |
|||
color: paint.color == null ? (uiColor?) null : uiColor.fromColor(paint.color), |
|||
blendMode: paint.blendMode, |
|||
style: paint.style, |
|||
strokeWidth: paint.strokeWidth, |
|||
strokeCap: paint.strokeCap, |
|||
strokeJoin: paint.strokeJoin, |
|||
strokeMiterLimit: paint.strokeMiterLimit, |
|||
filterMode: paint.filterMode, |
|||
colorFilter: paint.colorFilter == null |
|||
? (uiColorFilter?) null |
|||
: uiColorFilter.mode(uiColor.fromColor(paint.colorFilter.color), paint.colorFilter.blendMode), |
|||
maskFilter: paint.maskFilter == null |
|||
? (uiMaskFilter?) null |
|||
: uiMaskFilter.blur(paint.maskFilter.style, paint.maskFilter.sigma), |
|||
backdrop: filter, |
|||
shader: paint.shader, |
|||
invertColors: paint.invertColors |
|||
); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 9bde84e37c33148879131974b64a62aa |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using Unity.UIWidgets.foundation; |
|||
|
|||
namespace Unity.UIWidgets.ui { |
|||
public class uiPicture : PoolObject { |
|||
public uiPicture() { |
|||
} |
|||
|
|||
public static uiPicture create(List<uiDrawCmd> drawCmds, uiRect paintBounds) { |
|||
var picture = ObjectPool<uiPicture>.alloc(); |
|||
picture.drawCmds = drawCmds; |
|||
picture.paintBounds = paintBounds; |
|||
return picture; |
|||
} |
|||
|
|||
public List<uiDrawCmd> drawCmds; |
|||
public uiRect paintBounds; |
|||
|
|||
public override void clear() { |
|||
//the recorder will dispose the draw commands
|
|||
this.drawCmds = null; |
|||
} |
|||
} |
|||
|
|||
public class uiPictureRecorder { |
|||
readonly List<uiDrawCmd> _drawCmds = new List<uiDrawCmd>(128); |
|||
|
|||
readonly List<uiCanvasState> _states = new List<uiCanvasState>(32); |
|||
|
|||
public uiPictureRecorder() { |
|||
this.reset(); |
|||
} |
|||
|
|||
uiCanvasState _getState() { |
|||
D.assert(this._states.Count > 0); |
|||
return this._states[this._states.Count - 1]; |
|||
} |
|||
|
|||
void _setState(uiCanvasState state) { |
|||
this._states[this._states.Count - 1] = state; |
|||
} |
|||
|
|||
public uiMatrix3 getTotalMatrix() { |
|||
return this._getState().xform; |
|||
} |
|||
|
|||
public void reset() { |
|||
foreach (var drawCmd in this._drawCmds) { |
|||
drawCmd.release(); |
|||
} |
|||
|
|||
this._drawCmds.Clear(); |
|||
this._states.Clear(); |
|||
this._states.Add(new uiCanvasState { |
|||
xform = uiMatrix3.I(), |
|||
scissor = null, |
|||
saveLayer = false, |
|||
layerOffset = null, |
|||
paintBounds = uiRectHelper.zero |
|||
}); |
|||
} |
|||
|
|||
public uiPicture endRecording() { |
|||
if (this._states.Count > 1) { |
|||
throw new Exception("unmatched save/restore commands"); |
|||
} |
|||
|
|||
var state = this._getState(); |
|||
return uiPicture.create(this._drawCmds, state.paintBounds); |
|||
} |
|||
|
|||
public void addDrawCmd(uiDrawCmd drawCmd) { |
|||
this._drawCmds.Add(drawCmd); |
|||
|
|||
switch (drawCmd) { |
|||
case uiDrawSave _: |
|||
this._states.Add(this._getState().copy()); |
|||
break; |
|||
case uiDrawSaveLayer cmd: { |
|||
this._states.Add(new uiCanvasState { |
|||
xform = uiMatrix3.I(), |
|||
scissor = cmd.rect.Value.shift(-cmd.rect.Value.topLeft), |
|||
saveLayer = true, |
|||
layerOffset = cmd.rect.Value.topLeft, |
|||
paintBounds = uiRectHelper.zero |
|||
}); |
|||
break; |
|||
} |
|||
case uiDrawRestore _: { |
|||
var stateToRestore = this._getState(); |
|||
this._states.RemoveAt(this._states.Count - 1); |
|||
var state = this._getState(); |
|||
|
|||
if (!stateToRestore.saveLayer) { |
|||
state.paintBounds = stateToRestore.paintBounds; |
|||
} |
|||
else { |
|||
var paintBounds = stateToRestore.paintBounds.shift(stateToRestore.layerOffset.Value); |
|||
paintBounds = state.xform.mapRect(paintBounds); |
|||
this._addPaintBounds(paintBounds); |
|||
} |
|||
|
|||
this._setState(state); |
|||
break; |
|||
} |
|||
case uiDrawTranslate cmd: { |
|||
var state = this._getState(); |
|||
state.xform = new uiMatrix3(state.xform); |
|||
state.xform.preTranslate(cmd.dx, cmd.dy); |
|||
this._setState(state); |
|||
break; |
|||
} |
|||
case uiDrawScale cmd: { |
|||
var state = this._getState(); |
|||
state.xform = new uiMatrix3(state.xform); |
|||
state.xform.preScale(cmd.sx, (cmd.sy ?? cmd.sx)); |
|||
this._setState(state); |
|||
break; |
|||
} |
|||
case uiDrawRotate cmd: { |
|||
var state = this._getState(); |
|||
state.xform = new uiMatrix3(state.xform); |
|||
if (cmd.offset == null) { |
|||
state.xform.preRotate(cmd.radians); |
|||
} |
|||
else { |
|||
state.xform.preRotate(cmd.radians, |
|||
cmd.offset.Value.dx, |
|||
cmd.offset.Value.dy); |
|||
} |
|||
|
|||
this._setState(state); |
|||
break; |
|||
} |
|||
case uiDrawSkew cmd: { |
|||
var state = this._getState(); |
|||
state.xform = new uiMatrix3(state.xform); |
|||
state.xform.preSkew(cmd.sx, cmd.sy); |
|||
this._setState(state); |
|||
break; |
|||
} |
|||
case uiDrawConcat cmd: { |
|||
var state = this._getState(); |
|||
state.xform = new uiMatrix3(state.xform); |
|||
state.xform.preConcat(cmd.matrix.Value); |
|||
this._setState(state); |
|||
break; |
|||
} |
|||
case uiDrawResetMatrix _: { |
|||
var state = this._getState(); |
|||
state.xform = uiMatrix3.I(); |
|||
this._setState(state); |
|||
break; |
|||
} |
|||
case uiDrawSetMatrix cmd: { |
|||
var state = this._getState(); |
|||
state.xform = new uiMatrix3(cmd.matrix.Value); |
|||
this._setState(state); |
|||
break; |
|||
} |
|||
case uiDrawClipRect cmd: { |
|||
var state = this._getState(); |
|||
|
|||
var rect = state.xform.mapRect(cmd.rect.Value); |
|||
state.scissor = state.scissor == null ? rect : state.scissor.Value.intersect(rect); |
|||
this._setState(state); |
|||
break; |
|||
} |
|||
case uiDrawClipRRect cmd: { |
|||
var state = this._getState(); |
|||
|
|||
var rect = state.xform.mapRect(uiRectHelper.fromRect(cmd.rrect.outerRect)); |
|||
state.scissor = state.scissor == null ? rect : state.scissor.Value.intersect(rect); |
|||
this._setState(state); |
|||
break; |
|||
} |
|||
case uiDrawClipPath cmd: { |
|||
var state = this._getState(); |
|||
var scale = uiXformUtils.getScale(state.xform); |
|||
|
|||
var rectPathCache = cmd.path.flatten( |
|||
scale * Window.instance.devicePixelRatio); |
|||
var rectMesh = rectPathCache.getFillMesh(out _); |
|||
var transformedMesh = rectMesh.transform(state.xform); |
|||
var rect = transformedMesh.bounds; |
|||
state.scissor = state.scissor == null ? rect : state.scissor.Value.intersect(rect); |
|||
this._setState(state); |
|||
ObjectPool<uiMeshMesh>.release(transformedMesh); |
|||
break; |
|||
} |
|||
case uiDrawPath cmd: { |
|||
var state = this._getState(); |
|||
var scale = uiXformUtils.getScale(state.xform); |
|||
var path = cmd.path; |
|||
var paint = cmd.paint; |
|||
var devicePixelRatio = Window.instance.devicePixelRatio; |
|||
|
|||
uiMeshMesh mesh; |
|||
if (paint.style == PaintingStyle.fill) { |
|||
var cache = path.flatten(scale * devicePixelRatio); |
|||
var fillMesh = cache.getFillMesh(out _); |
|||
mesh = fillMesh.transform(state.xform); |
|||
} |
|||
else { |
|||
float strokeWidth = (paint.strokeWidth * scale).clamp(0, 200.0f); |
|||
float fringeWidth = 1 / devicePixelRatio; |
|||
|
|||
if (strokeWidth < fringeWidth) { |
|||
strokeWidth = fringeWidth; |
|||
} |
|||
|
|||
var cache = path.flatten(scale * devicePixelRatio); |
|||
var strokenMesh = cache.getStrokeMesh( |
|||
strokeWidth / scale * 0.5f, |
|||
paint.strokeCap, |
|||
paint.strokeJoin, |
|||
paint.strokeMiterLimit); |
|||
|
|||
mesh = strokenMesh.transform(state.xform); |
|||
} |
|||
|
|||
if (paint.maskFilter != null && paint.maskFilter.Value.sigma != 0) { |
|||
float sigma = scale * paint.maskFilter.Value.sigma; |
|||
float sigma3 = 3 * sigma; |
|||
this._addPaintBounds(uiRectHelper.inflate(mesh.bounds, sigma3)); |
|||
} |
|||
else { |
|||
this._addPaintBounds(mesh.bounds); |
|||
} |
|||
|
|||
ObjectPool<uiMeshMesh>.release(mesh); |
|||
break; |
|||
} |
|||
case uiDrawImage cmd: { |
|||
var state = this._getState(); |
|||
var rect = uiRectHelper.fromLTWH(cmd.offset.Value.dx, cmd.offset.Value.dy, |
|||
cmd.image.width, cmd.image.height); |
|||
rect = state.xform.mapRect(rect); |
|||
this._addPaintBounds(rect); |
|||
break; |
|||
} |
|||
case uiDrawImageRect cmd: { |
|||
var state = this._getState(); |
|||
var rect = state.xform.mapRect(cmd.dst.Value); |
|||
this._addPaintBounds(rect); |
|||
break; |
|||
} |
|||
case uiDrawImageNine cmd: { |
|||
var state = this._getState(); |
|||
var rect = state.xform.mapRect(cmd.dst.Value); |
|||
this._addPaintBounds(rect); |
|||
break; |
|||
} |
|||
case uiDrawPicture cmd: { |
|||
var state = this._getState(); |
|||
var rect = state.xform.mapRect(uiRectHelper.fromRect(cmd.picture.paintBounds)); |
|||
this._addPaintBounds(rect); |
|||
break; |
|||
} |
|||
case uiDrawTextBlob cmd: { |
|||
var state = this._getState(); |
|||
var scale = uiXformUtils.getScale(state.xform); |
|||
var rect = uiRectHelper.fromRect(cmd.textBlob.boundsInText).shift(cmd.offset.Value); |
|||
rect = state.xform.mapRect(rect); |
|||
|
|||
var paint = cmd.paint; |
|||
if (paint.maskFilter != null && paint.maskFilter.Value.sigma != 0) { |
|||
float sigma = scale * paint.maskFilter.Value.sigma; |
|||
float sigma3 = 3 * sigma; |
|||
this._addPaintBounds(uiRectHelper.inflate(rect, sigma3)); |
|||
} |
|||
else { |
|||
this._addPaintBounds(rect); |
|||
} |
|||
|
|||
break; |
|||
} |
|||
default: |
|||
throw new Exception("unknown drawCmd: " + drawCmd); |
|||
} |
|||
} |
|||
|
|||
void _addPaintBounds(uiRect? paintBounds) { |
|||
var state = this._getState(); |
|||
if (state.scissor != null) { |
|||
paintBounds = paintBounds.Value.intersect(state.scissor.Value); |
|||
} |
|||
|
|||
if (paintBounds == null || paintBounds.Value.isEmpty) { |
|||
return; |
|||
} |
|||
|
|||
if (state.paintBounds.isEmpty) { |
|||
state.paintBounds = paintBounds.Value; |
|||
} |
|||
else { |
|||
state.paintBounds = state.paintBounds.expandToInclude(paintBounds.Value); |
|||
} |
|||
|
|||
this._setState(state); |
|||
} |
|||
|
|||
struct uiCanvasState { |
|||
public uiMatrix3 xform; |
|||
public uiRect? scissor; |
|||
public bool saveLayer; |
|||
public uiOffset? layerOffset; |
|||
public uiRect paintBounds; |
|||
|
|||
public uiCanvasState copy() { |
|||
return new uiCanvasState { |
|||
xform = this.xform, |
|||
scissor = this.scissor, |
|||
saveLayer = false, |
|||
layerOffset = null, |
|||
paintBounds = this.paintBounds |
|||
}; |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: cb2a188869ac14f84b90cf8b06a0f048 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using UnityEngine; |
|||
|
|||
namespace Unity.UIWidgets.ui { |
|||
static class uiXformUtils { |
|||
public static float getScaleX(uiMatrix3 matrix) { |
|||
// ignore perspective parameters for now.
|
|||
if (matrix.isIdentity()) { |
|||
return 1.0f; |
|||
} |
|||
|
|||
if (matrix.getSkewY() == 0) { |
|||
return matrix.getScaleX(); |
|||
} |
|||
|
|||
var x = matrix.getScaleX(); |
|||
var y = matrix.getSkewY(); |
|||
|
|||
return Mathf.Sqrt(x * x + y * y); |
|||
} |
|||
|
|||
public static float getScaleY(uiMatrix3 matrix) { |
|||
// ignore perspective parameters for now.
|
|||
if (matrix.isIdentity()) { |
|||
return 1.0f; |
|||
} |
|||
|
|||
if (matrix.getSkewX() == 0) { |
|||
return matrix.getScaleY(); |
|||
} |
|||
|
|||
var x = matrix.getSkewX(); |
|||
var y = matrix.getScaleY(); |
|||
|
|||
return Mathf.Sqrt(x * x + y * y); |
|||
} |
|||
|
|||
public static float getScale(uiMatrix3 matrix) { |
|||
var scaleX = getScaleX(matrix); |
|||
var scaleY = getScaleY(matrix); |
|||
|
|||
if (scaleX == 1.0) { |
|||
return scaleY; |
|||
} |
|||
|
|||
if (scaleY == 1.0) { |
|||
return scaleX; |
|||
} |
|||
|
|||
// geometric mean of len0 and len1.
|
|||
return Mathf.Sqrt(scaleX * scaleY); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: fb644db0d0fbd48208a50a3321bc5840 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 6f7a64e74fe2b445abd45004603580e5 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: ce66bd4727b6e47d28bc5830b4af948a |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
部分文件因为文件数量过多而无法显示
撰写
预览
正在加载...
取消
保存
Reference in new issue