Files
Liubing\LB 3d8d4d18f3 first commit
先修复一下,错误的场景

删除不必要的钓场资产

修复into场景

update:更新meta文件,修复报错

update:修复资源

修复第一章节建造

修复建造第三章

update:删除多余内容

update:更新README.md

update:还原图标

update:更新README

update:更新配置
2026-04-28 02:17:22 +08:00

281 lines
9.9 KiB
C#

using Coffee.UISoftMaskInternal;
using UnityEditor;
using UnityEditor.U2D;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.UI;
namespace Coffee.UISoftMask
{
[CustomEditor(typeof(SoftMask), true)]
[CanEditMultipleObjects]
public class SoftMaskEditor : Editor
{
private const string k_PrefsPreview = "k_PrefsPreview";
private const int k_PreviewSize = 220;
private static readonly GUIContent s_ContentMaskingMode = new GUIContent();
private SerializedProperty _alphaHitTest;
private SerializedProperty _antiAliasingThreshold;
private SerializedProperty _downSamplingRate;
private SerializedProperty _maskingMode;
private bool _preview;
private SerializedProperty _showMaskGraphic;
private SerializedProperty _softnessRange;
protected void OnEnable()
{
_maskingMode = serializedObject.FindProperty("m_MaskingMode");
_antiAliasingThreshold = serializedObject.FindProperty("m_AntiAliasingThreshold");
_showMaskGraphic = serializedObject.FindProperty("m_ShowMaskGraphic");
_downSamplingRate = serializedObject.FindProperty("m_DownSamplingRate");
_alphaHitTest = serializedObject.FindProperty("m_AlphaHitTest");
_softnessRange = serializedObject.FindProperty("m_SoftnessRange");
_preview = EditorPrefs.GetBool(k_PrefsPreview, false);
s_ContentMaskingMode.text = _maskingMode.displayName;
s_ContentMaskingMode.tooltip = _maskingMode.tooltip;
SoftMask.onRenderSoftMaskBuffer += OnRenderSoftMaskBuffer;
}
private void OnDisable()
{
SoftMask.onRenderSoftMaskBuffer -= OnRenderSoftMaskBuffer;
}
public override void OnInspectorGUI()
{
var current = target as SoftMask;
if (current == null) return;
if (!current.graphic || !current.graphic.IsActive())
{
EditorGUILayout.HelpBox("Masking disabled due to Graphic component being disabled.",
MessageType.Warning);
}
EditorGUILayout.PropertyField(_maskingMode);
OpenProjectSettings(current);
switch ((SoftMask.MaskingMode)_maskingMode.intValue)
{
case SoftMask.MaskingMode.SoftMasking:
{
EditorGUILayout.PropertyField(_showMaskGraphic);
EditorGUILayout.PropertyField(_alphaHitTest);
EditorGUILayout.PropertyField(_downSamplingRate);
EditorGUILayout.PropertyField(_softnessRange);
FixUiMaskIssue(current); // Fix 'UIMask' issue.
DrawSoftMaskBuffer(); // Preview soft mask buffer.
break;
}
case SoftMask.MaskingMode.AntiAliasing:
{
EditorGUILayout.PropertyField(_alphaHitTest);
EditorGUILayout.PropertyField(_antiAliasingThreshold);
break;
}
case SoftMask.MaskingMode.Normal:
{
EditorGUILayout.PropertyField(_showMaskGraphic);
break;
}
}
serializedObject.ApplyModifiedProperties();
// Draw alpha hit test warning
if (current.alphaHitTest)
{
Utils.DrawAlphaHitTestWarning(current.graphic);
}
}
private void OnRenderSoftMaskBuffer(SoftMask softMask)
{
if (softMask != target) return;
Repaint();
}
private static void OpenProjectSettings(SoftMask current)
{
if (current.maskingMode != SoftMask.MaskingMode.SoftMasking) return;
if (UISoftMaskProjectSettings.instance.m_SoftMaskEnabled) return;
GUILayout.BeginHorizontal();
EditorGUILayout.HelpBox("SoftMasking is disabled in the project settings.", MessageType.Warning);
if (GUILayout.Button("Open"))
{
SettingsService.OpenProjectSettings("Project/UI/Soft Mask");
}
GUILayout.EndHorizontal();
}
private static void FixUiMaskIssue(SoftMask current)
{
if (current.graphic is Image currentImage && IsMaskUI(currentImage.sprite))
{
GUILayout.BeginHorizontal();
EditorGUILayout.HelpBox(
"SoftMask does not recommend to use 'UIMask' sprite as a source image.\n" +
"(It contains only small alpha pixels.)\n" +
"Do you want to use 'UISprite' instead?",
MessageType.Warning);
if (GUILayout.Button("Fix"))
{
currentImage.sprite = AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/UISprite.psd");
}
GUILayout.EndHorizontal();
}
}
private static bool IsMaskUI(Object obj)
{
return obj
&& obj.name == "UIMask"
&& AssetDatabase.GetAssetPath(obj) == "Resources/unity_builtin_extra";
}
private void DrawSoftMaskBuffer()
{
var current = target as SoftMask;
if (current == null || !current.SoftMaskingEnabled()) return;
GUILayout.BeginVertical(EditorStyles.helpBox);
{
if (_preview != (_preview = EditorGUILayout.ToggleLeft("Preview Soft Mask Buffer", _preview)))
{
EditorPrefs.SetBool(k_PrefsPreview, _preview);
}
if (_preview)
{
var tex = current._softMaskBuffer;
var depth = current.softMaskDepth;
var colorMask = GetColorMask(depth);
if (tex)
{
GUILayout.Label($"{tex.name} (Depth: {depth} {colorMask})");
var aspectRatio = (float)tex.width / tex.height;
EditorGUI.DrawPreviewTexture(
GUILayoutUtility.GetRect(k_PreviewSize, k_PreviewSize / aspectRatio), tex, null,
ScaleMode.ScaleToFit, aspectRatio, 0, colorMask);
}
}
}
GUILayout.EndVertical();
}
private static ColorWriteMask GetColorMask(int depth)
{
switch (depth)
{
case 0: return ColorWriteMask.Red;
case 1: return ColorWriteMask.Red | ColorWriteMask.Green;
case 2: return ColorWriteMask.Red | ColorWriteMask.Green | ColorWriteMask.Blue;
default: return ColorWriteMask.All;
}
}
private static string GetWarningMessage(Graphic src)
{
if (!(src is Image || src is RawImage))
{
return $"{src.GetType().Name} is not supported type for alpha hit test.";
}
if (src is Image image && image)
{
var atlas = image.overrideSprite
? image.overrideSprite.GetActiveAtlas()
: null;
if (atlas && atlas.GetPackingSettings().enableTightPacking)
{
return $"Tight packed sprite atlas '{atlas.name}' is not supported.";
}
}
var tex = src.GetActualMainTexture();
if (!tex)
{
return "No texture is assigned.";
}
if (!(tex is Texture2D))
{
return $"The texture '{tex.name}' is not Texture2D.";
}
if (!tex.isReadable)
{
return $"The texture '{tex.name}' is not readable";
}
return "";
}
public static void DrawAlphaHitTestWarning(Graphic graphic)
{
if (!graphic) return;
var warn = GetWarningMessage(graphic);
if (string.IsNullOrEmpty(warn)) return;
EditorGUILayout.BeginHorizontal();
EditorGUILayout.HelpBox(warn, MessageType.Warning);
if (GUILayout.Button("Select"))
{
if (graphic is Image image && image)
{
var sprite = image.overrideSprite;
if (sprite)
{
Selection.activeObject = sprite.GetActiveAtlas();
}
if (!Selection.activeObject)
{
Selection.activeObject = image.GetActualMainTexture();
}
}
else
{
Selection.activeObject = graphic.GetActualMainTexture();
}
}
EditorGUILayout.EndHorizontal();
}
//%%%% Context menu for editor %%%%
[MenuItem("CONTEXT/" + nameof(Mask) + "/Convert To " + nameof(SoftMask), true)]
private static bool _ConvertToSoftMask(MenuCommand command)
{
return command.context.CanConvertTo<SoftMask>();
}
[MenuItem("CONTEXT/" + nameof(Mask) + "/Convert To " + nameof(SoftMask), false)]
private static void ConvertToSoftMask(MenuCommand command)
{
command.context.ConvertTo<SoftMask>();
}
[MenuItem("CONTEXT/" + nameof(SoftMask) + "/Convert To " + nameof(Mask), true)]
private static bool _ConvertToMask(MenuCommand command)
{
return command.context.CanConvertTo<Mask>();
}
[MenuItem("CONTEXT/" + nameof(SoftMask) + "/Convert To " + nameof(Mask), false)]
private static void ConvertToMask(MenuCommand command)
{
command.context.ConvertTo<Mask>();
}
}
}