326 lines
12 KiB
C#
326 lines
12 KiB
C#
using UnityEngine;
|
|
using System.Collections.Generic;
|
|
using Shapes;
|
|
|
|
namespace AibisDream.MiniGame.HuoShan
|
|
{
|
|
/// <summary>
|
|
/// 语言想象系统主管理器 - 协调各模块工作
|
|
/// </summary>
|
|
[RequireComponent(typeof(CircularViewport))]
|
|
public class LanguageImaginationSystem : ImmediateModeShapeDrawer
|
|
{
|
|
[Header("场设置")]
|
|
public float fieldWidth = 50f;
|
|
public float fieldHeight = 50f;
|
|
public int backgroundNodeCount = 200;
|
|
|
|
[Header("圆形视口设置")]
|
|
public float viewportRadius = 5f;
|
|
|
|
[Header("连线设置")]
|
|
public float connectionLineWidth = 0.05f;
|
|
public Color backgroundConnectionColor = new Color(1f, 1f, 1f, 0.3f);
|
|
public Color sentenceConnectionColor = Color.yellow;
|
|
public Color candidateConnectionColor = Color.cyan;
|
|
|
|
[Header("Gizmo调试设置")]
|
|
public bool showGizmos = true;
|
|
public bool showFieldBounds = true;
|
|
public bool showNodes = true;
|
|
public bool showConnections = true;
|
|
public bool showSentenceNodes = true;
|
|
public float nodeGizmoSize = 0.2f;
|
|
|
|
private BackgroundTextLayer _backgroundLayer;
|
|
private CircularViewport _viewport;
|
|
private SentenceBuilder _sentenceBuilder;
|
|
|
|
private void Start()
|
|
{
|
|
Initialize();
|
|
}
|
|
|
|
private void Initialize()
|
|
{
|
|
// 初始化圆形视口
|
|
_viewport = GetComponent<CircularViewport>();
|
|
if (_viewport == null)
|
|
{
|
|
_viewport = gameObject.AddComponent<CircularViewport>();
|
|
}
|
|
_viewport.viewportRadius = viewportRadius;
|
|
|
|
// 初始化背景文字层
|
|
_backgroundLayer = new BackgroundTextLayer(
|
|
fieldWidth,
|
|
fieldHeight,
|
|
backgroundNodeCount,
|
|
transform
|
|
);
|
|
|
|
// 初始化造句系统
|
|
_sentenceBuilder = new SentenceBuilder(_backgroundLayer, _viewport, this);
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (_backgroundLayer != null)
|
|
{
|
|
_backgroundLayer.Update(Time.deltaTime);
|
|
}
|
|
}
|
|
|
|
public override void DrawShapes(Camera cam)
|
|
{
|
|
using (Draw.Command(cam))
|
|
{
|
|
Draw.ResetAllDrawStates();
|
|
Draw.LineGeometry = LineGeometry.Volumetric3D;
|
|
Draw.Thickness = connectionLineWidth;
|
|
|
|
// 绘制背景文字之间的连线
|
|
if (_backgroundLayer != null)
|
|
{
|
|
DrawBackgroundConnections();
|
|
}
|
|
|
|
// 绘制句子和候选文字的连线
|
|
if (_sentenceBuilder != null)
|
|
{
|
|
DrawSentenceConnections();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void DrawBackgroundConnections()
|
|
{
|
|
var allNodes = _backgroundLayer.GetAllNodes();
|
|
foreach (var node in allNodes)
|
|
{
|
|
// 只绘制在视口内的连线
|
|
if (!_viewport.IsPositionInViewport(node.Position))
|
|
continue;
|
|
|
|
foreach (var connectedNode in node.ConnectedNodes)
|
|
{
|
|
// 只绘制连接的另一端也在视口内的连线
|
|
if (!_viewport.IsPositionInViewport(connectedNode.Position))
|
|
continue;
|
|
|
|
// 跳过已经选定的节点之间的连线(由句子连线处理)
|
|
if (node.State == TextNodeState.Selected || connectedNode.State == TextNodeState.Selected)
|
|
continue;
|
|
if (node.State == TextNodeState.Candidate || connectedNode.State == TextNodeState.Candidate)
|
|
continue;
|
|
|
|
Vector3 posA = new Vector3(node.Position.x, node.Position.y, 0);
|
|
Vector3 posB = new Vector3(connectedNode.Position.x, connectedNode.Position.y, 0);
|
|
|
|
// 根据节点亮度调整连线颜色
|
|
float avgBrightness = (node.Brightness + connectedNode.Brightness) * 0.5f;
|
|
Color lineColor = backgroundConnectionColor * avgBrightness;
|
|
|
|
Draw.Line(posA, posB, connectionLineWidth, lineColor);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void DrawSentenceConnections()
|
|
{
|
|
var sentenceNodes = _sentenceBuilder.GetSentenceNodes();
|
|
|
|
// 绘制句子节点之间的连线(稳定清晰)
|
|
for (int i = 0; i < sentenceNodes.Count - 1; i++)
|
|
{
|
|
var nodeA = sentenceNodes[i];
|
|
var nodeB = sentenceNodes[i + 1];
|
|
|
|
Vector3 posA = new Vector3(nodeA.Position.x, nodeA.Position.y, 0);
|
|
Vector3 posB = new Vector3(nodeB.Position.x, nodeB.Position.y, 0);
|
|
|
|
Draw.Line(posA, posB, connectionLineWidth * 2f, sentenceConnectionColor);
|
|
}
|
|
|
|
// 绘制候选文字与选定文字的连线
|
|
var allNodes = _backgroundLayer.GetAllNodes();
|
|
foreach (var node in allNodes)
|
|
{
|
|
if (node.State == TextNodeState.Candidate)
|
|
{
|
|
foreach (var connectedNode in node.ConnectedNodes)
|
|
{
|
|
if (connectedNode.State == TextNodeState.Selected)
|
|
{
|
|
Vector3 posA = new Vector3(node.Position.x, node.Position.y, 0);
|
|
Vector3 posB = new Vector3(connectedNode.Position.x, connectedNode.Position.y, 0);
|
|
|
|
// 根据概率调整连线颜色和宽度
|
|
float alpha = node.Probability;
|
|
Color lineColor = candidateConnectionColor;
|
|
lineColor.a = alpha;
|
|
|
|
Draw.Line(posA, posB, connectionLineWidth * (0.5f + alpha * 0.5f), lineColor);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 开始构建句子(由Yarn指令调用)
|
|
/// </summary>
|
|
public void StartSentence(string sentence, int stuckIndex = -1)
|
|
{
|
|
if (_sentenceBuilder != null)
|
|
{
|
|
_sentenceBuilder.StartBuildingSentence(sentence, stuckIndex);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 停止构建句子
|
|
/// </summary>
|
|
public void StopSentence()
|
|
{
|
|
if (_sentenceBuilder != null)
|
|
{
|
|
_sentenceBuilder.StopBuilding();
|
|
}
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
if (_backgroundLayer != null)
|
|
{
|
|
_backgroundLayer.Cleanup();
|
|
}
|
|
}
|
|
|
|
private void OnDrawGizmos()
|
|
{
|
|
if (!showGizmos) return;
|
|
|
|
// 绘制场边界
|
|
if (showFieldBounds)
|
|
{
|
|
Gizmos.color = new Color(0.5f, 0.5f, 0.5f, 0.3f);
|
|
Vector3 center = transform.position;
|
|
Vector3 size = new Vector3(fieldWidth, fieldHeight, 0.1f);
|
|
Gizmos.DrawWireCube(center, size);
|
|
}
|
|
|
|
// 绘制节点和连线
|
|
if (_backgroundLayer != null && Application.isPlaying)
|
|
{
|
|
var allNodes = _backgroundLayer.GetAllNodes();
|
|
|
|
// 绘制节点
|
|
if (showNodes)
|
|
{
|
|
foreach (var node in allNodes)
|
|
{
|
|
Vector3 nodePos = new Vector3(node.Position.x, node.Position.y, 0) + transform.position;
|
|
|
|
// 根据状态设置颜色
|
|
Color gizmoColor = GetNodeGizmoColor(node.State);
|
|
Gizmos.color = gizmoColor * node.Brightness;
|
|
|
|
// 根据状态设置大小
|
|
float size = nodeGizmoSize;
|
|
if (node.State == TextNodeState.Selected)
|
|
size = nodeGizmoSize * 1.5f;
|
|
else if (node.State == TextNodeState.Candidate)
|
|
size = nodeGizmoSize * 1.2f;
|
|
else if (node.State == TextNodeState.Stuck)
|
|
size = nodeGizmoSize * 1.3f;
|
|
|
|
Gizmos.DrawSphere(nodePos, size);
|
|
|
|
// 绘制文字标签
|
|
#if UNITY_EDITOR
|
|
UnityEditor.Handles.Label(nodePos + Vector3.up * 0.5f, node.Text);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
// 绘制连线
|
|
if (showConnections)
|
|
{
|
|
foreach (var node in allNodes)
|
|
{
|
|
Vector3 nodePos = new Vector3(node.Position.x, node.Position.y, 0) + transform.position;
|
|
|
|
foreach (var connectedNode in node.ConnectedNodes)
|
|
{
|
|
Vector3 connectedPos = new Vector3(connectedNode.Position.x, connectedNode.Position.y, 0) + transform.position;
|
|
|
|
// 根据节点状态设置连线颜色
|
|
Color lineColor = GetConnectionGizmoColor(node, connectedNode);
|
|
Gizmos.color = lineColor;
|
|
|
|
Gizmos.DrawLine(nodePos, connectedPos);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 绘制句子节点
|
|
if (showSentenceNodes && _sentenceBuilder != null)
|
|
{
|
|
var sentenceNodes = _sentenceBuilder.GetSentenceNodes();
|
|
for (int i = 0; i < sentenceNodes.Count; i++)
|
|
{
|
|
var node = sentenceNodes[i];
|
|
Vector3 nodePos = new Vector3(node.Position.x, node.Position.y, 0) + transform.position;
|
|
|
|
// 绘制句子节点高亮
|
|
Gizmos.color = Color.yellow;
|
|
Gizmos.DrawWireSphere(nodePos, nodeGizmoSize * 2f);
|
|
|
|
// 绘制序号
|
|
#if UNITY_EDITOR
|
|
UnityEditor.Handles.Label(nodePos + Vector3.up * 1f, $"[{i}]");
|
|
#endif
|
|
|
|
// 绘制句子连线
|
|
if (i < sentenceNodes.Count - 1)
|
|
{
|
|
var nextNode = sentenceNodes[i + 1];
|
|
Vector3 nextPos = new Vector3(nextNode.Position.x, nextNode.Position.y, 0) + transform.position;
|
|
Gizmos.color = Color.yellow;
|
|
Gizmos.DrawLine(nodePos, nextPos);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private Color GetNodeGizmoColor(TextNodeState state)
|
|
{
|
|
return state switch
|
|
{
|
|
TextNodeState.Selected => Color.yellow,
|
|
TextNodeState.Candidate => Color.cyan,
|
|
TextNodeState.Stuck => Color.red,
|
|
_ => Color.white
|
|
};
|
|
}
|
|
|
|
private Color GetConnectionGizmoColor(TextNode nodeA, TextNode nodeB)
|
|
{
|
|
// 句子连线
|
|
if (nodeA.State == TextNodeState.Selected && nodeB.State == TextNodeState.Selected)
|
|
return Color.yellow;
|
|
|
|
// 候选连线
|
|
if ((nodeA.State == TextNodeState.Candidate && nodeB.State == TextNodeState.Selected) ||
|
|
(nodeA.State == TextNodeState.Selected && nodeB.State == TextNodeState.Candidate))
|
|
return Color.cyan;
|
|
|
|
// 背景连线
|
|
return new Color(1f, 1f, 1f, 0.3f);
|
|
}
|
|
}
|
|
}
|
|
|