update 0.6.4
This commit is contained in:
@@ -1,113 +1,18 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace XericLibrary.Runtime.Blueprint.QuickGraph
|
||||
{
|
||||
/// <summary>QuickGraph 网格背景;样式资源材质只绑定不拥有,运行时创建材质才由本工具释放。</summary>
|
||||
[BlueprintTool(phase: ToolPhase.Render, order: 0)]
|
||||
[BlueprintTheme("QuickGraph")]
|
||||
[BlueprintTool(phase: ToolPhase.Render, order: 0)] [BlueprintTheme("QuickGraph")]
|
||||
public class QuickUGUIGraphGridBackgroundTool : BlueprintTool
|
||||
{
|
||||
private const string BackgroundGoName = "__Bp_GridBackground";
|
||||
private QuickGraphGridBackgroundConfig _defaultConfig;
|
||||
private QuickGraphRenderStyleResolver _styleResolver;
|
||||
private Image _backgroundImage;
|
||||
private Material _backgroundMaterial;
|
||||
private QuickGraphGridBackgroundConfig _ownedMaterialConfig;
|
||||
private string _ownedShaderName;
|
||||
private QuickGraphGridBackgroundConfig Config
|
||||
{
|
||||
get
|
||||
{
|
||||
if (ToolConfig is QuickGraphGridBackgroundConfig external) return external;
|
||||
if (_defaultConfig == null) _defaultConfig = ScriptableObject.CreateInstance<QuickGraphGridBackgroundConfig>();
|
||||
return _defaultConfig;
|
||||
}
|
||||
}
|
||||
public override void OnInitialize()
|
||||
{
|
||||
_styleResolver = new QuickGraphRenderStyleResolver(Graph, gridFallback: ConfigStyle);
|
||||
_styleResolver.Changed += OnStyleChanged;
|
||||
EnsureBackground(); RebindMaterial(_styleResolver.Snapshot.Grid, true);
|
||||
}
|
||||
public override void OnRender()
|
||||
{
|
||||
if (Graph == null) return;
|
||||
EnsureBackground();
|
||||
var style = _styleResolver != null ? _styleResolver.Snapshot.Grid : ConfigStyle();
|
||||
RebindMaterial(style, false);
|
||||
ApplyStyle(style);
|
||||
}
|
||||
public override void OnConfigChanged()
|
||||
{
|
||||
_styleResolver?.Refresh();
|
||||
if (_styleResolver == null) RebindMaterial(ConfigStyle(), true);
|
||||
Graph?.MarkDirty();
|
||||
}
|
||||
private QuickGraphGridRenderStyle ConfigStyle()
|
||||
{
|
||||
var cfg = Config;
|
||||
return new QuickGraphGridRenderStyle { Material = cfg.OverrideMaterial, ShaderName = cfg.ShaderName, Size = cfg.GridSize, OverlayPower = cfg.GridOverlayPower, Threshold = cfg.GridLineThreshold, Exp = cfg.GridExp, Color = cfg.GridColor, Background = cfg.GridBackgroundColor };
|
||||
}
|
||||
private void OnStyleChanged(QuickGraphRenderStyleSnapshot snapshot)
|
||||
{
|
||||
if ((snapshot.Changes & QuickGraphRenderStyleChange.GridAppearance) == 0) return;
|
||||
RebindMaterial(snapshot.Grid, true);
|
||||
Graph?.MarkDirty();
|
||||
}
|
||||
private void EnsureBackground()
|
||||
{
|
||||
if (_backgroundImage != null || Graph?.Canvas?.GetRootTransform() == null) return;
|
||||
var root = Graph.Canvas.GetRootTransform(); var existing = root.Find(BackgroundGoName);
|
||||
if (existing != null) _backgroundImage = existing.GetComponent<Image>();
|
||||
if (_backgroundImage != null) return;
|
||||
if (existing != null) Object.DestroyImmediate(existing.gameObject);
|
||||
var go = new GameObject(BackgroundGoName, typeof(RectTransform)); go.hideFlags = HideFlags.HideAndDontSave; go.transform.SetParent(root, false); go.transform.SetAsFirstSibling();
|
||||
var rect = go.GetComponent<RectTransform>(); rect.anchorMin = Vector2.zero; rect.anchorMax = Vector2.one; rect.offsetMin = Vector2.zero; rect.offsetMax = Vector2.zero;
|
||||
_backgroundImage = go.AddComponent<Image>(); _backgroundImage.raycastTarget = true; _backgroundImage.maskable = false;
|
||||
}
|
||||
private void RebindMaterial(QuickGraphGridRenderStyle style, bool force)
|
||||
{
|
||||
if (_backgroundImage == null) return;
|
||||
Material target = style.Material;
|
||||
QuickGraphGridBackgroundConfig owner = null;
|
||||
string ownedShader = null;
|
||||
if (target == null)
|
||||
{
|
||||
// 旧 Config 仅在 style 未提供共享材质时参与回退;其缓存材质为唯一可释放对象。
|
||||
if (style.ShaderName == Config.ShaderName) { target = Config.GetOrCreateMaterial(); owner = Config.OverrideMaterial == null ? Config : null; }
|
||||
else if (!string.IsNullOrEmpty(style.ShaderName))
|
||||
{
|
||||
if (_backgroundMaterial != null && _ownedShaderName == style.ShaderName) return;
|
||||
var shader = Shader.Find(style.ShaderName); if (shader != null) { target = new Material(shader) { name = "BpGridBackground_StyleMat" }; ownedShader = style.ShaderName; }
|
||||
}
|
||||
}
|
||||
if (target == _backgroundMaterial) return;
|
||||
ReleaseOwnedMaterial();
|
||||
_backgroundMaterial = target; _ownedMaterialConfig = owner; _ownedShaderName = ownedShader;
|
||||
if (_backgroundImage != null) _backgroundImage.material = _backgroundMaterial;
|
||||
}
|
||||
private void ApplyStyle(QuickGraphGridRenderStyle style)
|
||||
{
|
||||
if (_backgroundMaterial == null || Graph?.Canvas == null || _backgroundImage == null) return;
|
||||
var size = _backgroundImage.rectTransform.rect.size; var zoom = Graph.Canvas.ZoomLevel; var pan = Graph.Canvas.PanOffset; var gridSize = Mathf.Max(.0001f, style.Size);
|
||||
_backgroundMaterial.SetVector("_Transform", new Vector4(size.x / (zoom * gridSize), size.y / (zoom * gridSize), -(pan.x + .5f * size.x) / (zoom * gridSize), -(pan.y + .5f * size.y) / (zoom * gridSize)));
|
||||
_backgroundMaterial.SetFloat("_GridOverlayPower", style.OverlayPower); _backgroundMaterial.SetFloat("_GridLineThreshold", style.Threshold); _backgroundMaterial.SetFloat("_GridExp", style.Exp);
|
||||
_backgroundMaterial.SetColor("_GridColor", style.Color); _backgroundMaterial.SetColor("_GridBackgroundColor", style.Background);
|
||||
}
|
||||
private void ReleaseOwnedMaterial()
|
||||
{
|
||||
if (_backgroundImage != null) _backgroundImage.material = null;
|
||||
if (_ownedMaterialConfig != null) _ownedMaterialConfig.ReleaseMaterial();
|
||||
else if (_backgroundMaterial != null && !string.IsNullOrEmpty(_ownedShaderName)) { if (Application.isPlaying) Object.Destroy(_backgroundMaterial); else Object.DestroyImmediate(_backgroundMaterial); }
|
||||
_backgroundMaterial = null; _ownedMaterialConfig = null; _ownedShaderName = null;
|
||||
}
|
||||
public override void OnDestroy()
|
||||
{
|
||||
if (_styleResolver != null) _styleResolver.Changed -= OnStyleChanged;
|
||||
_styleResolver?.Dispose(); _styleResolver = null; ReleaseOwnedMaterial();
|
||||
if (_backgroundImage != null) { if (Application.isPlaying) Object.Destroy(_backgroundImage.gameObject); else Object.DestroyImmediate(_backgroundImage.gameObject); _backgroundImage = null; }
|
||||
_defaultConfig = null;
|
||||
}
|
||||
private const string Name = "__Bp_GridBackground"; private QuickGraphRenderStyleResolver _styles; private Image _image; private Material _material; private string _ownedShader; private bool _transformErrorLogged; private bool _materialUnavailableErrorLogged;
|
||||
public override void OnInitialize() { _styles = new QuickGraphRenderStyleResolver(Graph); _styles.Changed += _ => Graph?.MarkDirty(); Ensure(); Rebind(_styles.Snapshot.Grid); }
|
||||
public override void OnConfigChanged() => _styles?.Refresh();
|
||||
public override void OnRender() { Ensure(); if (_styles == null) return; var style = _styles.Snapshot.Grid; Rebind(style); Apply(style); }
|
||||
private void Ensure() { if (_image != null || Graph?.Canvas?.GetRootTransform() == null) return; var root = Graph.Canvas.GetRootTransform(); var existing = root.Find(Name); if (existing != null) _image = existing.GetComponent<Image>(); if (_image == null) { if (existing != null) Object.DestroyImmediate(existing.gameObject); var go = new GameObject(Name, typeof(RectTransform), typeof(Image)); go.hideFlags = HideFlags.HideAndDontSave; go.transform.SetParent(root, false); go.transform.SetAsFirstSibling(); var rt = go.GetComponent<RectTransform>(); rt.anchorMin = Vector2.zero; rt.anchorMax = Vector2.one; rt.offsetMin = Vector2.zero; rt.offsetMax = Vector2.zero; _image = go.GetComponent<Image>(); } }
|
||||
private void Rebind(QuickGraphGridRenderStyle style) { if (_image == null) return; Material target = style.Material; string owned = null; if (target == null && !string.IsNullOrEmpty(style.ShaderName)) { if (_material != null && _ownedShader == style.ShaderName) return; var shader = Shader.Find(style.ShaderName); if (shader != null) { target = new Material(shader) { name = "BpGridBackground_StyleMat" }; owned = style.ShaderName; } } if (target == null) { if (!_materialUnavailableErrorLogged) { Debug.LogError($"[QuickGraph] 网格 material 与 shader 均不可用: GraphId={Graph?.GraphId}, material={style.Material}, shader=\"{style.ShaderName}\"。"); _materialUnavailableErrorLogged = true; } } else _materialUnavailableErrorLogged = false; if (target == _material) return; ReleaseMaterial(); _material = target; _ownedShader = owned; _image.material = target; }
|
||||
private void Apply(QuickGraphGridRenderStyle style) { if (_image == null) return; _image.raycastTarget = style.RaycastTarget; _image.maskable = style.Maskable; if (_material == null || Graph?.Canvas == null) return; var size = _image.rectTransform.rect.size; var zoom = Graph.Canvas.ZoomLevel; if (style.Size != 0f && zoom != 0f) { var pan = Graph.Canvas.PanOffset; _material.SetVector("_Transform", new Vector4(size.x / (zoom * style.Size), size.y / (zoom * style.Size), -(pan.x + .5f * size.x) / (zoom * style.Size), -(pan.y + .5f * size.y) / (zoom * style.Size))); _transformErrorLogged = false; } else if (!_transformErrorLogged) { Debug.LogError("[QuickGraph] 网格样式 size 或 zoom 为 0,未写入 _Transform。"); _transformErrorLogged = true; } _material.SetFloat("_GridOverlayPower", style.OverlayPower); _material.SetFloat("_GridLineThreshold", style.Threshold); _material.SetFloat("_GridExp", style.Exp); _material.SetColor("_GridColor", style.Color); _material.SetColor("_GridBackgroundColor", style.Background); _material.SetFloat("_LodTransthd", style.LodTransitionThreshold); _material.SetFloat("_LodTransitionStart", style.LodTransitionStart); _material.SetFloat("_LodTransitionEnd", style.LodTransitionEnd); _material.SetVector("_CellCenter", style.CellCenter); _material.SetFloat("_LineShapeScale", style.LineShapeScale); }
|
||||
private void ReleaseMaterial() { if (_image != null) _image.material = null; if (_material != null && _ownedShader != null) { if (Application.isPlaying) Object.Destroy(_material); else Object.DestroyImmediate(_material); } _material = null; _ownedShader = null; }
|
||||
public override void OnDestroy() { _styles?.Dispose(); ReleaseMaterial(); if (_image != null) { if (Application.isPlaying) Object.Destroy(_image.gameObject); else Object.DestroyImmediate(_image.gameObject); } _image = null; }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user