备份CatanBuilding瘦身独立工程

This commit is contained in:
JSD\13999
2026-05-26 16:15:54 +08:00
commit 2d0e6a61b7
12001 changed files with 2431925 additions and 0 deletions

View File

@@ -0,0 +1,105 @@
using TMPro;
using UnityEngine;
using UnityEngine.UI;
[RequireComponent(typeof(TMP_Text))]
public class ControlTextSize : MonoBehaviour, ILayoutElement
{
private TMP_Text curTxt;
private bool cached = false;
public float maxPreferredWidth = 0f;
public float maxPreferredHeight = 0f;
public float flexibleHeight
{
get
{
cacheReferences();
return curTxt.flexibleHeight;
}
}
public float flexibleWidth
{
get
{
cacheReferences();
return curTxt.flexibleWidth;
}
}
public int layoutPriority
{
get { return 1; }
}
public float minHeight
{
get
{
cacheReferences();
return curTxt.minHeight;
}
}
public float minWidth
{
get
{
cacheReferences();
return curTxt.minWidth;
}
}
public float preferredHeight
{
get
{
cacheReferences();
if (Mathf.Approximately(maxPreferredHeight, 0f))
{
return curTxt.preferredHeight;
}
else
{
return curTxt.preferredHeight > maxPreferredHeight ? maxPreferredHeight : curTxt.preferredHeight;
}
}
}
public float preferredWidth
{
get
{
cacheReferences();
if (Mathf.Approximately(maxPreferredWidth, 0f))
{
return curTxt.preferredWidth;
}
else
{
return curTxt.preferredWidth > maxPreferredWidth ? maxPreferredWidth : curTxt.preferredWidth;
}
}
}
public void CalculateLayoutInputHorizontal()
{
cacheReferences();
}
public void CalculateLayoutInputVertical()
{
cacheReferences();
}
private void cacheReferences()
{
if (!cached)
{
curTxt = gameObject.GetComponent<TMP_Text>();
cached = true;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 924b8e04b3fc53e448dc2b03624e1291
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,46 @@
using System;
using UnityEngine;
public static class FloatExtensions
{
public static string ToPercentageString(this float value)
{
int num = Mathf.RoundToInt(value * 100);
return string.Format("{0}%", num);
}
}
public static class StringExtensions
{
/// <summary>
/// 安全的字符串格式化扩展方法。如果格式化失败,返回原始格式字符串并输出错误日志。
/// </summary>
/// <param name="format">包含格式项的字符串。</param>
/// <param name="args">要格式化的对象数组。</param>
/// <returns>格式化后的字符串;如果格式化失败,返回原始格式字符串。</returns>
public static string SafeFormat(this string format, params object[] args)
{
if (format == null)
{
Debug.LogError("Error: Format string is null.");
return null;
}
try
{
return string.Format(format, args);
}
catch (FormatException ex)
{
Debug.LogError($"String formatting failed: {ex.Message}\n" +
$"Format string: {format}\n" +
$"Argument count: {args?.Length ?? 0}");
return format;
}
catch (Exception ex)
{
Debug.LogError($"Unknown error occurred during string formatting: {ex.Message}");
return format;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fc5d46d525f921d43b539af107736c5f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,772 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Sprites;
using UnityEngine.UI;
/// <summary>
/// The UI image mirror used to mirror image.
/// </summary>
[AddComponentMenu("Oasis/UI/Image Mirror")]
[RequireComponent(typeof(RectTransform))]
[RequireComponent(typeof(Image))]
public sealed class ImageMirror : BaseMeshEffect, ILayoutElement
{
[SerializeField] [Tooltip("The mirror type.")]
private MirrorModeType mirrorMode = MirrorModeType.Horizontal;
/// <summary>
/// The mirror type.
/// </summary>
public enum MirrorModeType
{
/// <summary>
/// Mirror horizontal mode.
/// </summary>
Horizontal,
/// <summary>
/// Mirror vertical mode.
/// </summary>
Vertical,
/// <summary>
/// Quarter mode.
/// </summary>
Quarter,
/// <summary>
/// Mirror horizontal and inverse vertical mode.
/// </summary>
HorizontalInverse,
/// <summary>
/// Mirror vertical and inverse horizontal mode.
/// </summary>
VerticalInverse,
}
/// <summary>
/// Gets or sets the mirror mode.
/// </summary>
public MirrorModeType MirrorMode
{
get => this.mirrorMode;
set
{
if (this.mirrorMode != value)
{
this.mirrorMode = value;
this.graphic?.SetVerticesDirty();
}
}
}
/// <inheritdoc/>
[System.Diagnostics.CodeAnalysis.SuppressMessage(
"StyleCop.CSharp.NamingRules",
"SA1300:ElementMustBeginWithUpperCaseLetter",
Justification = "Reviewed. Suppression is OK here.")]
public float flexibleHeight => -1;
/// <inheritdoc/>
[System.Diagnostics.CodeAnalysis.SuppressMessage(
"StyleCop.CSharp.NamingRules",
"SA1300:ElementMustBeginWithUpperCaseLetter",
Justification = "Reviewed. Suppression is OK here.")]
public float flexibleWidth => -1;
/// <inheritdoc/>
[System.Diagnostics.CodeAnalysis.SuppressMessage(
"StyleCop.CSharp.NamingRules",
"SA1300:ElementMustBeginWithUpperCaseLetter",
Justification = "Reviewed. Suppression is OK here.")]
public int layoutPriority => 0;
/// <inheritdoc/>
[System.Diagnostics.CodeAnalysis.SuppressMessage(
"StyleCop.CSharp.NamingRules",
"SA1300:ElementMustBeginWithUpperCaseLetter",
Justification = "Reviewed. Suppression is OK here.")]
public float minHeight => 0;
/// <inheritdoc/>
[System.Diagnostics.CodeAnalysis.SuppressMessage(
"StyleCop.CSharp.NamingRules",
"SA1300:ElementMustBeginWithUpperCaseLetter",
Justification = "Reviewed. Suppression is OK here.")]
public float minWidth => 0;
/// <inheritdoc/>
[System.Diagnostics.CodeAnalysis.SuppressMessage(
"StyleCop.CSharp.NamingRules",
"SA1300:ElementMustBeginWithUpperCaseLetter",
Justification = "Reviewed. Suppression is OK here.")]
public float preferredHeight
{
get
{
var image = this.graphic as Image;
if (image == null)
{
return 0;
}
switch (this.mirrorMode)
{
case MirrorModeType.Vertical:
case MirrorModeType.Quarter:
return 2 * image.preferredHeight;
default:
return image.preferredHeight;
}
}
}
/// <inheritdoc/>
[System.Diagnostics.CodeAnalysis.SuppressMessage(
"StyleCop.CSharp.NamingRules",
"SA1300:ElementMustBeginWithUpperCaseLetter",
Justification = "Reviewed. Suppression is OK here.")]
public float preferredWidth
{
get
{
var image = this.graphic as Image;
if (image == null)
{
return 0;
}
switch (this.mirrorMode)
{
case MirrorModeType.Horizontal:
case MirrorModeType.Quarter:
return 2 * image.preferredWidth;
default:
return image.preferredWidth;
}
}
}
/// <summary>
/// Set the native size for this mirror.
/// </summary>
public void SetNativeSize()
{
var image = this.graphic as Image;
if (image == null)
{
return;
}
var overrideSprite = image.overrideSprite;
if (overrideSprite == null)
{
return;
}
var w = overrideSprite.rect.width / image.pixelsPerUnit;
var h = overrideSprite.rect.height / image.pixelsPerUnit;
var rectTransform = this.transform as RectTransform;
rectTransform.anchorMax = rectTransform.anchorMin;
switch (this.mirrorMode)
{
case MirrorModeType.Horizontal:
rectTransform.sizeDelta = new Vector2(w * 2, h);
break;
case MirrorModeType.Vertical:
rectTransform.sizeDelta = new Vector2(w, h * 2);
break;
case MirrorModeType.Quarter:
rectTransform.sizeDelta = new Vector2(w * 2, h * 2);
break;
}
image.SetVerticesDirty();
}
/// <inheritdoc/>
public void CalculateLayoutInputHorizontal()
{
}
/// <inheritdoc/>
public void CalculateLayoutInputVertical()
{
}
/// <inheritdoc/>
public override void ModifyMesh(VertexHelper vh)
{
if (!this.IsActive() || vh.currentVertCount <= 0)
{
return;
}
var verts = ListPool<UIVertex>.Get();
vh.GetUIVertexStream(verts);
var newVerts = this.Modify(verts);
if (newVerts != null)
{
vh.Clear();
vh.AddUIVertexTriangleStream(newVerts);
}
ListPool<UIVertex>.Release(verts);
}
#if UNITY_EDITOR
/// <inheritdoc/>
protected override void OnValidate()
{
base.OnValidate();
this.graphic?.SetVerticesDirty();
}
#endif
/// <inheritdoc/>
protected override void OnEnable()
{
base.OnEnable();
this.graphic?.SetVerticesDirty();
}
private static float GetCenter(float p1, float p2, float p3)
{
var max = Mathf.Max(Mathf.Max(p1, p2), p3);
var min = Mathf.Min(Mathf.Min(p1, p2), p3);
return (max + min) / 2;
}
private static Vector2 GetOverturnUV(
Vector2 uv, float start, float end, bool isHorizontal = true)
{
if (isHorizontal)
{
uv.x = end - uv.x + start;
}
else
{
uv.y = end - uv.y + start;
}
return uv;
}
private List<UIVertex> Modify(List<UIVertex> verts)
{
var image = this.graphic as Image;
if (image == null)
{
return verts;
}
switch (image.type)
{
case Image.Type.Simple:
return this.ModifySimple(verts);
case Image.Type.Sliced:
return this.ModifySliced(image, verts);
case Image.Type.Tiled:
return this.ModifyTiled(image, verts);
}
return null;
}
private List<UIVertex> ModifySimple(List<UIVertex> verts)
{
switch (this.mirrorMode)
{
case MirrorModeType.Horizontal:
return this.ModifySimpleHorizontal(verts, false);
case MirrorModeType.HorizontalInverse:
return this.ModifySimpleHorizontal(verts, true);
case MirrorModeType.Vertical:
return this.ModifySimpleVertical(verts, false);
case MirrorModeType.VerticalInverse:
return this.ModifySimpleVertical(verts, true);
case MirrorModeType.Quarter:
return this.ModifySimpleQuarter(verts);
}
return null;
}
private List<UIVertex> ModifySimpleHorizontal(
List<UIVertex> verts, bool inverse)
{
var rect = this.graphic.GetPixelAdjustedRect();
var count = verts.Count;
for (int i = 0; i < count; ++i)
{
var vertex = verts[i];
var position = vertex.position;
position.x = (position.x + rect.x) * 0.5f;
vertex.position = position;
verts[i] = vertex;
}
verts.Capacity = count * 2;
if (inverse)
{
this.MirrorVertsHorizontalInverse(rect, verts);
}
else
{
this.MirrorVertsHorizontal(rect, verts);
}
return verts;
}
private List<UIVertex> ModifySimpleVertical(
List<UIVertex> verts, bool inverse)
{
var rect = this.graphic.GetPixelAdjustedRect();
var halfHeight = rect.height * 0.5f;
var count = verts.Count;
for (int i = 0; i < count; ++i)
{
var vertex = verts[i];
var position = vertex.position;
position.y = ((position.y + rect.y) * 0.5f) + halfHeight;
vertex.position = position;
verts[i] = vertex;
}
verts.Capacity = count * 2;
if (inverse)
{
this.MirrorVertsVecticalInverse(rect, verts);
}
else
{
this.MirrorVertsVectical(rect, verts);
}
return verts;
}
private List<UIVertex> ModifySimpleQuarter(List<UIVertex> verts)
{
var rect = this.graphic.GetPixelAdjustedRect();
var halfHeight = rect.height * 0.5f;
var count = verts.Count;
for (int i = 0; i < count; ++i)
{
var vertex = verts[i];
var position = vertex.position;
position.x = (position.x + rect.x) * 0.5f;
position.y = ((position.y + rect.y) * 0.5f) + halfHeight;
vertex.position = position;
verts[i] = vertex;
}
verts.Capacity = count * 4;
this.MirrorVertsHorizontal(rect, verts);
this.MirrorVertsVectical(rect, verts);
return verts;
}
private List<UIVertex> ModifySliced(Image image, List<UIVertex> verts)
{
switch (this.mirrorMode)
{
case MirrorModeType.Horizontal:
return this.ModifySlicedHorizontal(image, verts, false);
case MirrorModeType.HorizontalInverse:
return this.ModifySlicedHorizontal(image, verts, true);
case MirrorModeType.Vertical:
return this.ModifySlicedVertical(image, verts, false);
case MirrorModeType.VerticalInverse:
return this.ModifySlicedVertical(image, verts, true);
case MirrorModeType.Quarter:
return this.ModifySlicedQuarter(image, verts);
}
return null;
}
private List<UIVertex> ModifySlicedHorizontal(
Image image, List<UIVertex> verts, bool inverse)
{
var rect = this.graphic.GetPixelAdjustedRect();
var halfWidth = rect.width * 0.5f;
var midX = rect.x + halfWidth;
var count = verts.Count;
for (int i = 0; i < count; ++i)
{
var vertex = verts[i];
var position = vertex.position;
if (position.x >= midX)
{
position.x = midX;
}
vertex.position = position;
verts[i] = vertex;
}
this.SliceExcludeVerts(verts);
verts.Capacity = count * 2;
if (inverse)
{
this.MirrorVertsHorizontalInverse(rect, verts);
}
else
{
this.MirrorVertsHorizontal(rect, verts);
}
return verts;
}
private List<UIVertex> ModifySlicedVertical(
Image image, List<UIVertex> verts, bool inverse)
{
var rect = this.graphic.GetPixelAdjustedRect();
var halfHeight = rect.height * 0.5f;
var midY = rect.y + halfHeight;
var count = verts.Count;
for (int i = 0; i < count; ++i)
{
var vertex = verts[i];
var position = vertex.position;
if (position.y <= midY)
{
position.y = midY;
}
vertex.position = position;
verts[i] = vertex;
}
this.SliceExcludeVerts(verts);
verts.Capacity = count * 2;
if (inverse)
{
this.MirrorVertsVecticalInverse(rect, verts);
}
else
{
this.MirrorVertsVectical(rect, verts);
}
return verts;
}
private List<UIVertex> ModifySlicedQuarter(
Image image, List<UIVertex> verts)
{
var rect = this.graphic.GetPixelAdjustedRect();
var halfWidth = rect.width * 0.5f;
var halfHeight = rect.height * 0.5f;
var midX = rect.x + halfWidth;
var midY = rect.y + halfHeight;
var count = verts.Count;
for (int i = 0; i < count; ++i)
{
var vertex = verts[i];
var position = vertex.position;
if (position.x >= midX)
{
position.x = midX;
}
if (position.y <= midY)
{
position.y = midY;
}
vertex.position = position;
verts[i] = vertex;
}
this.SliceExcludeVerts(verts);
verts.Capacity = count * 2;
this.MirrorVertsHorizontal(rect, verts);
this.MirrorVertsVectical(rect, verts);
return verts;
}
private List<UIVertex> ModifyTiled(Image image, List<UIVertex> verts)
{
switch (this.mirrorMode)
{
case MirrorModeType.Horizontal:
return this.ModifyTiledHorizontal(image, verts);
case MirrorModeType.Vertical:
return this.ModifyTiledVertical(image, verts);
case MirrorModeType.Quarter:
return this.ModifyTiledQuarter(image, verts);
}
return null;
}
private List<UIVertex> ModifyTiledHorizontal(
Image image, List<UIVertex> verts)
{
var overrideSprite = image.overrideSprite;
if (overrideSprite == null)
{
return null;
}
var rect = this.graphic.GetPixelAdjustedRect();
var inner = DataUtility.GetInnerUV(overrideSprite);
var w = overrideSprite.rect.width / image.pixelsPerUnit;
var count = verts.Count;
var len = count / 3;
for (var i = 0; i < len; ++i)
{
var baseIndex = i * 3;
var v1 = verts[baseIndex + 0];
var v2 = verts[baseIndex + 1];
var v3 = verts[baseIndex + 2];
var centerX = GetCenter(
v1.position.x, v2.position.x, v3.position.x);
if (Mathf.FloorToInt((centerX - rect.xMin) / w) % 2 == 1)
{
v1.uv0.x = inner.z - v1.uv0.x + inner.x;
v2.uv0.x = inner.z - v2.uv0.x + inner.x;
v3.uv0.x = inner.z - v3.uv0.x + inner.x;
}
verts[baseIndex + 0] = v1;
verts[baseIndex + 1] = v2;
verts[baseIndex + 2] = v3;
}
return verts;
}
private List<UIVertex> ModifyTiledVertical(
Image image, List<UIVertex> verts)
{
var overrideSprite = image.overrideSprite;
if (overrideSprite == null)
{
return null;
}
var rect = this.graphic.GetPixelAdjustedRect();
var inner = DataUtility.GetInnerUV(overrideSprite);
var h = overrideSprite.rect.height / image.pixelsPerUnit;
var count = verts.Count;
var len = count / 3;
for (var i = 0; i < len; ++i)
{
var baseIndex = i * 3;
var v1 = verts[baseIndex + 0];
var v2 = verts[baseIndex + 1];
var v3 = verts[baseIndex + 2];
var centerY = GetCenter(v1.position.y, v2.position.y, v3.position.y);
if (Mathf.FloorToInt((centerY - rect.yMin) / h) % 2 == 1)
{
v1.uv0.y = inner.w - v1.uv0.y + inner.y;
v2.uv0.y = inner.w - v2.uv0.y + inner.y;
v3.uv0.y = inner.w - v3.uv0.y + inner.y;
}
verts[baseIndex + 0] = v1;
verts[baseIndex + 1] = v2;
verts[baseIndex + 2] = v3;
}
return verts;
}
private List<UIVertex> ModifyTiledQuarter(
Image image, List<UIVertex> verts)
{
var overrideSprite = image.overrideSprite;
if (overrideSprite == null)
{
return null;
}
var rect = this.graphic.GetPixelAdjustedRect();
var inner = DataUtility.GetInnerUV(overrideSprite);
var w = overrideSprite.rect.width / image.pixelsPerUnit;
var h = overrideSprite.rect.height / image.pixelsPerUnit;
var count = verts.Count;
var len = count / 3;
for (var i = 0; i < len; ++i)
{
var baseIndex = i * 3;
var v1 = verts[baseIndex + 0];
var v2 = verts[baseIndex + 1];
var v3 = verts[baseIndex + 2];
var centerX = GetCenter(
v1.position.x, v2.position.x, v3.position.x);
var centerY = GetCenter(
v1.position.y, v2.position.y, v3.position.y);
if (Mathf.FloorToInt((centerX - rect.xMin) / w) % 2 == 1)
{
v1.uv0.x = inner.z - v1.uv0.x + inner.x;
v2.uv0.x = inner.z - v2.uv0.x + inner.x;
v3.uv0.x = inner.z - v3.uv0.x + inner.x;
}
if (Mathf.FloorToInt((centerY - rect.yMin) / h) % 2 == 1)
{
v1.uv0.y = inner.w - v1.uv0.y + inner.y;
v2.uv0.y = inner.w - v2.uv0.y + inner.y;
v3.uv0.y = inner.w - v3.uv0.y + inner.y;
}
verts[baseIndex + 0] = v1;
verts[baseIndex + 1] = v2;
verts[baseIndex + 2] = v3;
}
return verts;
}
private void MirrorVertsHorizontal(Rect rect, List<UIVertex> verts)
{
var count = verts.Count;
for (int i = 0; i < count; ++i)
{
var vertex = verts[i];
var position = vertex.position;
position.x = (rect.center.x * 2) - position.x;
vertex.position = position;
verts.Add(vertex);
}
}
private void MirrorVertsHorizontalInverse(
Rect rect, List<UIVertex> verts)
{
var count = verts.Count;
var center = rect.center;
for (int i = 0; i < count; ++i)
{
var vertex = verts[i];
var position = vertex.position;
position.x = (center.x * 2) - position.x;
position.y = (center.y * 2) - position.y;
vertex.position = position;
verts.Add(vertex);
}
}
private void MirrorVertsVectical(Rect rect, List<UIVertex> verts)
{
var count = verts.Count;
for (int i = 0; i < count; ++i)
{
var vertex = verts[i];
var position = vertex.position;
position.y = (rect.center.y * 2) - position.y;
vertex.position = position;
verts.Add(vertex);
}
}
private void MirrorVertsVecticalInverse(
Rect rect, List<UIVertex> verts)
{
var count = verts.Count;
for (int i = 0; i < count; ++i)
{
var vertex = verts[i];
var position = vertex.position;
position.x = (rect.center.x * 2) - position.x;
position.y = (rect.center.y * 2) - position.y;
vertex.position = position;
verts.Add(vertex);
}
}
private Vector4 GetAdjustedBorders(Image image, Rect rect)
{
var overrideSprite = image.overrideSprite;
var border = overrideSprite.border;
border = border / image.pixelsPerUnit;
var combinedWidth = border.x + border.z;
if (rect.size.x < combinedWidth && combinedWidth != 0)
{
var scaleRatio = rect.size.x / combinedWidth;
border.x *= scaleRatio;
border.z *= scaleRatio;
}
var combinedHeight = border.y + border.w;
if (rect.size.y < combinedHeight && combinedHeight != 0)
{
var scaleRatio = rect.size.y / combinedHeight;
border.y *= scaleRatio;
border.w *= scaleRatio;
}
return border;
}
private void SliceExcludeVerts(List<UIVertex> verts)
{
var realCount = verts.Count;
var i = 0;
while (i < realCount)
{
var v1 = verts[i];
var v2 = verts[i + 1];
var v3 = verts[i + 2];
if (v1.position == v2.position ||
v2.position == v3.position ||
v3.position == v1.position)
{
verts[i] = verts[realCount - 3];
verts[i + 1] = verts[realCount - 2];
verts[i + 2] = verts[realCount - 1];
realCount -= 3;
continue;
}
i += 3;
}
if (realCount < verts.Count)
{
verts.RemoveRange(realCount, verts.Count - realCount);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7f5b823c1ac5824428ff87bdfbc0d98a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,72 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
public class LongPressOrClickEventTrigger : UIBehaviour, IPointerDownHandler, IPointerUpHandler, IPointerExitHandler,
IPointerClickHandler
{
public float durationThreshold = 1.0f;
public UnityEvent onLongPress = new UnityEvent();
public UnityEvent onClick = new UnityEvent();
public UnityEvent onDown = new UnityEvent();
public UnityEvent onUp = new UnityEvent();
private bool isPointerDown = false;
private bool longPressTriggered = false;
private float timePressStarted;
private void Update()
{
if (isPointerDown && !longPressTriggered)
{
if (Time.time - timePressStarted > 0.2f)
{
onLongPress.Invoke();
longPressTriggered = true;
}
// if (Time.time - timePressStarted > 0.2)
// {
// longPressTriggered = true;
// onLongPress.Invoke();
// }
}
}
public void OnPointerDown(PointerEventData eventData)
{
timePressStarted = Time.time;
isPointerDown = true;
longPressTriggered = false;
onDown.Invoke();
}
public void OnPointerUp(PointerEventData eventData)
{
isPointerDown = false;
onUp.Invoke();
}
public void OnPointerExit(PointerEventData eventData)
{
isPointerDown = false;
// onUp.Invoke();
}
public void OnPointerClick(PointerEventData eventData)
{
if (!longPressTriggered)
{
onClick.Invoke();
}
}
protected override void OnDisable()
{
base.OnDisable();
isPointerDown = false;
longPressTriggered = false;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fce04e7aebd477444a03f7700681bd6f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,132 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class MeshImage : Image
{
private Vector2[] pos;
private Vector2[] uvs;
public int rotatePointIndex;
[SerializeField]
private bool isErrorReset;
public void SetPos(Vector2[] pos, bool referesh)
{
this.pos = pos;
this.uvs = SetUvs(pos);
if (referesh)
{
SetAllDirty();
}
}
public void SetSize(float width, float height, bool adaptPointToSize)
{
rectTransform.sizeDelta = new Vector2(width, height);
if (adaptPointToSize)
{
float minW = 9999;
float minH = 9999;
float maxW = -1;
float maxH = -1;
foreach (var po in pos)
{
if (po.x < minW)
{
minW = po.x;
}
if (po.x > maxW)
{
maxW = po.x;
}
if (po.y < minH)
{
minH = po.y;
}
if (po.y > maxH)
{
maxH = po.y;
}
}
float w = maxW - minW;
float h = maxH - minH;
float sw = w / width;
float sh = h / height;
float s = sw > sh ? sw : sh;
for (int i = 0; i < pos.Length; i++)
{
pos[i] /= s;
}
SetPos(pos, true);
}
}
public void SetRotatePointIndex(int index)
{
rotatePointIndex = index;
}
public Vector2[] GetPos()
{
return pos;
}
private Vector2[] SetUvs(Vector2[] tempPos)
{
Vector2[] tempUvs = new Vector2[tempPos.Length];
for (int i = 0; i < tempPos.Length; i++)
{
tempUvs[i] = new Vector2(tempPos[i].x / rectTransform.rect.width + 0.5f,
tempPos[i].y / rectTransform.rect.height + 0.5f);
}
return tempUvs;
}
protected override void OnPopulateMesh(VertexHelper vh)
{
Vector2[] tempPos = pos;
Vector2[] tempUvs = uvs;
if (tempPos == null)
{
base.OnPopulateMesh(vh);
return;
}
Color32 color32 = color;
vh.Clear();
try
{
for (int i = 0; i < tempPos.Length; i++)
{
vh.AddVert(tempPos[i], color32, tempUvs[i]);
}
Triangulator triangular = new Triangulator(tempPos); //计算三角面的类
int[] indices = triangular.Triangulate(); //得到三角面
for (int i = 0; i < indices.Length - 2; i += 3)
{
vh.AddTriangle(indices[i], indices[i + 1], indices[i + 2]);
}
}
catch (Exception e)
{
Debug.LogError(e.ToString());
base.OnPopulateMesh(vh);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2a37f4f91bafa7b4aaf1929f6e103d75
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,687 @@
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System;
using System.Collections.Generic;
using DG.Tweening;
public class PanelScroll : ScrollRect
{
// [SerializeField] public float inertiaMaxTime = 0.5f; //限制惯性持续时间
// private float _scrolledTime = 0f;
private Action _stopScrollCallback = null;
private Vector2 _lastPosition = Vector2.zero;
private float offsetX;
private RectTransform _content;
private Action StopScrollCallback;
private Action RefreshItem;
public bool loop = false;
public int currentIndex;
public int FirstIndex;
public int CurDownIndex;
private int minShowItemNum;
List<GameObject> itemGoList = new List<GameObject>();
Vector2 startDeltaPos;
Vector2 endDeltaDirection;
bool isDrag = false;
public bool isReversal = false;
int minShowAdd = 2;
Vector2 InverseTransformPointOffset;
float startAdd = 0;
protected override void Start()
{
base.Start();
RectTransform rectTransform = GetComponent<RectTransform>();
var pivot = rectTransform.pivot - new Vector2(0.5f, 0.5f);
var rect = rectTransform.rect.size;
InverseTransformPointOffset = new Vector2(pivot.x * rect.x, pivot.y * rect.y);
}
public List<T> Init<T, T1>(float _offsetX, GameObject _item, Action<T> _OnBtnItem,
List<T1> _ItemData, bool click = false, int _currentIndex = 0, int _minShowAdd = 2)
where T : PanelItemBase<T1>
{
float spacing = 0;
float addSizeDelta = 0; startAdd = 0;
if (horizontal)
{
HorizontalLayoutGroup layoutGroup = content.GetComponent<HorizontalLayoutGroup>();
if (layoutGroup != null)
{
spacing = layoutGroup.spacing;
addSizeDelta = layoutGroup.padding.horizontal;
startAdd = layoutGroup.padding.left;
layoutGroup.enabled = false;
}
}
else
{
VerticalLayoutGroup layoutGroup = content.GetComponent<VerticalLayoutGroup>();
if (layoutGroup != null)
{
spacing = layoutGroup.spacing;
addSizeDelta = layoutGroup.padding.vertical;
startAdd = layoutGroup.padding.top;
layoutGroup.enabled = false;
}
}
_offsetX += spacing;
minShowAdd = _minShowAdd;
if (_currentIndex >= _ItemData.Count)
{
_currentIndex = _ItemData.Count - 1;
}
int _showItemNum;
int showDelta = _ItemData.Count;
if (horizontal)
minShowItemNum = Mathf.CeilToInt(GetComponent<RectTransform>().rect.width / _offsetX) + minShowAdd;
else
minShowItemNum = Mathf.CeilToInt(GetComponent<RectTransform>().rect.height / _offsetX) + minShowAdd;
_showItemNum = minShowItemNum;
if (loop)
{
showDelta = minShowItemNum;
}
else if (minShowItemNum > _ItemData.Count)
{
_showItemNum = showDelta;
}
movementType = loop ? MovementType.Unrestricted : MovementType.Elastic;
offsetX = _offsetX;
_item.gameObject.SetActive(false);
_content = transform.Find("Viewport/Content").GetComponent<RectTransform>();
_content.sizeDelta = horizontal ? new Vector2(showDelta * _offsetX + addSizeDelta, _content.sizeDelta.y) : new Vector2(_content.sizeDelta.x, showDelta * _offsetX + addSizeDelta);
if (isReversal)
{
_content.anchoredPosition = horizontal ?
new Vector2(loop ? -((_showItemNum - 1) / 2f - _currentIndex) * _offsetX : _currentIndex * _offsetX, _content.anchoredPosition.y) :
new Vector2(_content.anchoredPosition.x, loop ? -(_currentIndex - (_showItemNum - 1) / 2f) * _offsetX : -_currentIndex * _offsetX);
}
else
{
_content.anchoredPosition = horizontal ?
new Vector2(loop ? ((_showItemNum - 1) / 2f - _currentIndex) * _offsetX : -_currentIndex * _offsetX, _content.anchoredPosition.y) :
new Vector2(_content.anchoredPosition.x, loop ? (_currentIndex - (_showItemNum - 1) / 2f) * _offsetX : _currentIndex * _offsetX);
}
List<T> items = new List<T>();
int count = itemGoList.Count;
for (int i = 0; i < count; i++)
{
itemGoList[i].SetActive(false);
}
for (int i = 0; i < _showItemNum; i++)
{
GameObject go;
if (count > i)
{
go = itemGoList[i].gameObject;
}
else
{
go = Instantiate(_item, _content);
itemGoList.Add(go);
}
go.SetActive(true);
if (isReversal)
{
go.transform.GetComponent<RectTransform>().anchoredPosition = horizontal ?
new Vector3(-(i + 0.5f) * _offsetX - startAdd, go.transform.GetComponent<RectTransform>().anchoredPosition.y, 0) :
new Vector3(go.transform.GetComponent<RectTransform>().anchoredPosition.x, (i + 0.5f) * _offsetX + startAdd, 0);
}
else
{
go.transform.GetComponent<RectTransform>().anchoredPosition = horizontal ?
new Vector3((i + 0.5f) * _offsetX + startAdd, go.transform.GetComponent<RectTransform>().anchoredPosition.y, 0) :
new Vector3(go.transform.GetComponent<RectTransform>().anchoredPosition.x, -(i + 0.5f) * _offsetX - startAdd, 0);
}
T t = go.GetComponent<T>() ?? go.AddComponent<T>();
items.Add(t);
items[i].index = i;
var i1 = i;
items[i].OnBtnItemAction = () => { _OnBtnItem?.Invoke(items[i1]); };
items[i].SetDataAction = () =>
{
int count = _ItemData.Count;
items[i1].index %= count;
if (items[i1].index < 0)
{
items[i1].index += count;
}
return _ItemData[items[i1].index];
};
}
if (isReversal)
{
ReversalSetOnValueChanged(items, _ItemData);
}
else
{
SetOnValueChanged(items, _ItemData);
}
SetStopScrollCallback(click, items, _ItemData);
RefreshItem = () =>
{
foreach (var t in items)
{
t.SetData();
}
};
currentIndex = _currentIndex;
if (currentIndex > 1)
{
if (!loop)
{
if (currentIndex + _showItemNum > showDelta)
{
currentIndex = showDelta - _showItemNum;
}
currentIndex--;
}
//currentIndex -= minShowItemNum;
for (int i = items.Count - 1; i >= 0; i--)
{
T t = items[i];
if (isReversal)
{
t.rectTransform.anchoredPosition = horizontal ?
new Vector3(t.rectTransform.anchoredPosition.x - currentIndex * offsetX, t.rectTransform.anchoredPosition.y, 0) :
new Vector3(t.rectTransform.anchoredPosition.x, t.rectTransform.anchoredPosition.y + currentIndex * offsetX, 0);
}
else
{
t.rectTransform.anchoredPosition = horizontal ?
new Vector3(t.rectTransform.anchoredPosition.x + currentIndex * offsetX, t.rectTransform.anchoredPosition.y, 0) :
new Vector3(t.rectTransform.anchoredPosition.x, t.rectTransform.anchoredPosition.y - currentIndex * offsetX, 0);
}
t.index += currentIndex;
}
}
RefreshItem();
currentIndex = _currentIndex;
if (click)
{
if (currentIndex > 0)
{
for (int i = 0; i < items.Count; i++)
{
if (items[i].index == _currentIndex)
{
_OnBtnItem?.Invoke(items[i]);
return items;
}
}
}
if (items.Count > 0)
{
_OnBtnItem?.Invoke(items[0]);
}
}
return items;
}
void ReversalSetOnValueChanged<T, T1>(List<T> items, List<T1> _ItemData) where T : PanelItemBase<T1>
{
onValueChanged.RemoveAllListeners();
if (horizontal)
{
onValueChanged.AddListener(arg0 =>
{
foreach (var t in items)
{
//transform相对于scrollRect的位置
var arg1 = InverseTransformPoint(t.transform.position);
if (arg1.x < -(minShowItemNum + 1) / 2 * offsetX/* - offsetX*/)
{
if (loop || t.index - minShowItemNum >= 0)
{
t.rectTransform.anchoredPosition =
new Vector3(t.rectTransform.anchoredPosition.x + minShowItemNum * offsetX, t.rectTransform.anchoredPosition.y, 0);
t.OnChangIndex(-minShowItemNum);
}
}
else if (arg1.x > (minShowItemNum + 1) / 2 * offsetX /*+ offsetX*/)
{
if (loop || t.index + minShowItemNum < _ItemData.Count)
{
t.rectTransform.anchoredPosition =
new Vector3(t.rectTransform.anchoredPosition.x - minShowItemNum * offsetX, t.rectTransform.anchoredPosition.y, 0);
t.OnChangIndex(minShowItemNum);
}
}
arg1 = InverseTransformPoint(t.transform.position);
t.OffsetX(arg1.x, offsetX);
}
});
}
else
{
onValueChanged.AddListener(arg0 =>
{
foreach (var t in items)
{
//transform相对于scrollRect的位置
var arg1 = InverseTransformPoint(t.transform.position);
if (arg1.y < -(minShowItemNum + 1) / 2 * offsetX/* - offsetX*/)
{
if (loop || t.index + minShowItemNum < _ItemData.Count)
{
t.rectTransform.anchoredPosition =
new Vector3(t.rectTransform.anchoredPosition.x, t.rectTransform.anchoredPosition.y + minShowItemNum * offsetX, 0);
t.OnChangIndex(minShowItemNum);
}
}
else if (arg1.y > (minShowItemNum + 1) / 2 * offsetX /*+ offsetX*/)
{
if (loop || t.index - minShowItemNum >= 0)
{
t.rectTransform.anchoredPosition =
new Vector3(t.rectTransform.anchoredPosition.x, t.rectTransform.anchoredPosition.y - minShowItemNum * offsetX, 0);
t.OnChangIndex(-minShowItemNum);
}
}
arg1 = InverseTransformPoint(t.transform.position);
t.OffsetX(arg1.y, offsetX);
}
});
}
}
void SetOnValueChanged<T, T1>(List<T> items, List<T1> _ItemData) where T : PanelItemBase<T1>
{
onValueChanged.RemoveAllListeners();
if (horizontal)
{
onValueChanged.AddListener(arg0 =>
{
var panelHeight = GetComponent<RectTransform>().rect.width;
var panelUpPos = panelHeight / 2f;
var PanelDownPos = -panelHeight / 2f;
foreach (var t in items)
{
//transform相对于scrollRect的位置
var arg1 = InverseTransformPoint(t.transform.position);
//进入退出窗口判断
var itemUpPos = arg1.x + offsetX / 2f;
var itemDownPos = arg1.x - offsetX / 2f;
if (itemUpPos > PanelDownPos && CurDownIndex < t.index)
CurDownIndex = t.index;
if (itemUpPos < PanelDownPos && CurDownIndex >= t.index)
CurDownIndex = Mathf.Clamp(t.index - 1, 0, _ItemData.Count - 1);
if (itemDownPos < panelUpPos && FirstIndex > t.index)
{
FirstIndex = t.index;
}
if (itemDownPos > panelUpPos && FirstIndex <= t.index)
FirstIndex = Mathf.Clamp(t.index + 1, 0, _ItemData.Count - 1);
if (arg1.x < -(minShowItemNum + 1) / 2 * offsetX/* - offsetX*/)
{
if (loop || t.index + minShowItemNum < _ItemData.Count)
{
t.rectTransform.anchoredPosition =
new Vector3(t.rectTransform.anchoredPosition.x + minShowItemNum * offsetX, t.rectTransform.anchoredPosition.y, 0);
t.OnChangIndex(minShowItemNum);
}
}
else if (arg1.x > (minShowItemNum + 1) / 2 * offsetX /*+ offsetX*/)
{
if (loop || t.index - minShowItemNum >= 0)
{
t.rectTransform.anchoredPosition =
new Vector3(t.rectTransform.anchoredPosition.x - minShowItemNum * offsetX, t.rectTransform.anchoredPosition.y, 0);
t.OnChangIndex(-minShowItemNum);
}
}
arg1 = InverseTransformPoint(t.transform.position);
t.OffsetX(arg1.x, offsetX);
}
});
}
else
{
onValueChanged.AddListener(arg0 =>
{
var panelHeight = GetComponent<RectTransform>().rect.height;
var panelUpPos = panelHeight / 2f;
var PanelDownPos = -panelHeight / 2f;
foreach (var t in items)
{
//transform相对于scrollRect的位置
var arg1 = InverseTransformPoint(t.transform.position);
//进入退出窗口判断
var itemUpPos = arg1.y + offsetX / 2f;
var itemDownPos = arg1.y - offsetX / 2f;
if (itemUpPos > PanelDownPos && CurDownIndex < t.index)
CurDownIndex = t.index;
if (itemUpPos < PanelDownPos && CurDownIndex >= t.index)
CurDownIndex = Mathf.Clamp(t.index - 1, 0, _ItemData.Count - 1);
if (itemDownPos < panelUpPos && FirstIndex > t.index)
{
FirstIndex = t.index;
}
if (itemDownPos > panelUpPos && FirstIndex <= t.index)
FirstIndex = Mathf.Clamp(t.index + 1, 0, _ItemData.Count - 1);
//循环判断
if (arg1.y < -(minShowItemNum + 1) / 2 * offsetX /*- offsetX*/)
{
if (loop || t.index - minShowItemNum >= 0)
{
t.rectTransform.anchoredPosition =
new Vector3(t.rectTransform.anchoredPosition.x, t.rectTransform.anchoredPosition.y + minShowItemNum * offsetX, 0);
t.OnChangIndex(-minShowItemNum);
}
}
else if (arg1.y > (minShowItemNum + 1) / 2 * offsetX /*+ offsetX*/)
{
if (loop || t.index + minShowItemNum < _ItemData.Count)
{
t.rectTransform.anchoredPosition =
new Vector3(t.rectTransform.anchoredPosition.x, t.rectTransform.anchoredPosition.y - minShowItemNum * offsetX, 0);
t.OnChangIndex(minShowItemNum);
}
}
arg1 = InverseTransformPoint(t.transform.position);
t.OffsetX(arg1.y, offsetX);
}
});
}
}
void SetStopScrollCallback<T, T1>(bool click, List<T> items, List<T1> _ItemData) where T : PanelItemBase<T1>
{
if (click)
{
if (horizontal)
{
StopScrollCallback = () =>
{
int count = items.Count;
for (int i = 0; i < count; i++)
{
T t = items[i];
Vector3 pos = InverseTransformPoint(t.transform.position);
if (pos.x > -offsetX / 2 - 0.01f && pos.x < offsetX / 2 + 0.01f)
{
if (isDrag)
{
if (endDeltaDirection.x > 1)
{
if (pos.x > 5)
{
if (i != 0)
{
if (loop || currentIndex > 0)
{
t = items[i - 1];
}
}
else if (loop || t.index - minShowItemNum / 2 >= 0)
{
t = items[^1];
}
}
}
else if (endDeltaDirection.x < -1)
{
if (pos.x < -5)
{
if (i < count - 1)
{
if (loop || currentIndex < _ItemData.Count - 1)
{
t = items[i + 1];
}
}
else if (loop || t.index + minShowItemNum / 2 < _ItemData.Count)
{
t = items[0];
}
}
}
}
if (!loop)
{
content.DOLocalMoveX(-t.transform.localPosition.x + 0.5f * offsetX, 0.2f);
}
currentIndex = t.index;
t.OnBtnItem();
break;
}
}
isDrag = false;
};
}
else
{
StopScrollCallback = () =>
{
int count = items.Count;
for (int i = 0; i < count; i++)
{
T t = items[i];
Vector3 pos = InverseTransformPoint(t.transform.position);
if (pos.y > -offsetX / 2 - 0.01f && pos.y < offsetX / 2 + 0.01f)
{
if (isDrag)
{
if (endDeltaDirection.y > 1)
{
if (pos.y > 10)
{
if (i < count - 1)
{
t = items[i + 1];
}
else if (loop || t.index + minShowItemNum / 2 < _ItemData.Count)
{
t = items[0];
}
}
}
else if (endDeltaDirection.y < -1)
{
if (pos.y < -10)
{
if (i != 0)
{
t = items[i - 1];
}
else if (loop || t.index - minShowItemNum / 2 >= 0)
{
t = items[^1];
}
}
}
}
if (!loop)
{
content.DOLocalMoveY(-t.transform.localPosition.y - 0.5f * offsetX, 0.2f);
}
currentIndex = t.index;
t.OnBtnItem();
break;
}
}
isDrag = false;
};
}
}
else
{
StopScrollCallback = null;
}
}
//跳到目标位置
public void JumpToTarget(int index, float posOffset = 0f)
{
float offset = offsetX;
if (isReversal)
{
offset = -offsetX;
}
if (loop)
{
if (index > currentIndex)
{
if (horizontal)
{
_content.DOLocalMoveX(_content.localPosition.x - (index - currentIndex) * offset + posOffset, 0.3f).OnComplete(() => { StopScrollCallback?.Invoke(); });
}
else
{
_content.DOLocalMoveY(_content.localPosition.y + (index - currentIndex) * offset + posOffset, 0.3f).OnComplete(() => { StopScrollCallback?.Invoke(); });
}
}
else
{
if (horizontal)
{
_content.DOLocalMoveX(_content.localPosition.x + (currentIndex - index) * offset + posOffset, 0.3f).OnComplete(() => { StopScrollCallback?.Invoke(); });
}
else
{
_content.DOLocalMoveY(_content.localPosition.y - (currentIndex - index) * offset + posOffset, 0.3f).OnComplete(() => { StopScrollCallback?.Invoke(); });
}
}
}
else
{
index -= (int)((minShowItemNum - minShowAdd) / 2f);
if (horizontal)
{
_content.DOLocalMoveX(-index * offset + posOffset, 0.5f).OnComplete(() => { StopScrollCallback?.Invoke(); });
}
else
{
_content.DOLocalMoveY(index * offset + posOffset, 0.5f).OnComplete(() => { StopScrollCallback?.Invoke(); });
}
}
}
public void Refresh()
{
RefreshItem?.Invoke();
}
public override void OnBeginDrag(PointerEventData eventData)
{
base.OnBeginDrag(eventData);
startDeltaPos = eventData.position;
}
public override void OnEndDrag(PointerEventData eventData)
{
base.OnEndDrag(eventData);
endDeltaDirection = eventData.position - startDeltaPos;
isDrag = true;
_stopScrollCallback = StopScrollCallback;
// _scrolledTime = 0f;
//如果没有在移动
if (this.velocity.magnitude < 3)
{
if (_stopScrollCallback != null)
{
_stopScrollCallback();
_stopScrollCallback = null;
}
}
}
public override void OnDrag(PointerEventData eventData)
{
base.OnDrag(eventData);
// _scrolledTime = 0f;
}
protected override void SetContentAnchoredPosition(Vector2 position)
{
if (Vector3.Distance(_lastPosition, position) < 3)
{
if (_stopScrollCallback != null)
{
_stopScrollCallback();
_stopScrollCallback = null;
}
return;
}
_lastPosition = position;
base.SetContentAnchoredPosition(position);
// _scrolledTime += Time.unscaledDeltaTime;
}
public Vector3 InverseTransformPoint(Vector3 position)
{
var point = transform.InverseTransformPoint(position);
point.x += InverseTransformPointOffset.x;
point.y += InverseTransformPointOffset.y;
return point;
}
}
public abstract class PanelItemBase<T> : MonoBehaviour
{
private RectTransform _rectTransform;
public Action OnBtnItemAction;
public Func<T> SetDataAction;
public T data;
public RectTransform rectTransform
{
get
{
if (_rectTransform == null)
{
_rectTransform = GetComponent<RectTransform>();
}
return _rectTransform;
}
}
public int index = 0;
public abstract void OnInit();
public virtual void OffsetX(float _offsetX, float width)
{
}
public virtual void SetData()
{
data = SetDataAction();
OnInit();
}
public virtual void OnBtnItem()
{
OnBtnItemAction?.Invoke();
}
public void OnChangIndex(int _index)
{
index += _index;
SetData();
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: cb82d7ec26d44381af77c9fe5eb75c46
timeCreated: 1690966171

View File

@@ -0,0 +1,41 @@
using UnityEngine;
using UnityEngine.UI;
[RequireComponent(typeof(RectTransform), typeof(TrailRenderer))]
public class ScreenSpaceTrail : MonoBehaviour
{
private RectTransform rectTransform;
private TrailRenderer trail;
private Camera uiCamera;
void Start()
{
rectTransform = GetComponent<RectTransform>();
trail = GetComponent<TrailRenderer>();
uiCamera = GetComponentInParent<Canvas>().worldCamera;
}
void Update()
{
UpdateTrailPosition();
}
void UpdateTrailPosition()
{
// 将UI坐标转换为世界坐标
Vector3 screenPos = RectTransformUtility.WorldToScreenPoint(
uiCamera,
rectTransform.position);
// 设置Z值在相机近裁剪面稍前方
Vector3 worldPos = uiCamera.ScreenToWorldPoint(
new Vector3(screenPos.x, screenPos.y, uiCamera.nearClipPlane + 0.1f));
transform.position = worldPos;
}
public void ClearTrail()
{
trail.Clear();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 64a59ef44005a8c449362d886a44b68d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,97 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class SubScrollRect : ScrollRect
{
//父ScrollRect对象
private ScrollRect m_Parent;
public enum Direction
{
Horizontal,
Vertical
}
//滑动方向
private Direction m_Direction = Direction.Horizontal;
//当前操作方向
private Direction m_BeginDragDirection = Direction.Horizontal;
protected override void Start()
{
base.Start();
//找到父对象
Transform parent = transform.parent;
m_Parent = parent.GetComponentInParent<ScrollRect>();
m_Direction = this.horizontal ? Direction.Horizontal : Direction.Vertical;
}
public override void OnBeginDrag(PointerEventData eventData)
{
if (m_Parent)
{
m_BeginDragDirection = Mathf.Abs(eventData.delta.x) > Mathf.Abs(eventData.delta.y)
? Direction.Horizontal
: Direction.Vertical;
if (m_BeginDragDirection != m_Direction)
{
//当前操作方向不等于滑动方向,将事件传给父对象
ExecuteEvents.Execute(m_Parent.gameObject, eventData, ExecuteEvents.beginDragHandler);
return;
}
}
base.OnBeginDrag(eventData);
}
public override void OnDrag(PointerEventData eventData)
{
if (m_Parent)
{
if (m_BeginDragDirection != m_Direction)
{
//当前操作方向不等于滑动方向,将事件传给父对象
ExecuteEvents.Execute(m_Parent.gameObject, eventData, ExecuteEvents.dragHandler);
return;
}
}
base.OnDrag(eventData);
}
public override void OnEndDrag(PointerEventData eventData)
{
if (m_Parent)
{
if (m_BeginDragDirection != m_Direction)
{
//当前操作方向不等于滑动方向,将事件传给父对象
ExecuteEvents.Execute(m_Parent.gameObject, eventData, ExecuteEvents.endDragHandler);
return;
}
}
base.OnEndDrag(eventData);
}
public override void OnScroll(PointerEventData data)
{
if (m_Parent)
{
if (m_BeginDragDirection != m_Direction)
{
//当前操作方向不等于滑动方向,将事件传给父对象
ExecuteEvents.Execute(m_Parent.gameObject, data, ExecuteEvents.scrollHandler);
return;
}
}
base.OnScroll(data);
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: edfe100865c549d1ad3874cb648c5f3c
timeCreated: 1691565987

View File

@@ -0,0 +1,68 @@
using TMPro;
using UnityEngine;
[RequireComponent(typeof(TMP_Text))]
public class TMP_Text_Curved : MonoBehaviour
{
public TMP_Text m_TextComponent;
public float height = 1;
public float allWidth = 800;
public float radian_angle = 30f;
private void OnValidate()
{
if (m_TextComponent == null)
{
m_TextComponent = GetComponent<TMP_Text>();
}
SetTextCurved();
}
private void Awake()
{
if (m_TextComponent == null)
{
m_TextComponent = GetComponent<TMP_Text>();
}
}
private void LateUpdate()
{
SetTextCurved();
}
void SetTextCurved()
{
m_TextComponent.ForceMeshUpdate();
TMP_TextInfo textInfo = m_TextComponent.textInfo;
if (textInfo == null) return;
int characterCount = textInfo.characterCount;
if (characterCount == 0) return;
Quaternion rotation;
Vector3 center;
var charInfo = textInfo.characterInfo[characterCount - 1];
Vector3[] vertices;
int vertexIndex;
for (int i = 0; i < characterCount; i++)
{
charInfo = textInfo.characterInfo[i];
if (!charInfo.isVisible) continue;
vertices = textInfo.meshInfo[charInfo.materialReferenceIndex].vertices;
vertexIndex = charInfo.vertexIndex;
center = (vertices[vertexIndex + 0] + vertices[vertexIndex + 1] + vertices[vertexIndex + 2] + vertices[vertexIndex + 3]) / 4;
float angle = center.x < 0 ? vertices[vertexIndex + 0].x / allWidth : vertices[vertexIndex + 3].x / allWidth;
rotation = Quaternion.Euler(0, 0, -angle * radian_angle);
vertices[vertexIndex + 0] = rotation * (vertices[vertexIndex + 0] - center) + center;
vertices[vertexIndex + 1] = rotation * (vertices[vertexIndex + 1] - center) + center;
vertices[vertexIndex + 2] = rotation * (vertices[vertexIndex + 2] - center) + center;
vertices[vertexIndex + 3] = rotation * (vertices[vertexIndex + 3] - center) + center;
Vector3 offset = Vector3.up * (Mathf.Cos(angle * Mathf.PI) - 1f) * height;
vertices[vertexIndex + 0] += offset;
vertices[vertexIndex + 1] += offset;
vertices[vertexIndex + 2] += offset;
vertices[vertexIndex + 3] += offset;
}
for (int i = 0; i < textInfo.meshInfo.Length; i++)
{
var meshInfo = textInfo.meshInfo[i];
meshInfo.mesh.vertices = meshInfo.vertices;
m_TextComponent.UpdateGeometry(meshInfo.mesh, i);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e97c7089d02127542be97cbb2e963b85
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,96 @@
using asap.core;
using System;
using TMPro;
using UniRx;
using UnityEngine;
using UnityEngine.UI;
namespace GameCore
{
public enum TextType
{
Text, // UGUI Text
TextMeshPro, // TextMeshPro - Text
TextMeshPro_UGUI // TextMeshPro - Text(UI)
}
public class TextLocalization : MonoBehaviour
{
[SerializeField] private string localizationId;
[SerializeField] private TextType textType = TextType.TextMeshPro_UGUI;
private Text text;
private TextMeshProUGUI text_UGUI;
private TextMeshPro text_Pro;
private IDisposable disposable;
void Awake()
{
if (string.IsNullOrEmpty(localizationId))
{
return;
}
switch (textType)
{
case TextType.Text:
text = gameObject.GetComponent<Text>();
break;
case TextType.TextMeshPro_UGUI:
text_UGUI = gameObject.GetComponent<TextMeshProUGUI>();
break;
case TextType.TextMeshPro:
text_Pro = gameObject.GetComponent<TextMeshPro>();
break;
}
if (string.IsNullOrEmpty(localizationId))
{
return;
}
OnChangeLanguage();
disposable = GContext.OnEvent<ChangeLanguageEvent>().Subscribe(OnChangeLanguage);
}
void OnChangeLanguage(ChangeLanguageEvent changeLanguageEvent = null)
{
string localized_text = LocalizationMgr.GetText(localizationId);
if (!string.IsNullOrEmpty(localized_text))
{
switch (textType)
{
case TextType.Text:
if (text)
{
text.text = localized_text;
}
return;
case TextType.TextMeshPro_UGUI:
if (text_UGUI)
{
text_UGUI.text = localized_text;
}
return;
case TextType.TextMeshPro:
if (text_Pro)
{
text_Pro.text = localized_text;
}
return;
}
}
}
private void OnDestroy()
{
if (disposable != null)
{
disposable.Dispose();
disposable = null;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 67302bfe21c2841429242d7d1edc8f16
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,79 @@
using System;
using UniRx;
using UniRx.Triggers;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class UIButton : Button
{
[SerializeField]private float _holdThresh = 0.5f;
private ButtonClickedEvent m_OnDown = new ButtonClickedEvent();
private ButtonClickedEvent m_OnUp = new ButtonClickedEvent();
private ButtonClickedEvent m_OnLongPress = new ButtonClickedEvent();
private ButtonClickedEvent m_OnShortClick = new ButtonClickedEvent();
private IDisposable clickStream, longPressStream;
private DateTimeOffset _lastDownTime, _lastUpTime;
//private CompositeDisposable _pressTimer;
//private float ci;
PointerEventData pointerEventData;
protected override void Start()
{
var pointerDownStream = this.OnPointerDownAsObservable().Timestamp();
var pointerUpStream = this.OnPointerUpAsObservable().Timestamp();
//Logic of long press: delayed.Timestamp - delayThreshold - lastButtonUpTime > 0
longPressStream = pointerDownStream
.SelectMany(_ => Observable.Timer(TimeSpan.FromSeconds(_holdThresh)))
.Timestamp()
.Where(_ => (_.Timestamp - _lastUpTime ).TotalSeconds > _holdThresh)
.Subscribe(_ => m_OnLongPress.Invoke())
.AddTo(this);
clickStream = pointerUpStream
.CombineLatest(pointerDownStream, (eUp, eDown) => eUp.Timestamp - eDown.Timestamp)
.Where(interval => interval.TotalSeconds > 0 && interval.TotalSeconds <= _holdThresh)
.Subscribe(_ => m_OnShortClick.Invoke())
.AddTo(this);
}
public ButtonClickedEvent onDown
{
get { return m_OnDown; }
set { m_OnDown = value; }
}
public ButtonClickedEvent onUp
{
get { return m_OnUp; }
set { m_OnUp = value; }
}
public ButtonClickedEvent onLongPress
{
get { return m_OnLongPress; }
set { m_OnLongPress = value; }
}
public new ButtonClickedEvent onClick
{
get { return m_OnShortClick; }
set { m_OnShortClick = value; }
}
public override void OnPointerDown(PointerEventData eventData)
{
base.OnPointerDown(eventData);
m_OnDown.Invoke();
pointerEventData = eventData;
_lastDownTime = DateTimeOffset.Now;
}
public override void OnPointerUp(PointerEventData eventData)
{
base.OnPointerUp(eventData);
m_OnUp.Invoke();
_lastUpTime = DateTimeOffset.Now;
}
public void Up()
{
OnPointerUp(pointerEventData);
}
public bool IsDowning => IsPressed();
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0bf32009b1c846b8b2750cdfb3419975
timeCreated: 1694487538

View File

@@ -0,0 +1,84 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using static UnityEngine.EventSystems.ExecuteEvents;
public class UIButtonDouble : Button
{
public int ExecuteCount = 1;
public int curExecuteCount = 0;
private ButtonClickedEvent m_OnDown = new ButtonClickedEvent();
private ButtonClickedEvent m_OnUp = new ButtonClickedEvent();
PointerEventData _pointerEventData;
public PointerEventData PointerEventData => _pointerEventData;
public ButtonClickedEvent onDown
{
get { return m_OnDown; }
set { m_OnDown = value; }
}
public ButtonClickedEvent onUp
{
get { return m_OnUp; }
set { m_OnUp = value; }
}
public override void OnPointerClick(PointerEventData eventData)
{
RaycastThrough(eventData, pointerClickHandler);
base.OnPointerClick(eventData);
}
public override void OnPointerDown(PointerEventData eventData)
{
RaycastThrough(eventData, pointerDownHandler);
m_OnDown.Invoke();
base.OnPointerDown(eventData);
}
public override void OnPointerUp(PointerEventData eventData)
{
RaycastThrough(eventData, pointerUpHandler);
m_OnUp.Invoke();
base.OnPointerUp(eventData);
}
public void RaycastThrough<T>(BaseEventData baseEventData, EventFunction<T> eventFunction) where T : IEventSystemHandler
{
_pointerEventData = (PointerEventData)baseEventData;
List<RaycastResult> raycastResults = new List<RaycastResult>();
//当前处理的gameobject
GameObject currentObj = gameObject ?? _pointerEventData.pointerDrag;
//获取当前射线检测到的所有结果
EventSystem.current.RaycastAll(_pointerEventData, raycastResults);
curExecuteCount = 0;
bool isExecute = false;
for (int i = 0; i < raycastResults.Count; i++)
{
//}
//foreach (var item in raycastResults)
//{
var item = raycastResults[i];
GameObject nextObj = item.gameObject;
if (nextObj != null && nextObj == currentObj)
{
isExecute = true;
}
if (isExecute && nextObj != null && nextObj != currentObj)
{
GameObject excuteObj = GetEventHandler<T>(nextObj);
if (excuteObj != null && excuteObj != currentObj)
{
//执行下一层事件,如果你还需要继续执行下面层UI事件可以不return我这里只检测下一层的所以我循环一次就直接return
Execute(excuteObj, _pointerEventData, eventFunction);
}
curExecuteCount++;
if (curExecuteCount >= ExecuteCount)
{
return;
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e0b36a0614d5b804abb38c6bbfcb3ef9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,80 @@
using UnityEngine;
using UnityEngine.EventSystems;
public class UIDrag : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler, IPointerDownHandler, IPointerUpHandler
{
//按下回调
public System.Action OnPointerDownCall;
public System.Action OnPointerUpCall;
//开始拖动回调
public System.Action OnBeginDragCall;
//拖动中回调
public System.Action<PointerEventData> OnDragCall;
//拖动结束回调
public System.Action OnEndDragCall;
bool isdrag = false;
public bool isTouchTwo = false;
public void OnPointerDown(PointerEventData eventData)
{
OnPointerDownCall?.Invoke();
}
public void OnPointerUp(PointerEventData eventData)
{
OnPointerUpCall?.Invoke();
}
public void OnBeginDrag(PointerEventData eventData)
{
#if UNITY_EDITOR
if (Input.GetMouseButton(0))
#else
if (Input.touchCount == 1 || Input.touchCount == 2)
#endif
{
OnBeginDragCall?.Invoke();
isdrag = true;
}
}
public void OnDrag(PointerEventData eventData)
{
OnDragCall?.Invoke(eventData);
if (isTouchTwo)
{
#if !UNITY_EDITOR
//if (Input.touchCount == 1)
//{
// if (!isdrag)
// {
// OnBeginDragCall?.Invoke();
// isdrag = true;
// }
//}
//else
if (Input.touchCount == 2)
{
//双指操作
if (isdrag)
{
OnEndDragCall?.Invoke();
isdrag = false;
}
}
#endif
}
}
public void OnEndDrag(PointerEventData eventData)
{
if (isdrag)
{
OnEndDragCall?.Invoke();
isdrag = false;
}
}
//双指操作
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 909da6861b624f80826aa23bef9ad875
timeCreated: 1694420922