Add project files.
This commit is contained in:
104
Assets/Cryville/Common/Unity/UI/AspectRatioLayoutElement.cs
Normal file
104
Assets/Cryville/Common/Unity/UI/AspectRatioLayoutElement.cs
Normal file
@@ -0,0 +1,104 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Cryville.Common.Unity.UI {
|
||||
public class AspectRatioLayoutElement : UIBehaviour, ILayoutElement {
|
||||
[SerializeField]
|
||||
private RectTransform m_containerTransform = null;
|
||||
public RectTransform ContainerTransform {
|
||||
get { return m_containerTransform; }
|
||||
set { SetProperty(ref m_containerTransform, value); }
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private float m_aspectRatio = 1;
|
||||
public float AspectRatio {
|
||||
get { return m_aspectRatio; }
|
||||
set { SetProperty(ref m_aspectRatio, value); }
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private bool m_isVertical = false;
|
||||
public bool IsVertical {
|
||||
get { return m_isVertical; }
|
||||
set { SetProperty(ref m_isVertical, value); }
|
||||
}
|
||||
|
||||
private void SetProperty<T>(ref T prop, T value) {
|
||||
if (Equals(prop, value)) return;
|
||||
prop = value;
|
||||
SetDirty();
|
||||
}
|
||||
|
||||
private void SetDirty() {
|
||||
if (!IsActive()) return;
|
||||
LayoutRebuilder.MarkLayoutForRebuild(transform as RectTransform);
|
||||
}
|
||||
|
||||
public float minWidth {
|
||||
get {
|
||||
return m_isVertical
|
||||
? m_containerTransform.rect.width
|
||||
: m_containerTransform.rect.height * m_aspectRatio;
|
||||
}
|
||||
}
|
||||
public float preferredWidth { get { return minWidth; } }
|
||||
public float flexibleWidth { get { return 0; } }
|
||||
|
||||
public float minHeight {
|
||||
get {
|
||||
return m_isVertical
|
||||
? m_containerTransform.rect.width / m_aspectRatio
|
||||
: m_containerTransform.rect.height;
|
||||
}
|
||||
}
|
||||
public float preferredHeight { get { return minHeight; } }
|
||||
public float flexibleHeight { get { return 0; } }
|
||||
|
||||
public int layoutPriority { get { return 1; } }
|
||||
|
||||
private bool isRootLayoutGroup {
|
||||
get {
|
||||
Transform parent = transform.parent;
|
||||
return parent == null || transform.parent.GetComponent(typeof(ILayoutGroup)) == null;
|
||||
}
|
||||
}
|
||||
|
||||
public void CalculateLayoutInputHorizontal() { }
|
||||
|
||||
public void CalculateLayoutInputVertical() { }
|
||||
|
||||
protected override void OnDidApplyAnimationProperties() {
|
||||
base.OnDidApplyAnimationProperties();
|
||||
SetDirty();
|
||||
}
|
||||
|
||||
protected override void OnDisable() {
|
||||
LayoutRebuilder.MarkLayoutForRebuild(transform as RectTransform);
|
||||
base.OnDisable();
|
||||
}
|
||||
|
||||
protected override void OnEnable() {
|
||||
base.OnEnable();
|
||||
SetDirty();
|
||||
}
|
||||
|
||||
protected override void OnRectTransformDimensionsChange() {
|
||||
base.OnRectTransformDimensionsChange();
|
||||
SetDirty();
|
||||
}
|
||||
|
||||
protected override void OnTransformParentChanged() {
|
||||
base.OnTransformParentChanged();
|
||||
SetDirty();
|
||||
}
|
||||
|
||||
#pragma warning disable IDE0051
|
||||
new void OnValidate() {
|
||||
SetDirty();
|
||||
}
|
||||
#pragma warning restore IDE0051
|
||||
}
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4152cfa558755cd44bf81d408a0fdeb6
|
||||
timeCreated: 1638428042
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,16 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Cryville.Common.Unity.UI {
|
||||
public sealed class DockAspectRatioLayoutGroup : DockLayoutGroup {
|
||||
[SerializeField]
|
||||
private float m_dockAspectRatio = 1;
|
||||
public float DockAspectRatio {
|
||||
get { return m_dockAspectRatio; }
|
||||
set { base.SetProperty(ref m_dockAspectRatio, value); }
|
||||
}
|
||||
|
||||
protected override float GetDockElementSize(Vector2 groupSize) {
|
||||
return groupSize.y * m_dockAspectRatio;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f56dd50c0bf4a1341bcaa95451a735c8
|
||||
timeCreated: 1637546486
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
74
Assets/Cryville/Common/Unity/UI/DockLayoutGroup.cs
Normal file
74
Assets/Cryville/Common/Unity/UI/DockLayoutGroup.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Cryville.Common.Unity.UI {
|
||||
public abstract class DockLayoutGroup : LayoutGroup {
|
||||
public enum Side {
|
||||
Top = 0,
|
||||
Right = 1,
|
||||
Bottom = 2,
|
||||
Left = 3,
|
||||
}
|
||||
[SerializeField]
|
||||
private Side m_side;
|
||||
public Side DockSide {
|
||||
get { return m_side; }
|
||||
set { base.SetProperty(ref m_side, value); }
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private float m_slideIndex;
|
||||
public float SlideIndex {
|
||||
get { return m_slideIndex; }
|
||||
set { base.SetProperty(ref m_slideIndex, value); }
|
||||
}
|
||||
|
||||
public sealed override void CalculateLayoutInputHorizontal() { base.CalculateLayoutInputHorizontal(); }
|
||||
public sealed override void CalculateLayoutInputVertical() { }
|
||||
public sealed override void SetLayoutHorizontal() { SetChildrenAlongAxis(0); }
|
||||
public sealed override void SetLayoutVertical() { SetChildrenAlongAxis(1); }
|
||||
|
||||
private float GetSlidePosition(float groupHeight, float dockHeight) {
|
||||
bool d = Mathf.FloorToInt(m_slideIndex - Mathf.Floor(m_slideIndex / 2) * 2) == 0;
|
||||
int l = Mathf.FloorToInt(m_slideIndex / 2);
|
||||
float p = m_slideIndex - Mathf.Floor(m_slideIndex);
|
||||
if (d) return l * groupHeight + p * dockHeight;
|
||||
else return l * groupHeight + dockHeight + p * (groupHeight - dockHeight);
|
||||
}
|
||||
|
||||
private void SetChildrenAlongAxis(int axis) {
|
||||
int isHorizontal = (int)m_side & 1;
|
||||
bool isReversed = m_side == Side.Right || m_side == Side.Bottom;
|
||||
var rect = rectTransform.rect;
|
||||
if ((isHorizontal ^ axis) == 1) {
|
||||
float p0 = isHorizontal == 1 ? m_Padding.left : m_Padding.top;
|
||||
float p1 = isHorizontal == 1 ? m_Padding.right : m_Padding.bottom;
|
||||
var gs = rect.size - new Vector2(m_Padding.horizontal, m_Padding.vertical);
|
||||
if (isHorizontal == 0) gs = new Vector2(gs.y, gs.x);
|
||||
float s1 = GetDockElementSize(gs);
|
||||
float s0 = GetSlidePosition(gs.x, s1);
|
||||
float a1 = (isHorizontal == 0 ? rect.height : rect.width) - p0 - p1;
|
||||
for (int i = 0; i < base.rectChildren.Count; i++) {
|
||||
var c = base.rectChildren[i];
|
||||
bool d = i % 2 == 0;
|
||||
int l = i / 2;
|
||||
if (isReversed)
|
||||
base.SetChildAlongAxis(c, axis, (d ? a1 - s1 + p0 : p0) - a1 * l + s0, d ? s1 : a1 - s1);
|
||||
else
|
||||
base.SetChildAlongAxis(c, axis, (d ? p0 : s1 + p0) - s0 + a1 * l, d ? s1 : a1 - s1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
float p0 = isHorizontal == 0 ? m_Padding.left : m_Padding.top;
|
||||
float p1 = isHorizontal == 0 ? m_Padding.right : m_Padding.bottom;
|
||||
var height = (isHorizontal == 1 ? rect.height : rect.width) - p0 - p1;
|
||||
for (int i = 0; i < base.rectChildren.Count; i++) {
|
||||
base.SetChildAlongAxis(base.rectChildren[i], axis, p0, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract float GetDockElementSize(Vector2 groupSize);
|
||||
}
|
||||
}
|
12
Assets/Cryville/Common/Unity/UI/DockLayoutGroup.cs.meta
Normal file
12
Assets/Cryville/Common/Unity/UI/DockLayoutGroup.cs.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 452470fc804a21741b5b4b0b64f14d0b
|
||||
timeCreated: 1637543050
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,16 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Cryville.Common.Unity.UI {
|
||||
public sealed class DockOccupiedRatioLayoutGroup : DockLayoutGroup {
|
||||
[SerializeField]
|
||||
private float m_dockOccupiedRatio = 1;
|
||||
public float DockOccupiedRatio {
|
||||
get { return m_dockOccupiedRatio; }
|
||||
set { base.SetProperty(ref m_dockOccupiedRatio, value); }
|
||||
}
|
||||
|
||||
protected override float GetDockElementSize(Vector2 groupSize) {
|
||||
return groupSize.x * m_dockOccupiedRatio;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a9139d5b66d1eb140856a276012df0b8
|
||||
timeCreated: 1637546712
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
36
Assets/Cryville/Common/Unity/UI/GridLayoutSizeFitter.cs
Normal file
36
Assets/Cryville/Common/Unity/UI/GridLayoutSizeFitter.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Cryville.Common.Unity.UI {
|
||||
[RequireComponent(typeof(GridLayoutGroup))]
|
||||
public class GridLayoutSizeFitter : MonoBehaviour {
|
||||
RectTransform rectTransform;
|
||||
GridLayoutGroup gridLayoutGroup;
|
||||
Canvas canvas;
|
||||
public int GroupItemCount = 3;
|
||||
|
||||
#pragma warning disable IDE0051
|
||||
void Awake() {
|
||||
rectTransform = GetComponent<RectTransform>();
|
||||
gridLayoutGroup = GetComponent<GridLayoutGroup>();
|
||||
canvas = GetComponentInParent<Canvas>();
|
||||
}
|
||||
void Update() {
|
||||
var cellSize = gridLayoutGroup.cellSize;
|
||||
var frameSize = rectTransform.sizeDelta;
|
||||
int lineCount = Mathf.CeilToInt((float)transform.childCount / GroupItemCount);
|
||||
var rect = RectTransformUtility.PixelAdjustRect((RectTransform)transform, canvas);
|
||||
if (gridLayoutGroup.startAxis == GridLayoutGroup.Axis.Horizontal) {
|
||||
cellSize.x = rect.width / GroupItemCount;
|
||||
frameSize.y = cellSize.y * lineCount;
|
||||
}
|
||||
else {
|
||||
cellSize.y = rect.height / GroupItemCount;
|
||||
frameSize.x = cellSize.x * lineCount;
|
||||
}
|
||||
gridLayoutGroup.cellSize = cellSize;
|
||||
rectTransform.sizeDelta = frameSize;
|
||||
}
|
||||
#pragma warning restore IDE0051
|
||||
}
|
||||
}
|
12
Assets/Cryville/Common/Unity/UI/GridLayoutSizeFitter.cs.meta
Normal file
12
Assets/Cryville/Common/Unity/UI/GridLayoutSizeFitter.cs.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 45ec4804e78a14a489a6fae9197e9b57
|
||||
timeCreated: 1637231253
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
160
Assets/Cryville/Common/Unity/UI/ImageSliced3.cs
Normal file
160
Assets/Cryville/Common/Unity/UI/ImageSliced3.cs
Normal file
@@ -0,0 +1,160 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Sprites;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Cryville.Common.Unity.UI {
|
||||
/// <summary>
|
||||
/// An image that is sliced into three parts, with the middle part stretched and the two borders preserved their aspect ratio.
|
||||
/// </summary>
|
||||
[ExecuteInEditMode]
|
||||
public class ImageSliced3 : MaskableGraphic {
|
||||
[SerializeField]
|
||||
private Sprite m_sprite;
|
||||
/// <summary>
|
||||
/// The sliced sprite.
|
||||
/// </summary>
|
||||
public Sprite Sprite {
|
||||
get { return m_sprite; }
|
||||
set { m_sprite = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The mode how a sliced image is generated when it is too compact.
|
||||
/// </summary>
|
||||
public enum CompactMode {
|
||||
/// <summary>
|
||||
/// Squeezes both the left border and the right border.
|
||||
/// </summary>
|
||||
SqueezeBoth = 0,
|
||||
/// <summary>
|
||||
/// Squeezes the left border and preserves the width of the right border.
|
||||
/// </summary>
|
||||
SqueezeLeft = 2,
|
||||
/// <summary>
|
||||
/// Squeezes the right border and preserves the width of the left border.
|
||||
/// </summary>
|
||||
SqueezeRight = 3,
|
||||
/// <summary>
|
||||
/// Squeezes the lower edge of the left border and the upper edge of the right border.
|
||||
/// </summary>
|
||||
DiagonalLeft = 4,
|
||||
/// <summary>
|
||||
/// Squeezes the upper edge of the left border and the lower edge of the right border.
|
||||
/// </summary>
|
||||
DiagonalRight = 5,
|
||||
}
|
||||
[SerializeField]
|
||||
private CompactMode m_compact;
|
||||
/// <summary>
|
||||
/// The mode how a sliced image is generated when it is too compact.
|
||||
/// </summary>
|
||||
public CompactMode Compact {
|
||||
get { return m_compact; }
|
||||
set { m_compact = value; }
|
||||
}
|
||||
|
||||
public override Texture mainTexture {
|
||||
get { return Sprite == null ? s_WhiteTexture : Sprite.texture; }
|
||||
}
|
||||
|
||||
protected override void OnPopulateMesh(VertexHelper vh) {
|
||||
float actualWidth = rectTransform.rect.width;
|
||||
|
||||
Vector4 uv = DataUtility.GetOuterUV(Sprite);
|
||||
|
||||
float cornerLeftSizeRatio = Sprite.border.x / Sprite.rect.height;
|
||||
float actualLeftCornerWidth = cornerLeftSizeRatio * rectTransform.rect.height;
|
||||
float actualLeftUVWidth = (uv.w - uv.y) * (Sprite.border.x / Sprite.rect.width);
|
||||
|
||||
float cornerRightSizeRatio = Sprite.border.z / Sprite.rect.height;
|
||||
float actualRightCornerWidth = cornerRightSizeRatio * rectTransform.rect.height;
|
||||
float actualRightUVWidth = (uv.w - uv.y) * (Sprite.border.z / Sprite.rect.width);
|
||||
|
||||
float actualTotalCornerWidth = actualLeftCornerWidth + actualRightCornerWidth;
|
||||
|
||||
Vector2 corner1 = new Vector2(0f, 0f);
|
||||
Vector2 corner2 = new Vector2(1f, 1f);
|
||||
|
||||
corner1.x -= rectTransform.pivot.x;
|
||||
corner1.y -= rectTransform.pivot.y;
|
||||
corner2.x -= rectTransform.pivot.x;
|
||||
corner2.y -= rectTransform.pivot.y;
|
||||
|
||||
corner1.x *= actualWidth;
|
||||
corner1.y *= rectTransform.rect.height;
|
||||
corner2.x *= actualWidth;
|
||||
corner2.y *= rectTransform.rect.height;
|
||||
|
||||
if (Sprite == null) {
|
||||
throw new UnityException("No sprite");
|
||||
}
|
||||
else if (Sprite.border == Vector4.zero) {
|
||||
throw new UnityException("No sprite border");
|
||||
}
|
||||
|
||||
float w3, w4, w5, w6;
|
||||
if (actualTotalCornerWidth > actualWidth) {
|
||||
switch (Compact) {
|
||||
case CompactMode.SqueezeBoth:
|
||||
w3 = w4 = actualLeftCornerWidth / actualTotalCornerWidth * actualWidth;
|
||||
w5 = w6 = actualRightCornerWidth / actualTotalCornerWidth * actualWidth;
|
||||
break;
|
||||
case CompactMode.SqueezeLeft:
|
||||
w3 = w4 = actualWidth - actualRightCornerWidth;
|
||||
w5 = w6 = actualRightCornerWidth;
|
||||
break;
|
||||
case CompactMode.SqueezeRight:
|
||||
w3 = w4 = actualLeftCornerWidth;
|
||||
w5 = w6 = actualWidth - actualLeftCornerWidth;
|
||||
break;
|
||||
case CompactMode.DiagonalLeft:
|
||||
w3 = actualLeftCornerWidth;
|
||||
w4 = actualWidth - actualRightCornerWidth;
|
||||
w5 = actualWidth - actualLeftCornerWidth;
|
||||
w6 = actualRightCornerWidth;
|
||||
break;
|
||||
case CompactMode.DiagonalRight:
|
||||
w3 = actualWidth - actualRightCornerWidth;
|
||||
w4 = actualLeftCornerWidth;
|
||||
w5 = actualRightCornerWidth;
|
||||
w6 = actualWidth - actualLeftCornerWidth;
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("Compact");
|
||||
}
|
||||
}
|
||||
else {
|
||||
w3 = w4 = actualLeftCornerWidth;
|
||||
w5 = w6 = actualRightCornerWidth;
|
||||
}
|
||||
|
||||
vh.Clear();
|
||||
vh.AddVert(new Vector3(corner1.x, corner2.y), color, new Vector2(uv.x, uv.w));
|
||||
vh.AddVert(new Vector3(corner1.x, corner1.y), color, new Vector2(uv.x, uv.y));
|
||||
vh.AddVert(new Vector3(corner1.x + w3, corner2.y), color, new Vector2(uv.x + actualLeftUVWidth, uv.w));
|
||||
vh.AddVert(new Vector3(corner1.x + w4, corner1.y), color, new Vector2(uv.x + actualLeftUVWidth, uv.y));
|
||||
vh.AddVert(new Vector3(corner2.x - w5, corner2.y), color, new Vector2(uv.z - actualRightUVWidth, uv.w));
|
||||
vh.AddVert(new Vector3(corner2.x - w6, corner1.y), color, new Vector2(uv.z - actualRightUVWidth, uv.y));
|
||||
vh.AddVert(new Vector3(corner2.x, corner2.y), color, new Vector2(uv.z, uv.w));
|
||||
vh.AddVert(new Vector3(corner2.x, corner1.y), color, new Vector2(uv.z, uv.y));
|
||||
|
||||
if (((int)Compact & 0x1) == 0) {
|
||||
vh.AddTriangle(2, 1, 0);
|
||||
vh.AddTriangle(1, 2, 3);
|
||||
vh.AddTriangle(4, 3, 2);
|
||||
vh.AddTriangle(3, 4, 5);
|
||||
vh.AddTriangle(6, 5, 4);
|
||||
vh.AddTriangle(5, 6, 7);
|
||||
}
|
||||
else {
|
||||
vh.AddTriangle(3, 1, 0);
|
||||
vh.AddTriangle(0, 2, 3);
|
||||
vh.AddTriangle(5, 3, 2);
|
||||
vh.AddTriangle(2, 4, 5);
|
||||
vh.AddTriangle(7, 5, 4);
|
||||
vh.AddTriangle(4, 6, 7);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/Cryville/Common/Unity/UI/ImageSliced3.cs.meta
Normal file
11
Assets/Cryville/Common/Unity/UI/ImageSliced3.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7a17c6b12c477af44bbfd74a46ed0c72
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
42
Assets/Cryville/Common/Unity/UI/LayoutAspectRatioFitter.cs
Normal file
42
Assets/Cryville/Common/Unity/UI/LayoutAspectRatioFitter.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Cryville.Common.Unity.UI {
|
||||
public class LayoutAspectRatioFitter : MonoBehaviour {
|
||||
[SerializeField]
|
||||
private float m_aspectRatioPerElement = 1;
|
||||
public float AspectRatioPerElement {
|
||||
get { return m_aspectRatioPerElement; }
|
||||
set { m_aspectRatioPerElement = value; }
|
||||
}
|
||||
|
||||
AspectRatioFitter aspectRatioFitter;
|
||||
DockAspectRatioLayoutGroup syncTo;
|
||||
int axis;
|
||||
#pragma warning disable IDE0051
|
||||
void Awake() {
|
||||
aspectRatioFitter = GetComponent<AspectRatioFitter>();
|
||||
if (aspectRatioFitter == null) {
|
||||
syncTo = GetComponentInParent<DockAspectRatioLayoutGroup>();
|
||||
axis = (syncTo.DockSide == DockLayoutGroup.Side.Top || syncTo.DockSide == DockLayoutGroup.Side.Bottom) ? 1 : 0;
|
||||
}
|
||||
else axis = aspectRatioFitter.aspectMode == AspectRatioFitter.AspectMode.WidthControlsHeight ? 1 : 0;
|
||||
OnTransformChildrenChanged();
|
||||
}
|
||||
void OnTransformChildrenChanged() {
|
||||
float r;
|
||||
switch (axis) {
|
||||
case 0:
|
||||
r = AspectRatioPerElement * transform.childCount;
|
||||
break;
|
||||
case 1:
|
||||
r = AspectRatioPerElement / transform.childCount;
|
||||
break;
|
||||
default: return;
|
||||
}
|
||||
if (aspectRatioFitter != null) aspectRatioFitter.aspectRatio = r;
|
||||
else syncTo.DockAspectRatio = r;
|
||||
}
|
||||
#pragma warning restore IDE0051
|
||||
}
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c6a0bd7b6df9009488cf6694cb73422c
|
||||
timeCreated: 1637570493
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
27
Assets/Cryville/Common/Unity/UI/ProgressBar.cs
Normal file
27
Assets/Cryville/Common/Unity/UI/ProgressBar.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Cryville.Common.Unity.UI {
|
||||
public class ProgressBar : Slider {
|
||||
[SerializeField][Range(0f, 1f)]
|
||||
float m_smooth = 0;
|
||||
public float Smooth {
|
||||
get { return m_smooth; }
|
||||
set { m_smooth = value; }
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
float m_targetValue;
|
||||
public override float value {
|
||||
get { return base.value; }
|
||||
set { m_targetValue = value; }
|
||||
}
|
||||
|
||||
#pragma warning disable IDE0051
|
||||
protected override void Update() {
|
||||
base.value = (base.value - m_targetValue) * m_smooth + m_targetValue;
|
||||
base.Update();
|
||||
}
|
||||
#pragma warning restore IDE0051
|
||||
}
|
||||
}
|
11
Assets/Cryville/Common/Unity/UI/ProgressBar.cs.meta
Normal file
11
Assets/Cryville/Common/Unity/UI/ProgressBar.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b1a44bd454a0aa64e835b9e309c79bff
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
209
Assets/Cryville/Common/Unity/UI/ScrollableItemGrid.cs
Normal file
209
Assets/Cryville/Common/Unity/UI/ScrollableItemGrid.cs
Normal file
@@ -0,0 +1,209 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Cryville.Common.Unity.UI {
|
||||
public sealed class ScrollableItemGrid : MonoBehaviour {
|
||||
[SerializeField]
|
||||
private GameObject m_itemTemplate;
|
||||
public GameObject ItemTemplate {
|
||||
get { return m_itemTemplate; }
|
||||
set { m_itemTemplate = value; OnTemplateUpdate(); }
|
||||
}
|
||||
public Func<int, GameObject, bool> LoadItem { private get; set; }
|
||||
|
||||
public enum Corner {
|
||||
UpperLeft = 0,
|
||||
UpperRight = 1,
|
||||
LowerLeft = 2,
|
||||
LowerRight = 3,
|
||||
}
|
||||
[SerializeField]
|
||||
private Corner m_startCorner; // TODO
|
||||
public Corner StartCorner {
|
||||
get { return m_startCorner; }
|
||||
set { m_startCorner = value; OnFrameUpdate(); }
|
||||
}
|
||||
|
||||
public enum Axis {
|
||||
Horizontal = 0, Vertical = 1,
|
||||
}
|
||||
[SerializeField]
|
||||
private Axis m_startAxis;
|
||||
public Axis StartAxis {
|
||||
get { return m_startAxis; }
|
||||
set { m_startAxis = value; OnFrameUpdate(); }
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private Vector2 m_spacing; // TODO
|
||||
public Vector2 Spacing {
|
||||
get { return m_spacing; }
|
||||
set { m_spacing = value; OnFrameUpdate(); }
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private int m_itemCount = 3;
|
||||
public int ItemCount {
|
||||
get { return m_itemCount; }
|
||||
set { m_itemCount = value; OnRefresh(); }
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private int m_lineItemCount = 3;
|
||||
public int LineItemCount {
|
||||
get { return m_lineItemCount; }
|
||||
set { m_lineItemCount = value; OnFrameUpdate(); }
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private float m_lineHeight = 100;
|
||||
public float LineHeight {
|
||||
get { return m_lineHeight; }
|
||||
set { m_lineHeight = value; OnFrameUpdate(); }
|
||||
}
|
||||
|
||||
private int LineCount {
|
||||
get { return Mathf.CeilToInt((float)m_itemCount / m_lineItemCount); }
|
||||
}
|
||||
private float GroupHeight {
|
||||
get { return m_lineHeight * LineCount; }
|
||||
}
|
||||
private Vector2 VisibleSize {
|
||||
get {
|
||||
Rect parentRect = ((RectTransform)transform.parent).rect;
|
||||
return new Vector2(
|
||||
m_startAxis == Axis.Horizontal ? parentRect.width : parentRect.height,
|
||||
m_startAxis == Axis.Horizontal ? parentRect.height : parentRect.width
|
||||
);
|
||||
}
|
||||
}
|
||||
public int VisibleLines {
|
||||
get {
|
||||
return Mathf.CeilToInt(VisibleSize.y / m_lineHeight) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
private bool initialized;
|
||||
private GameObject[][] lines;
|
||||
private int[] refl;
|
||||
Vector2 cpos = new Vector2(0, 1);
|
||||
Vector2 pprectsize;
|
||||
|
||||
#pragma warning disable IDE0051
|
||||
void Start() {
|
||||
GetComponentInParent<ScrollRect>().onValueChanged.AddListener(OnScroll);
|
||||
initialized = true;
|
||||
OnFrameUpdate();
|
||||
}
|
||||
|
||||
void Update() {
|
||||
Vector2 cprectsize = ((RectTransform)transform.parent).rect.size;
|
||||
if (cprectsize != pprectsize) {
|
||||
OnFrameUpdate();
|
||||
pprectsize = cprectsize;
|
||||
}
|
||||
}
|
||||
#pragma warning restore IDE0051
|
||||
|
||||
private void OnFrameUpdate() {
|
||||
if (!initialized) return;
|
||||
if (lines != null) for (int i = 0; i < lines.Length; i++)
|
||||
if (lines[i] != null) foreach (GameObject c in lines[i])
|
||||
GameObject.Destroy(c);
|
||||
lines = new GameObject[VisibleLines][];
|
||||
refl = new int[VisibleLines];
|
||||
for (int i = 0; i < refl.Length; i++) refl[i] = i;
|
||||
ResetLines();
|
||||
SetCells();
|
||||
ResizeGroup();
|
||||
}
|
||||
|
||||
private void OnTemplateUpdate() {
|
||||
if (!initialized) return;
|
||||
ResetLines();
|
||||
SetCells();
|
||||
}
|
||||
|
||||
private void ResetLines() {
|
||||
for (int i = 0; i < lines.Length; i++) {
|
||||
if (lines[i] != null) foreach (GameObject c in lines[i])
|
||||
GameObject.Destroy(c);
|
||||
lines[i] = new GameObject[LineItemCount];
|
||||
GenerateLine(i, refl[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void OnScroll(Vector2 scrpos) {
|
||||
cpos = scrpos;
|
||||
int l0 = GetFirstVisibleLine(cpos);
|
||||
int l1 = l0 + VisibleLines - 1;
|
||||
for (int l = l0; l <= l1; l++) {
|
||||
if (Array.IndexOf(refl, l) != -1) continue;
|
||||
int repl = Array.FindIndex(refl, i => i < l0 || i > l1);
|
||||
if (repl == -1) return;
|
||||
LoadLine(repl, l);
|
||||
SetCells(repl);
|
||||
}
|
||||
}
|
||||
|
||||
void OnRefresh() {
|
||||
if (!initialized) return;
|
||||
int l0 = GetFirstVisibleLine(cpos);
|
||||
int l1 = l0 + VisibleLines - 1;
|
||||
int i = 0;
|
||||
for (int l = l0; l <= l1; i++, l++) {
|
||||
LoadLine(i, l);
|
||||
SetCells(i);
|
||||
}
|
||||
ResizeGroup();
|
||||
}
|
||||
|
||||
void ResizeGroup() {
|
||||
((RectTransform)transform).sizeDelta = m_startAxis == 0
|
||||
? new Vector2(0, GroupHeight)
|
||||
: new Vector2(GroupHeight, 0);
|
||||
}
|
||||
|
||||
int GetFirstVisibleLine(Vector2 scrpos) {
|
||||
float scr = m_startAxis == Axis.Horizontal ? 1 - scrpos.y : scrpos.x;
|
||||
float maxScroll = Mathf.Max(0, GroupHeight - VisibleSize.y);
|
||||
if (maxScroll == 0) return 0;
|
||||
return Mathf.FloorToInt(scr * maxScroll / LineHeight);
|
||||
}
|
||||
|
||||
void GenerateLine(int index, int line) {
|
||||
for (int j = 0; j < LineItemCount; j++) {
|
||||
var child = GameObject.Instantiate(m_itemTemplate);
|
||||
child.transform.SetParent(transform, false);
|
||||
lines[index][j] = child;
|
||||
}
|
||||
LoadLine(index, line);
|
||||
}
|
||||
|
||||
void LoadLine(int index, int line) {
|
||||
refl[index] = line;
|
||||
for (int j = 0; j < LineItemCount; j++) {
|
||||
var id = line * m_lineItemCount + j;
|
||||
if (id < 0 || id >= m_itemCount || LoadItem == null) lines[index][j].SetActive(false);
|
||||
else lines[index][j].SetActive(LoadItem(id, lines[index][j]));
|
||||
}
|
||||
}
|
||||
|
||||
private void SetCells() {
|
||||
for (int i = 0; i < VisibleLines; i++) SetCells(i);
|
||||
}
|
||||
|
||||
private void SetCells(int index) {
|
||||
float itemWidth = VisibleSize[0] / m_lineItemCount;
|
||||
for (int j = 0; j < LineItemCount; j++) {
|
||||
((RectTransform)lines[index][j].transform).anchoredPosition = m_startAxis == 0
|
||||
? new Vector2(j * itemWidth, -refl[index] * m_lineHeight)
|
||||
: new Vector2(refl[index] * m_lineHeight, -j * itemWidth);
|
||||
((RectTransform)lines[index][j].transform).sizeDelta = m_startAxis == 0
|
||||
? new Vector2(itemWidth, m_lineHeight)
|
||||
: new Vector2(m_lineHeight, itemWidth);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
12
Assets/Cryville/Common/Unity/UI/ScrollableItemGrid.cs.meta
Normal file
12
Assets/Cryville/Common/Unity/UI/ScrollableItemGrid.cs.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4e3bba63289205243bdddd79b4341bc4
|
||||
timeCreated: 1637504893
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user