修复气泡布局存在的一些问题
This commit is contained in:
@@ -0,0 +1,182 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace XericUIEditor.BubbleLayout
|
||||
{
|
||||
/// <summary>
|
||||
/// BubbleLayout Editor 共享样式,提供白色圆角边框 + 深色底的 GUIStyle。
|
||||
/// </summary>
|
||||
internal static class BubbleLayoutEditorStyles
|
||||
{
|
||||
private static GUIStyle s_BoxStyle;
|
||||
private static bool s_Initialized;
|
||||
|
||||
/// <summary>白色圆角边框 + 深灰黑色底的 Box 样式</summary>
|
||||
public static GUIStyle BoxStyle
|
||||
{
|
||||
get
|
||||
{
|
||||
EnsureInitialized();
|
||||
return s_BoxStyle;
|
||||
}
|
||||
}
|
||||
|
||||
private static void EnsureInitialized()
|
||||
{
|
||||
if (s_Initialized)
|
||||
return;
|
||||
|
||||
s_BoxStyle = new GUIStyle(GUI.skin.box)
|
||||
{
|
||||
padding = new RectOffset(12, 12, 10, 10),
|
||||
margin = new RectOffset(4, 4, 4, 4),
|
||||
};
|
||||
|
||||
const int borderThickness = 2;
|
||||
const int cornerRadius = 4;
|
||||
|
||||
s_BoxStyle.normal.background = GenerateRoundedBorderTexture(
|
||||
borderThickness, cornerRadius,
|
||||
Color.white,
|
||||
new Color(0.155f, 0.155f, 0.155f, 1f),
|
||||
out var borderInset);
|
||||
|
||||
s_BoxStyle.border = borderInset;
|
||||
|
||||
s_Initialized = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 生成一张用于 GUIStyle 9-slice 的圆角边框纹理。
|
||||
///
|
||||
/// 纹理布局(9-slice):
|
||||
/// borderInset ─┤├─ edge ─┤├─ borderInset
|
||||
///
|
||||
/// 左上角块 │ 上边缘 │ 右上角块
|
||||
/// ──────────┼─────────┼──────────
|
||||
/// 左边缘 │ 中心 │ 右边缘
|
||||
/// ──────────┼─────────┼──────────
|
||||
/// 左下角块 │ 下边缘 │ 右下角块
|
||||
/// </summary>
|
||||
private static Texture2D GenerateRoundedBorderTexture(
|
||||
int borderThickness,
|
||||
int cornerRadius,
|
||||
Color borderColor,
|
||||
Color fillColor,
|
||||
out RectOffset borderInset)
|
||||
{
|
||||
// 角块大小必须能容纳整个圆角装饰 (圆角半径 + 边框宽度)
|
||||
int cornerBlockSize = cornerRadius + borderThickness + 1;
|
||||
// 边缘条带宽度
|
||||
int edgeWidth = 4;
|
||||
// 中心区域最小尺寸
|
||||
int centerSize = 2;
|
||||
|
||||
int texSize = cornerBlockSize * 2 + edgeWidth;
|
||||
// 确保中心区域有像素
|
||||
if (edgeWidth < centerSize)
|
||||
{
|
||||
edgeWidth = centerSize;
|
||||
texSize = cornerBlockSize * 2 + edgeWidth;
|
||||
}
|
||||
|
||||
borderInset = new RectOffset(cornerBlockSize, cornerBlockSize, cornerBlockSize, cornerBlockSize);
|
||||
|
||||
var tex = new Texture2D(texSize, texSize, TextureFormat.RGBA32, false);
|
||||
tex.wrapMode = TextureWrapMode.Clamp;
|
||||
tex.filterMode = FilterMode.Bilinear;
|
||||
|
||||
Color transparent = new Color(0, 0, 0, 0);
|
||||
Color[] pixels = new Color[texSize * texSize];
|
||||
|
||||
int maxCoord = texSize - 1;
|
||||
float outerR = cornerRadius + borderThickness; // 外圆角半径(白色边框的外缘)
|
||||
float innerR = cornerRadius; // 内圆角半径(深色填充的外缘)
|
||||
|
||||
for (int y = 0; y < texSize; y++)
|
||||
{
|
||||
for (int x = 0; x < texSize; x++)
|
||||
{
|
||||
// 像素是否在「外圆角矩形」内(白色边框区域)
|
||||
bool inOuter = IsInsideRoundedRect(x, y, 0, 0, maxCoord, maxCoord, outerR);
|
||||
if (!inOuter)
|
||||
{
|
||||
pixels[y * texSize + x] = transparent;
|
||||
continue;
|
||||
}
|
||||
|
||||
// 像素是否在「内圆角矩形」内(深色填充区域)
|
||||
int innerMin = borderThickness;
|
||||
int innerMax = maxCoord - borderThickness;
|
||||
|
||||
bool inInner = IsInsideRoundedRect(
|
||||
x, y,
|
||||
innerMin, innerMin,
|
||||
innerMax, innerMax,
|
||||
innerR);
|
||||
|
||||
pixels[y * texSize + x] = inInner ? fillColor : borderColor;
|
||||
}
|
||||
}
|
||||
|
||||
tex.SetPixels(pixels);
|
||||
tex.Apply();
|
||||
return tex;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断坐标 (x,y) 是否在由 (minX,minY)-(maxX,maxY) 定义的圆角矩形内。
|
||||
/// </summary>
|
||||
private static bool IsInsideRoundedRect(
|
||||
int x, int y,
|
||||
int minX, int minY,
|
||||
int maxX, int maxY,
|
||||
float radius)
|
||||
{
|
||||
// 完全在边界外
|
||||
if (x < minX || x > maxX || y < minY || y > maxY)
|
||||
return false;
|
||||
|
||||
// 主体矩形区域(远离四个角)
|
||||
if (x >= minX + radius && x <= maxX - radius) return true;
|
||||
if (y >= minY + radius && y <= maxY - radius) return true;
|
||||
|
||||
// 四个圆角区域 —— 判断是否在对应的四分之一圆内
|
||||
float cx, cy;
|
||||
|
||||
if (x < minX + radius && y < minY + radius)
|
||||
{
|
||||
// 左上角
|
||||
cx = minX + radius;
|
||||
cy = minY + radius;
|
||||
}
|
||||
else if (x > maxX - radius && y < minY + radius)
|
||||
{
|
||||
// 右上角
|
||||
cx = maxX - radius;
|
||||
cy = minY + radius;
|
||||
}
|
||||
else if (x < minX + radius && y > maxY - radius)
|
||||
{
|
||||
// 左下角
|
||||
cx = minX + radius;
|
||||
cy = maxY - radius;
|
||||
}
|
||||
else if (x > maxX - radius && y > maxY - radius)
|
||||
{
|
||||
// 右下角
|
||||
cx = maxX - radius;
|
||||
cy = maxY - radius;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 边缘条带区域(不在任何角区),在矩形边界内
|
||||
return true;
|
||||
}
|
||||
|
||||
float dx = x - cx;
|
||||
float dy = y - cy;
|
||||
return (dx * dx + dy * dy) <= (radius * radius);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3b3b1ec1e8a20824488b035d1258c2e6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -25,7 +25,6 @@ namespace XericUIEditor.BubbleLayout
|
||||
private SerializedProperty m_LayoutIgnoreInactive;
|
||||
|
||||
// ── 样式 ──
|
||||
private static GUIStyle s_BoxStyle;
|
||||
private static GUIStyle s_PerfHeaderStyle;
|
||||
private static GUIStyle s_PerfLabelStyle;
|
||||
private static GUIStyle s_PerfValueStyle;
|
||||
@@ -36,17 +35,6 @@ namespace XericUIEditor.BubbleLayout
|
||||
if (s_StylesInitialized)
|
||||
return;
|
||||
|
||||
s_BoxStyle = new GUIStyle(GUI.skin.box)
|
||||
{
|
||||
padding = new RectOffset(12, 12, 10, 10),
|
||||
margin = new RectOffset(4, 4, 4, 4),
|
||||
};
|
||||
|
||||
var bgTex = new Texture2D(1, 1);
|
||||
bgTex.SetPixel(0, 0, new Color(0.18f, 0.18f, 0.18f, 1f));
|
||||
bgTex.Apply();
|
||||
s_BoxStyle.normal.background = bgTex;
|
||||
|
||||
s_PerfHeaderStyle = new GUIStyle(EditorStyles.boldLabel)
|
||||
{
|
||||
fontSize = 11,
|
||||
@@ -93,7 +81,7 @@ namespace XericUIEditor.BubbleLayout
|
||||
EnsureStyles();
|
||||
|
||||
// ── 白色圆角边框 + 深色底 ──
|
||||
EditorGUILayout.BeginVertical(s_BoxStyle);
|
||||
EditorGUILayout.BeginVertical(BubbleLayoutEditorStyles.BoxStyle);
|
||||
|
||||
serializedObject.Update();
|
||||
|
||||
@@ -147,7 +135,7 @@ namespace XericUIEditor.BubbleLayout
|
||||
|
||||
EditorGUILayout.Space(6);
|
||||
|
||||
EditorGUILayout.BeginVertical(s_BoxStyle);
|
||||
EditorGUILayout.BeginVertical(BubbleLayoutEditorStyles.BoxStyle);
|
||||
|
||||
EditorGUILayout.LabelField("性能指标", s_PerfHeaderStyle);
|
||||
EditorGUILayout.Space(2);
|
||||
|
||||
@@ -5,42 +5,16 @@ using XericUI.BubbleLayout;
|
||||
namespace XericUIEditor.BubbleLayout
|
||||
{
|
||||
/// <summary>
|
||||
/// 气泡布局插件通用 Inspector —— 白色圆角边框 + 深色底,对所有 BubbleLayoutPluginBase 子类生效
|
||||
/// 气泡布局插件通用 Inspector —— 白色圆角边框 + 深色底,对所有 BubbleLayoutPluginBase 子类生效。
|
||||
/// </summary>
|
||||
[CustomEditor(typeof(BubbleLayoutPluginBase), true)]
|
||||
[CanEditMultipleObjects]
|
||||
internal class BubbleLayoutPluginEditor : Editor
|
||||
{
|
||||
private static GUIStyle s_BoxStyle;
|
||||
private static bool s_StylesInitialized;
|
||||
|
||||
private static void EnsureStyles()
|
||||
{
|
||||
if (s_StylesInitialized)
|
||||
return;
|
||||
|
||||
s_BoxStyle = new GUIStyle(GUI.skin.box)
|
||||
{
|
||||
padding = new RectOffset(12, 12, 10, 10),
|
||||
margin = new RectOffset(4, 4, 4, 4),
|
||||
};
|
||||
|
||||
var bgTex = new Texture2D(1, 1);
|
||||
bgTex.SetPixel(0, 0, new Color(0.18f, 0.18f, 0.18f, 1f));
|
||||
bgTex.Apply();
|
||||
s_BoxStyle.normal.background = bgTex;
|
||||
|
||||
s_StylesInitialized = true;
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
EnsureStyles();
|
||||
EditorGUILayout.BeginVertical(BubbleLayoutEditorStyles.BoxStyle);
|
||||
|
||||
// ── 白色圆角边框 + 深色底 ──
|
||||
EditorGUILayout.BeginVertical(s_BoxStyle);
|
||||
|
||||
// 绘制所有序列化字段(包括基类的 Enabled 和 Order)
|
||||
serializedObject.Update();
|
||||
|
||||
SerializedProperty iterator = serializedObject.GetIterator();
|
||||
@@ -50,7 +24,6 @@ namespace XericUIEditor.BubbleLayout
|
||||
{
|
||||
enterChildren = false;
|
||||
|
||||
// 跳过脚本引用字段
|
||||
if (iterator.name == "m_Script")
|
||||
continue;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user