284 lines
7.9 KiB
C#
284 lines
7.9 KiB
C#
using UnityEngine;
|
|
|
|
/// <summary>
|
|
/// 把两个纹理以缝合的方式显示的组件,需要下面有两个UITexture节点
|
|
/// </summary>
|
|
[ExecuteInEditMode]
|
|
public class UISutureTexture : MonoBehaviour
|
|
{
|
|
//原始图片宽度和高度 比例默认是: h/w = 2.3
|
|
public int OrgImageW = 1984;
|
|
public int OrgImageH = 862;
|
|
|
|
//分割的两个图片分别宽度
|
|
public int PartImageW = 1024;
|
|
//中间重叠的宽度
|
|
public int OverlapW = 64;
|
|
|
|
//图片展示的宽度比例
|
|
public float wfactor;
|
|
|
|
//最外层控制大小的box
|
|
private UIWidget _box;
|
|
//左边的图片组件
|
|
private UITexture _left;
|
|
//右边的图片组件
|
|
private UITexture _right;
|
|
|
|
//左纹理
|
|
public Texture2D _leftTex;
|
|
|
|
//右纹理
|
|
public Texture2D _rightTex;
|
|
|
|
//组件深度
|
|
private int _depth;
|
|
|
|
private void OnEnable()
|
|
{
|
|
OnInit(transform);
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
|
|
}
|
|
|
|
|
|
private void Start()
|
|
{
|
|
OnInit(transform);
|
|
}
|
|
|
|
|
|
private void OnValidate()
|
|
{
|
|
RefreshUI();
|
|
}
|
|
|
|
public void SetDepth(int depth)
|
|
{
|
|
_depth = depth;
|
|
RefreshUI();
|
|
|
|
}
|
|
|
|
public void SetTexture(UISutureTextureData data)
|
|
{
|
|
SetTexture(data.Left, data.Right);
|
|
}
|
|
|
|
//设置当前组件纹理
|
|
public void SetTexture(Texture2D left, Texture2D right)
|
|
{
|
|
_leftTex = left;
|
|
_rightTex = right;
|
|
RefreshUI();
|
|
OnBoxDimensionsChanged();
|
|
}
|
|
|
|
//清理当前组件上的纹理
|
|
public void ResetTexture()
|
|
{
|
|
_leftTex = null;
|
|
_rightTex = null;
|
|
if(_left != null) _left.mainTexture = null;
|
|
if (_right != null) _right.mainTexture = null;
|
|
}
|
|
|
|
//脚本初始化
|
|
private void OnInit(Transform trans)
|
|
{
|
|
if (_box == null)
|
|
{
|
|
_box = trans.GetComponent<UIWidget>();
|
|
if (trans.childCount == 0)
|
|
{
|
|
CreateNode(trans, "Left");
|
|
CreateNode(trans, "Right");
|
|
}
|
|
else if (trans.childCount == 1)
|
|
{
|
|
CreateNode(trans, "Right");
|
|
}
|
|
|
|
_left = RequireComponent<UITexture>(trans.GetChild(0));
|
|
_right = RequireComponent<UITexture>(trans.GetChild(1));
|
|
|
|
|
|
_left.SetAnchor(_box.transform);
|
|
_right.SetAnchor(_box.transform);
|
|
|
|
_left.updateAnchors = UIRect.AnchorUpdate.OnUpdate;
|
|
_right.updateAnchors = UIRect.AnchorUpdate.OnUpdate;
|
|
|
|
_box.onChange = OnBoxDimensionsChanged;
|
|
|
|
_depth = _box.depth;
|
|
}
|
|
RefreshUI();
|
|
OnBoxDimensionsChanged();
|
|
|
|
}
|
|
|
|
private void CreateNode(Transform parent,string name)
|
|
{
|
|
GameObject go = new GameObject(name);
|
|
go.layer = parent.gameObject.layer;
|
|
go.transform.parent = parent;
|
|
go.transform.localPosition = Vector3.zero;
|
|
go.transform.localEulerAngles = Vector3.zero;
|
|
go.transform.localScale = Vector3.one;
|
|
}
|
|
|
|
|
|
//刷新UI
|
|
private void RefreshUI()
|
|
{
|
|
if (_box != null)
|
|
{
|
|
_box.depth = _depth;
|
|
if (_left != null)
|
|
{
|
|
_left.depth = _depth;
|
|
_left.mainTexture = _leftTex;
|
|
}
|
|
if (_right != null)
|
|
{
|
|
_right.depth = _depth;
|
|
_right.mainTexture = _rightTex;
|
|
}
|
|
}
|
|
}
|
|
|
|
//box的大小改变时回调处理
|
|
private void OnBoxDimensionsChanged()
|
|
{
|
|
try
|
|
{
|
|
if (_left != null && _right != null && _box != null)
|
|
{
|
|
wfactor = GetWidthClipScale(OrgImageW, OrgImageH, _box.width, _box.height);
|
|
var v = GetPartWRect(OrgImageW, PartImageW, wfactor);
|
|
float ol = GetScreenOverlapLen(OrgImageW, OverlapW, _box.width, wfactor) * 0.5f;
|
|
|
|
_left.uvRect = new Rect(v.x, 0f, v.y, 1f);
|
|
_right.uvRect = new Rect(v.z, 0f, v.w, 1f);
|
|
|
|
_left.leftAnchor.Set(0, 0);
|
|
_left.rightAnchor.Set(0.5f, ol);
|
|
_left.bottomAnchor.Set(0, 0);
|
|
_left.topAnchor.Set(1, 0);
|
|
_left.UpdateAnchors();
|
|
|
|
//针对小数部分,来进行调整
|
|
float frac = ol - Mathf.Floor(ol);
|
|
//如果大于0.5表示被误差大于1个像素.
|
|
if (frac >= 0.5)
|
|
{
|
|
//把右边的图片向左位移1个像素
|
|
ol = ol - 1;
|
|
}
|
|
_right.leftAnchor.Set(0.5f, -ol);
|
|
_right.rightAnchor.Set(1, 0);
|
|
_right.bottomAnchor.Set(0, 0);
|
|
_right.topAnchor.Set(1, 0);
|
|
_right.UpdateAnchors();
|
|
}
|
|
}
|
|
catch(System.Exception ex)
|
|
{
|
|
Debug.LogException(ex);
|
|
}
|
|
|
|
}
|
|
|
|
#region//静态方法
|
|
|
|
private static T RequireComponent<T>(Transform trans)
|
|
where T : Component
|
|
{
|
|
T result = trans.GetComponent<T>();
|
|
if (result == null)
|
|
{
|
|
result = trans.gameObject.AddComponent<T>();
|
|
}
|
|
return result;
|
|
|
|
}
|
|
/// <summary>
|
|
/// 根据屏幕的宽高比,以图片高为基准对图片宽度进行比例切割
|
|
/// </summary>
|
|
/// <param name="ImageW"></param>
|
|
/// <param name="ImageH"></param>
|
|
/// <returns>图片宽度被剪切后的比例</returns>
|
|
public static float GetWidthClipScale(float ImageW, float ImageH, float ScreenW, int ScreenH)
|
|
{
|
|
float wfactor = (ScreenW * ImageH) / (ScreenH * ImageW);
|
|
return wfactor > 1 ? 1f : wfactor;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 根据原始图片的宽度,以及分割后中间重叠的长度,获取图片在屏幕上的重叠长度,关于如何切割请看示例在本类的最后.
|
|
/// </summary>
|
|
/// <param name="OrgImageW">原始图片的长度</param>
|
|
/// <param name="ImageOverlapLen">图片分割后中间重叠的长度</param>
|
|
/// <param name="ScreenW">屏幕的宽度</param>
|
|
/// <param name="Wfactor">图片宽度被剪切后的比例</param>
|
|
/// <returns></returns>
|
|
public static float GetScreenOverlapLen(float OrgImageW, float ImageOverlapLen, float ScreenW, float Wfactor)
|
|
{
|
|
return ((ScreenW * ImageOverlapLen)) / ((OrgImageW * Wfactor));
|
|
}
|
|
|
|
/// <summary>
|
|
/// 根据原始图片的宽度和子图片的宽度,以及原始赌片被剪切的比例,来获得两个两个部分的偏移和缩放 ,关于如何切割请看示例在本类的最后.
|
|
/// 注意:这里的计算图片的偏移和剪切都是以原始图片中心点为锚点的.
|
|
/// </summary>
|
|
/// <param name="OrgImageW"></param>
|
|
/// <param name="PartImageW"></param>
|
|
/// <param name="Wfactor"></param>
|
|
/// <returns></returns>
|
|
public static Vector4 GetPartWRect(float OrgImageW, float PartImageW, float Wfactor)
|
|
{
|
|
//首先计算左边图片的偏移比例
|
|
float leftOffset = OrgImageW * (1 - Wfactor) * 0.5f / PartImageW;
|
|
//左边展示的宽度比例
|
|
float leftClipScale = 1 - leftOffset;
|
|
//右边图片的偏移比例
|
|
float rightOffset = 0f;
|
|
//右边图片的宽度比例
|
|
float rightClipScale = leftClipScale;
|
|
return new Vector4(leftOffset, leftClipScale, rightOffset, rightClipScale);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* 这个示例中:
|
|
* 原始图片宽度: OrgImageW : 1984
|
|
* 切割后的宽度: ImageW:1024
|
|
* 重叠部分的宽度: ImageOverlapLen:64
|
|
*
|
|
|<--------1984-------->|
|
|
|----------------------|
|
|
| |
|
|
| |
|
|
| |
|
|
|----------------------|
|
|
|
|
|<---1024--->|
|
|
|---------|--|---------|
|
|
| | | |
|
|
| | | |
|
|
| | | |
|
|
|---------|--|---------|
|
|
|<---1024--->|
|
|
|64|
|
|
*/
|
|
#endregion
|
|
|
|
|
|
}
|
|
|