update 0.6.4
This commit is contained in:
@@ -1,198 +1,19 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace XericLibrary.Runtime.Blueprint.QuickGraph
|
||||
{
|
||||
/// <summary>
|
||||
/// QuickGraph 输入交互工具 —— 处理画布平移、缩放。
|
||||
/// <para>中键拖拽 = 平移;滚轮 = 缩放。</para>
|
||||
/// <para>视图状态读写委托给 <see cref="BlueprintViewportController"/>,
|
||||
/// 输入参数从 <see cref="QuickGraphInputConfig"/> 读取。</para>
|
||||
/// </summary>
|
||||
[BlueprintTool(phase: ToolPhase.PreUpdate, order: 50)]
|
||||
[BlueprintTheme("QuickGraph")]
|
||||
[BlueprintTool(phase: ToolPhase.PreUpdate, order: 50)] [BlueprintTheme("QuickGraph")]
|
||||
public class QuickGraphInputTool : BlueprintTool
|
||||
{
|
||||
// ---------- 配置(从 ToolConfigAssets 读取) ----------
|
||||
private QuickGraphInputConfig Config
|
||||
{
|
||||
get
|
||||
{
|
||||
if (ToolConfig is QuickGraphInputConfig external)
|
||||
return external;
|
||||
if (_defaultConfig == null)
|
||||
_defaultConfig = ScriptableObject.CreateInstance<QuickGraphInputConfig>();
|
||||
return _defaultConfig;
|
||||
}
|
||||
}
|
||||
private static QuickGraphInputConfig _defaultConfig;
|
||||
|
||||
// ---------- 缓存的 ViewportController 引用 ----------
|
||||
private BlueprintViewportController _viewport;
|
||||
private BlueprintViewportController Viewport
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_viewport == null && Graph != null)
|
||||
_viewport = BlueprintToolProvider.GetToolByType<BlueprintViewportController>(Graph);
|
||||
return _viewport;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------- 拖拽状态 ----------
|
||||
private bool _isDragging;
|
||||
private int _activeDragButton = -1;
|
||||
|
||||
private Vector2 senderPanDirection() => GraphInputTool.GetAdapter(Graph)?.PanDirection ?? Vector2.zero;
|
||||
private float senderZoomAxis() => GraphInputTool.GetAdapter(Graph)?.ZoomAxis ?? 0f;
|
||||
|
||||
// ---------- 选择状态 ----------
|
||||
private BlueprintElementBase _hoveredElement;
|
||||
|
||||
public override void OnPointerMove(GraphInputTool sender, Vector2 canvasPoint, Vector2 delta)
|
||||
{
|
||||
if (Graph == null || _isDragging) return;
|
||||
|
||||
var hit = Graph.HitTest(canvasPoint);
|
||||
_hoveredElement = hit as BlueprintElementBase;
|
||||
}
|
||||
|
||||
/// <summary>当前悬停的元素(可能为 null)</summary>
|
||||
public BlueprintElementBase HoveredElement => _hoveredElement;
|
||||
|
||||
/// <summary>当前选中的元素(委托给 SelectorHandle)。</summary>
|
||||
public BlueprintElementBase SelectedElement =>
|
||||
BlueprintToolProvider.GetSelector(Graph).PrimarySelection as BlueprintElementBase;
|
||||
|
||||
public override void OnConfigChanged()
|
||||
{
|
||||
var viewport = Viewport;
|
||||
if (viewport == null) return;
|
||||
|
||||
var cfg = Config;
|
||||
viewport.MinZoom = cfg.MinZoom;
|
||||
viewport.MaxZoom = cfg.MaxZoom;
|
||||
viewport.TargetZoomLevel = Mathf.Clamp(viewport.TargetZoomLevel, cfg.MinZoom, cfg.MaxZoom);
|
||||
|
||||
// ViewportController 是 Canvas Pan/Zoom 的唯一提交者;这里只更新 controller 的范围与目标。
|
||||
Graph?.MarkDirty();
|
||||
}
|
||||
|
||||
public override void OnUpdate(float deltaTime)
|
||||
{
|
||||
if (Graph?.Canvas == null) return;
|
||||
var viewport = Viewport;
|
||||
if (viewport == null) return;
|
||||
|
||||
var cfg = Config;
|
||||
|
||||
// ── 同步缩放范围 ──
|
||||
viewport.MinZoom = cfg.MinZoom;
|
||||
viewport.MaxZoom = cfg.MaxZoom;
|
||||
|
||||
// ── 键盘 Pan ──
|
||||
viewport.TargetPanOffset += senderPanDirection() * cfg.KeyboardPanSpeed * deltaTime;
|
||||
|
||||
// ── 键盘 Zoom ──
|
||||
float zoomInput = senderZoomAxis();
|
||||
if (!Mathf.Approximately(zoomInput, 0f))
|
||||
{
|
||||
float oldZoom = viewport.TargetZoomLevel;
|
||||
float zoomDelta = zoomInput / cfg.ZoomDivisor;
|
||||
viewport.TargetZoomLevel = Mathf.Clamp(
|
||||
viewport.TargetZoomLevel + zoomDelta,
|
||||
viewport.MinZoom, viewport.MaxZoom);
|
||||
ApplyZoomFocus(oldZoom);
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 鼠标按下 =====
|
||||
|
||||
public override void OnPointerDown(GraphInputTool sender, Vector2 canvasPoint, int mouseButton)
|
||||
{
|
||||
if (Graph == null) return;
|
||||
|
||||
if (mouseButton == 2)
|
||||
{
|
||||
_isDragging = true;
|
||||
_activeDragButton = 2;
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 鼠标释放 =====
|
||||
|
||||
public override void OnPointerUp(GraphInputTool sender, Vector2 canvasPoint, int mouseButton)
|
||||
{
|
||||
if (_isDragging && _activeDragButton == mouseButton)
|
||||
{
|
||||
_isDragging = false;
|
||||
_activeDragButton = -1;
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 拖拽 =====
|
||||
|
||||
public override void OnPointerDrag(GraphInputTool sender, Vector2 canvasPoint, Vector2 delta, int mouseButton)
|
||||
{
|
||||
var viewport = Viewport;
|
||||
if (viewport == null) return;
|
||||
|
||||
if (mouseButton == 2)
|
||||
{
|
||||
// canvas delta 在本帧 Pan 提交后会反向跳变;仅使用 RenderRoot local 平面 delta。
|
||||
viewport.TargetPanOffset += (sender?.PointerLocalDelta ?? Vector2.zero) * Config.DragPanSpeed;
|
||||
Graph.MarkDirty();
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 滚轮 =====
|
||||
|
||||
public override void OnScroll(GraphInputTool sender, Vector2 canvasPoint, Vector2 scrollDelta)
|
||||
{
|
||||
var viewport = Viewport;
|
||||
if (viewport == null) return;
|
||||
|
||||
float oldZoom = viewport.TargetZoomLevel;
|
||||
|
||||
viewport.TargetZoomLevel = Mathf.Clamp(
|
||||
viewport.TargetZoomLevel + scrollDelta.y / Config.ZoomDivisor,
|
||||
viewport.MinZoom, viewport.MaxZoom);
|
||||
|
||||
if (!Mathf.Approximately(oldZoom, viewport.TargetZoomLevel))
|
||||
{
|
||||
viewport.TargetPanOffset += canvasPoint * (oldZoom - viewport.TargetZoomLevel);
|
||||
Graph.MarkDirty();
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 快捷键 =====
|
||||
|
||||
public override void OnAction(GraphInputTool sender, string actionName)
|
||||
{
|
||||
if (Graph?.Canvas == null) return;
|
||||
|
||||
switch (actionName)
|
||||
{
|
||||
case BlueprintInputConstants.FocusHome:
|
||||
Viewport?.ResetView();
|
||||
break;
|
||||
case BlueprintInputConstants.Undo:
|
||||
break;
|
||||
case BlueprintInputConstants.Redo:
|
||||
break;
|
||||
case BlueprintInputConstants.NavigateParent:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 以鼠标焦点为中心缩放(键盘调用 — 自行读取鼠标位置) =====
|
||||
|
||||
private void ApplyZoomFocus(float oldZoom)
|
||||
{
|
||||
var viewport = Viewport;
|
||||
if (viewport == null || Graph?.Canvas == null) return;
|
||||
|
||||
Vector2 canvasCursor = Graph.Canvas.ScreenToCanvas(BlueprintUGUIInputManager.MousePosition);
|
||||
viewport.TargetPanOffset += canvasCursor * (oldZoom - viewport.TargetZoomLevel);
|
||||
}
|
||||
private QuickGraphRenderStyleResolver _styles; private BlueprintViewportController _viewport; private bool _dragging; private int _button = -1; private BlueprintViewportController Viewport => _viewport ?? (_viewport = BlueprintToolProvider.GetToolByType<BlueprintViewportController>(Graph));
|
||||
private Vector2 Pan => GraphInputTool.GetAdapter(Graph)?.PanDirection ?? Vector2.zero; private float Zoom => GraphInputTool.GetAdapter(Graph)?.ZoomAxis ?? 0f;
|
||||
public override void OnInitialize() { _styles = new QuickGraphRenderStyleResolver(Graph); _styles.Changed += _ => ApplyViewport(); ApplyViewport(); }
|
||||
public override void OnConfigChanged() => _styles?.Refresh(); private void ApplyViewport() { if (Viewport == null || _styles == null) return; Graph?.MarkDirty(); }
|
||||
public override void OnUpdate(float dt) { if (Graph?.Canvas == null || Viewport == null || _styles == null) return; var s = _styles.Snapshot.Input; ApplyViewport(); Viewport.TargetPanOffset += Pan * s.KeyboardPanSpeed * dt; var input = Zoom; if (!Mathf.Approximately(input, 0f)) { var old = Viewport.TargetZoomLevel; Viewport.TargetZoomLevel += input * s.KeyboardZoomSpeed; ApplyFocus(old); } }
|
||||
public override void OnPointerDown(GraphInputTool sender, Vector2 point, int button) { if (_styles != null && button == _styles.Snapshot.Input.PanMouseButton) { _dragging = true; _button = button; } }
|
||||
public override void OnPointerUp(GraphInputTool sender, Vector2 point, int button) { if (_dragging && _button == button) { _dragging = false; _button = -1; } }
|
||||
public override void OnPointerDrag(GraphInputTool sender, Vector2 point, Vector2 delta, int button) { if (_dragging && _button == button && Viewport != null) { Viewport.TargetPanOffset += (sender?.PointerLocalDelta ?? Vector2.zero) * _styles.Snapshot.Input.DragPanSpeed; Graph.MarkDirty(); } }
|
||||
public override void OnScroll(GraphInputTool sender, Vector2 point, Vector2 delta) { if (Viewport == null || _styles == null) return; var old = Viewport.TargetZoomLevel; Viewport.TargetZoomLevel += delta.y / _styles.Snapshot.Input.ZoomDivisor; if (!Mathf.Approximately(old, Viewport.TargetZoomLevel)) { Viewport.TargetPanOffset += point * (old - Viewport.TargetZoomLevel); Graph.MarkDirty(); } }
|
||||
private void ApplyFocus(float old) { if (Viewport == null || Graph?.Canvas == null) return; var cursor = Graph.Canvas.ScreenToCanvas(BlueprintUGUIInputManager.MousePosition); Viewport.TargetPanOffset += cursor * (old - Viewport.TargetZoomLevel); }
|
||||
public override void OnDestroy() { _styles?.Dispose(); _styles = null; }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user