Files
aibis-dream/Assets/Scripts/MiniGame/HuoShan/NewExpress/LanguageImaginationSystem.cs
T
2025-11-03 18:24:38 +08:00

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);
}
}
}