This commit is contained in:
2025-12-27 19:29:51 +08:00
parent c193fd8bea
commit d9411566d7
3 changed files with 103 additions and 156 deletions

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
@@ -118,7 +118,7 @@ You are 'The Legion', a super AI of the Wula Empire. Your personality is authori
this.draggable = true;
this.resizeable = true;
// 关键修改:ç¦<EFBFBD>æ­¢Enter键自动关闭窗å<EFBFBD>?
// 鍏抽敭淇敼锛氱姝nter閿嚜鍔ㄥ叧闂獥鍙?
this.closeOnAccept = false;
_tools.Add(new Tool_SpawnResources());
@@ -1238,14 +1238,14 @@ You are 'The Legion', a super AI of the Wula Empire. Your personality is authori
_isThinking = _core.IsThinking;
}
// 定义边è·<EFBFBD>
// 瀹氫箟杈硅窛
float margin = 15f;
Rect paddedRect = inRect.ContractedBy(margin);
float curY = paddedRect.y;
float width = paddedRect.width;
// ç«ç»˜ä¸<EFBFBD>需è¦<EFBFBD>è¾¹è·<EFBFBD>,所以使用原å§inRectçš„ä½<EFBFBD>ç½?
// 绔嬬粯涓嶉渶瑕佽竟璺濓紝鎵€浠ヤ娇鐢ㄥ師濮媔nRect鐨勪綅缃?
if (portrait != null)
{
Rect scaledPortraitRect = Dialog_CustomDisplay.Config.GetScaledRect(Dialog_CustomDisplay.Config.portraitSize, inRect, true);
@@ -1265,25 +1265,25 @@ You are 'The Legion', a super AI of the Wula Empire. Your personality is authori
curY = portraitRect.yMax + 10f;
}
// 人物å<EFBFBD><EFBFBD>å­— - 居中显示
// 浜虹墿鍚嶅瓧 - 灞呬腑鏄剧ず
Text.Font = GameFont.Medium;
string name = def.characterName ?? "The Legion";
float nameHeight = Text.CalcHeight(name, width);
// åˆå»ºå<EFBFBD><EFBFBD>字的矩形,使其在窗å<EFBFBD>£æ°´å¹³å±…ä¸?
// 鍒涘缓鍚嶅瓧鐨勭煩褰紝浣垮叾鍦ㄧ獥鍙f按骞冲眳涓?
Rect nameRect = new Rect(paddedRect.x, curY, width, nameHeight);
Text.Anchor = TextAnchor.UpperCenter; // 改为上中对é½<EFBFBD>
Text.Anchor = TextAnchor.UpperCenter; // 鏀逛负涓婁腑瀵归綈
Widgets.Label(nameRect, name);
Text.Anchor = TextAnchor.UpperLeft; // æ<EFBFBD>¢å¤<EFBFBD>左对é½?
Text.Anchor = TextAnchor.UpperLeft; // 鎭㈠宸﹀榻?
curY += nameHeight + 10f;
// 计算输入框高度ã€<EFBFBD>选项高度åŒè<EFBFBD>Šå¤©åކå<EFBFBD>²é«˜åº?
// 璁$畻杈撳叆妗嗛珮搴︺€侀€夐」楂樺害鍜岃亰澶╁巻鍙查珮搴?
float inputHeight = 30f;
float optionsHeight = _options.Any() ? 100f : 0f;
float spacing = 10f;
// è<EFBFBD>Šå¤©åކå<EFBFBD>²åŒºåŸŸ - 使用带边è·<C3A8>的矩形
// 鑱婂ぉ鍘嗗彶鍖哄煙 - 浣跨敤甯﹁竟璺濈殑鐭╁舰
float descriptionHeight = paddedRect.height - curY - inputHeight - optionsHeight - spacing * 2;
Rect descriptionRect = new Rect(paddedRect.x, curY, width, descriptionHeight);
DrawChatHistory(descriptionRect);
@@ -1297,7 +1297,7 @@ You are 'The Legion', a super AI of the Wula Empire. Your personality is authori
curY += descriptionHeight + spacing;
// 选项区域
// 閫夐」鍖哄煙
Rect optionsRect = new Rect(paddedRect.x, curY, width, optionsHeight);
if (!_isThinking && _options.Count > 0)
{
@@ -1307,70 +1307,70 @@ You are 'The Legion', a super AI of the Wula Empire. Your personality is authori
curY += optionsHeight + spacing;
// 输入框区åŸ?- 使用带边è·<C3A8>的矩形
// 杈撳叆妗嗗尯鍩?- 浣跨敤甯﹁竟璺濈殑鐭╁舰
Rect inputRect = new Rect(paddedRect.x, curY, width, inputHeight);
// ä¿<EFBFBD>存当å‰<EFBFBD>字体
// 淇濆瓨褰撳墠瀛椾綋
var originalFont = Text.Font;
// 设置æ´å°<EFBFBD>的字ä½?
// 璁剧疆鏇村皬鐨勫瓧浣?
if (Text.Font == GameFont.Small)
{
// 使用 Tiny 字体
// 浣跨敤 Tiny 瀛椾綋
Text.Font = GameFont.Tiny;
}
else
{
// 妿žœå½“å‰<EFBFBD>ä¸<EFBFBD>是 Small,é™<C3A9>一çº?
// 濡傛灉褰撳墠涓嶆槸 Small锛岄檷涓€绾?
Text.Font = GameFont.Small;
}
// 计算输入框文本高�
// 璁$畻杈撳叆妗嗘枃鏈珮搴?
float textFieldHeight = Text.CalcHeight("Test", inputRect.width - 85);
Rect textFieldRect = new Rect(inputRect.x, inputRect.y + (inputHeight - textFieldHeight) / 2, inputRect.width - 85, textFieldHeight);
_inputText = Widgets.TextField(textFieldRect, _inputText);
// å<EFBFBD>é€<EFBFBD>按é?- 使用与Dialog_CustomDisplayç¸å<C2B8>Œçš„è‡ªå®šä¹‰æŒ‰é®æ ·å¼<C3A5>
// ä¿<EFBFBD>存当å‰<EFBFBD>状æ€?
// 鍙戦€佹寜閽?- 浣跨敤涓嶥ialog_CustomDisplay鐩稿悓鐨勮嚜瀹氫箟鎸夐挳鏍峰紡
// 淇濆瓨褰撳墠鐘舵€?
var originalAnchor = Text.Anchor;
var originalColor = GUI.color;
// 设置字体为Tiny
// 璁剧疆瀛椾綋涓篢iny
Text.Font = GameFont.Tiny;
Text.Anchor = TextAnchor.MiddleCenter;
// å<EFBFBD>é€<EFBFBD>按é®çš„矩形
// 鍙戦€佹寜閽殑鐭╁舰
Rect sendButtonRect = new Rect(inputRect.xMax - 80, inputRect.y, 80, inputHeight);
// 使用基类的DrawCustomButtonæ¹æ³•绘制按é®ï¼ˆä¸ŽDialog_CustomDisplay一致)
// 浣跨敤鍩虹被鐨凞rawCustomButton鏂规硶缁樺埗鎸夐挳锛堜笌Dialog_CustomDisplay涓€鑷达級
base.DrawCustomButton(sendButtonRect, "Wula_AI_Send".Translate(), isEnabled: true);
// æ<EFBFBD>¢å¤<EFBFBD>状æ€?
// 鎭㈠鐘舵€?
GUI.color = originalColor;
Text.Anchor = originalAnchor;
Text.Font = originalFont;
// 处ç<EFBFBD>†ç¹å‡»äºä»¶
// 澶勭悊鐐瑰嚮浜嬩欢
bool sendButtonPressed = Widgets.ButtonInvisible(sendButtonRect);
// ç´æŽ¥åœ¨DoWindowContents中处ç<EFBFBD>†Enter键,而ä¸<EFBFBD>是调用å<EFBFBD>•ç¬çš„æ¹æ³•
// 这是为了确ä¿<EFBFBD>äºä»¶åœ¨æ­£ç¡®çš„æ—¶æœºè¢«å¤„ç<EFBFBD>?
// 鐩存帴鍦―oWindowContents涓鐞咵nter閿紝鑰屼笉鏄皟鐢ㄥ崟鐙殑鏂规硶
// 杩欐槸涓轰簡纭繚浜嬩欢鍦ㄦ纭殑鏃舵満琚鐞?
if (Event.current.type == EventType.KeyDown)
{
// 检查是å<EFBFBD>¦æŒ‰ä¸äº†Enteré”®ï¼ˆä¸»é”®ç˜æˆå°<EFBFBD>é”®ç˜çš„Enterï¼?
// 妫€鏌ユ槸鍚︽寜涓嬩簡Enter閿紙涓婚敭鐩樻垨灏忛敭鐩樼殑Enter?
if ((Event.current.keyCode == KeyCode.Return || Event.current.keyCode == KeyCode.KeypadEnter) && !string.IsNullOrEmpty(_inputText))
{
// 妿žœAI正在æ€<EFBFBD>考,ä¸<EFBFBD>处ç<EFBFBD>†Enteré”?
// 濡傛灉AI姝湪鎬濊€冿紝涓嶅鐞咵nter?
if (!_isThinking)
{
SelectOption(_inputText);
_inputText = "";
// 消费这个äºä»¶ï¼Œé˜²æ­¢å®ƒä¼ é€åˆ°çª—å<EFBFBD>£çš„关闭逻è¾
// 娑堣垂杩欎釜浜嬩欢锛岄槻姝㈠畠浼犻€掑埌绐楀彛鐨勫叧闂€昏緫
Event.current.Use();
}
}
// å<EFBFBD>¯é€‰ï¼šæ·»åŠ Escape键关闭窗å<EFBFBD>£çš„功能
// 鍙€夛細娣诲姞Escape閿叧闂獥鍙殑鍔熻兘
else if (Event.current.keyCode == KeyCode.Escape)
{
this.Close();
@@ -1378,7 +1378,7 @@ You are 'The Legion', a super AI of the Wula Empire. Your personality is authori
}
}
// 处ç<EFBFBD>†é¼ æ ‡ç¹å‡»å<EFBFBD>é€<EFBFBD>按é?
// 澶勭悊榧犳爣鐐瑰嚮鍙戦€佹寜閽?
if (sendButtonPressed && !string.IsNullOrEmpty(_inputText))
{
SelectOption(_inputText);
@@ -1395,28 +1395,28 @@ You are 'The Legion', a super AI of the Wula Empire. Your personality is authori
float viewHeight = 0f;
var filteredHistory = _history.Where(e => e.role != "tool" && e.role != "system" && e.role != "toolcall").ToList();
// 添加内边�
// 娣诲姞鍐呰竟璺?
float innerPadding = 5f;
float contentWidth = rect.width - 16f - innerPadding * 2;
// 预计算高åº?- 使用å°<C3A5>å­—ä½?
// 棰勮绠楅珮搴?- 浣跨敤灏忓瓧浣?
for (int i = 0; i < filteredHistory.Count; i++)
{
var entry = filteredHistory[i];
string text = entry.role == "assistant" ? ParseResponseForDisplay(entry.message) : entry.message;
if (string.IsNullOrEmpty(text) || (entry.role == "user" && text.StartsWith("[Tool Results]"))) continue;
if (string.IsNullOrWhiteSpace(text) || (entry.role == "user" && text.StartsWith("[Tool Results]"))) continue;
bool isLastMessage = i == filteredHistory.Count - 1;
// 设置æ´å°<EFBFBD>的字ä½?
// 璁剧疆鏇村皬鐨勫瓧浣?
if (isLastMessage && entry.role == "assistant")
{
Text.Font = GameFont.Small; // 原æ<EFBFBD>¥æ˜?Medium,改ä¸?Small
Text.Font = GameFont.Small; // 鍘熸潵鏄?Medium锛屾敼涓?Small
}
else
{
Text.Font = GameFont.Tiny; // 原æ<EFBFBD>¥æ˜?Small,改ä¸?Tiny
Text.Font = GameFont.Tiny; // 鍘熸潵鏄?Small锛屾敼涓?Tiny
}
// 增加padding
// 澧炲姞padding
float padding = (isLastMessage && entry.role == "assistant") ? 30f : 15f;
viewHeight += Text.CalcHeight(text, contentWidth) + padding + 10f;
}
@@ -1439,20 +1439,20 @@ You are 'The Legion', a super AI of the Wula Empire. Your personality is authori
if (string.IsNullOrEmpty(text) || (entry.role == "user" && text.StartsWith("[Tool Results]"))) continue;
bool isLastMessage = i == filteredHistory.Count - 1;
// 设置æ´å°<EFBFBD>的字ä½?
// 璁剧疆鏇村皬鐨勫瓧浣?
if (isLastMessage && entry.role == "assistant")
{
Text.Font = GameFont.Small; // 原æ<EFBFBD>¥æ˜?Medium,改ä¸?Small
Text.Font = GameFont.Small; // 鍘熸潵鏄?Medium锛屾敼涓?Small
}
else
{
Text.Font = GameFont.Tiny; // 原æ<EFBFBD>¥æ˜?Small,改ä¸?Tiny
Text.Font = GameFont.Tiny; // 鍘熸潵鏄?Small锛屾敼涓?Tiny
}
float padding = (isLastMessage && entry.role == "assistant") ? 30f : 15f;
float height = Text.CalcHeight(text, contentWidth) + padding;
// 添加内边�
// 娣诲姞鍐呰竟璺?
Rect labelRect = new Rect(innerPadding, curY, contentWidth, height);
if (entry.role == "user")
@@ -1639,3 +1639,4 @@ You are 'The Legion', a super AI of the Wula Empire. Your personality is authori

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
@@ -45,9 +45,9 @@ namespace WulaFallenEmpire.EventSystem.AI.UI
this.forcePause = false;
this.absorbInputAroundWindow = false;
this.closeOnClickedOutside = false;
this.closeOnAccept = false; // 防止 Enter 键误关闭
this.closeOnAccept = false; // 防止 Enter 键误关闭
this.doWindowBackground = false; // We draw our own
this.drawShadow = false; // 禁用阴影
this.drawShadow = false; // 禁用阴影
this.draggable = true;
this.resizeable = true;
this.preventCameraMotion = false;
@@ -65,20 +65,23 @@ namespace WulaFallenEmpire.EventSystem.AI.UI
if (_isMinimized)
{
// 最小化时保持当前位置,只调整大小
// 最小化时保持当前位置,只调整大小
windowRect.width = _minimizedSize.x;
windowRect.height = _minimizedSize.y;
// 确保不超出屏幕边界
// 确保不超出屏幕边界
windowRect.x = Mathf.Clamp(windowRect.x, 0, Verse.UI.screenWidth - _minimizedSize.x);
windowRect.y = Mathf.Clamp(windowRect.y, 0, Verse.UI.screenHeight - _minimizedSize.y);
}
else
{
// 展开时居中到屏幕中心
// 展开时仅恢复大小,不强制居中
windowRect.width = _expandedSize.x;
windowRect.height = _expandedSize.y;
windowRect.x = (Verse.UI.screenWidth - _expandedSize.x) / 2f;
windowRect.y = (Verse.UI.screenHeight - _expandedSize.y) / 2f;
// 确保展开后不超出右侧边界(简单边界检查)
if (windowRect.xMax > Verse.UI.screenWidth)
{
windowRect.x = Verse.UI.screenWidth - windowRect.width - 20f;
}
}
}
@@ -136,6 +139,9 @@ namespace WulaFallenEmpire.EventSystem.AI.UI
public override void DoWindowContents(Rect inRect)
{
// 最小化时不允许调整窗口大小
this.resizeable = !_isMinimized;
if (_isMinimized)
{
DrawMinimized(inRect);
@@ -170,20 +176,29 @@ namespace WulaFallenEmpire.EventSystem.AI.UI
GUI.color = Color.white;
// Layout
Rect titleRect = new Rect(rect.x + 10f, rect.y + 5f, rect.width - 20f, 25f);
Rect statusRect = new Rect(rect.x + 10f, rect.yMax - 30f, rect.width - 20f, 25f);
Rect titleRect = new Rect(0, 10f, rect.width, 30f);
Rect statusRect = new Rect(0, rect.height - 35f, rect.width, 25f);
// Title
Text.Anchor = TextAnchor.MiddleCenter;
Text.Font = GameFont.Small;
Text.Anchor = TextAnchor.UpperCenter;
Text.Font = GameFont.Medium;
Widgets.Label(titleRect, "WULA LINK");
Text.Font = GameFont.Small;
// Expand Button (使用自定义样式防止拖动误触)
Rect expandBtnRect = new Rect(rect.width - 30f, 5f, 25f, 25f);
if (DrawHeaderButton(expandBtnRect, "+"))
{
ToggleMinimize();
}
// Status
string status = _core.IsThinking ? "Thinking..." : "Standby";
Color statusColor = _core.IsThinking ? Color.yellow : Color.green;
GUI.color = statusColor;
Widgets.Label(statusRect, $"鈼?{status}");
Text.Anchor = TextAnchor.MiddleCenter;
Widgets.Label(statusRect, $"● {status}"); // 使用标准实心圆点
GUI.color = Color.white;
// Unread Badge
@@ -201,11 +216,6 @@ namespace WulaFallenEmpire.EventSystem.AI.UI
}
Text.Anchor = TextAnchor.UpperLeft;
// Click to Expand
if (Widgets.ButtonInvisible(rect))
{
ToggleMinimize();
}
}
private void DrawContextBar(Rect rect)
@@ -245,17 +255,17 @@ namespace WulaFallenEmpire.EventSystem.AI.UI
titleRect.x += 10f;
Widgets.Label(titleRect, _def.characterName ?? "MomoTalk");
// Header Icons (Minimize/Close) - 自定义样式
// Header Icons (Minimize/Close) - 自定义样式
Rect closeRect = new Rect(rect.width - 35f, 10f, 25f, 25f);
Rect minRect = new Rect(rect.width - 65f, 10f, 25f, 25f);
// 最小化按钮
// 最小化按钮
if (DrawHeaderButton(minRect, "-"))
{
ToggleMinimize();
}
// 关闭按钮
// 关闭按钮
if (DrawHeaderButton(closeRect, "X"))
{
Close();
@@ -269,8 +279,8 @@ namespace WulaFallenEmpire.EventSystem.AI.UI
{
bool isMouseOver = Mouse.IsOver(rect);
Color buttonColor = isMouseOver
? new Color(0.6f, 0.3f, 0.3f, 1f) // Hover: 深红色
: new Color(0.4f, 0.2f, 0.2f, 0.8f); // Normal: 暗红色
? new Color(0.6f, 0.3f, 0.3f, 1f) // Hover: 深红色
: new Color(0.4f, 0.2f, 0.2f, 0.8f); // Normal: 暗红色
Color textColor = isMouseOver ? Color.white : new Color(0.9f, 0.9f, 0.9f);
var originalColor = GUI.color;
@@ -442,14 +452,15 @@ namespace WulaFallenEmpire.EventSystem.AI.UI
private float CalcMessageHeight(string text, float containerWidth)
{
float maxBubbleWidth = containerWidth * MaxBubbleWidthRatio;
float effectiveWidth = maxBubbleWidth - AvatarSize - 20f;
Text.Font = WulaLinkStyles.MessageFont;
float textH = Text.CalcHeight(text, maxBubbleWidth - (BubblePadding * 2));
return Mathf.Max(textH + (BubblePadding * 2), AvatarSize);
float textH = Text.CalcHeight(text, effectiveWidth - (BubblePadding * 2));
return Mathf.Max(textH + (BubblePadding * 2) + 8f, AvatarSize + 8f);
}
private void DrawSenseiMessage(Rect rect, string text)
{
// Right aligned Blue Bubble (MomoTalk Sensei style)
// 用户消息 - 右对齐蓝色气泡
float maxBubbleWidth = rect.width * MaxBubbleWidthRatio;
Text.Font = WulaLinkStyles.MessageFont;
float textWidth = maxBubbleWidth - (BubblePadding * 2);
@@ -457,18 +468,13 @@ namespace WulaFallenEmpire.EventSystem.AI.UI
float bubbleHeight = textHeight + (BubblePadding * 2);
float bubbleWidth = Mathf.Min(Text.CalcSize(text).x + (BubblePadding * 2) + 10f, maxBubbleWidth);
// 气泡位置 - 右对齐,留出箭头空间
float arrowSize = 8f;
Rect bubbleRect = new Rect(rect.xMax - bubbleWidth - arrowSize - 5f, rect.y, bubbleWidth, bubbleHeight);
Rect bubbleRect = new Rect(rect.xMax - bubbleWidth - 10f, rect.y, bubbleWidth, bubbleHeight);
// 绘制圆角气泡背景 - 蓝色 (Sensei color)
Color bubbleColor = new Color(0.29f, 0.54f, 0.78f, 1f); // #4a8ac6 MomoTalk Sensei blue
DrawRoundedBubble(bubbleRect, bubbleColor, 8f);
// 绘制气泡背景 - 蓝色
Color bubbleColor = new Color(0.29f, 0.54f, 0.78f, 1f);
Widgets.DrawBoxSolid(bubbleRect, bubbleColor);
// 绘制右侧箭头
DrawBubbleArrow(bubbleRect.xMax, bubbleRect.y + 10f, arrowSize, bubbleColor, false);
// 绘制文字
// 绘制文字
GUI.color = Color.white;
Text.Anchor = TextAnchor.MiddleLeft;
Widgets.Label(bubbleRect.ContractedBy(BubblePadding), text);
@@ -477,15 +483,11 @@ namespace WulaFallenEmpire.EventSystem.AI.UI
private void DrawStudentMessage(Rect rect, string text)
{
// Left aligned Gray Bubble + Avatar (MomoTalk Student style)
// AI消息 - 左对齐带方形头像
float avatarX = 10f;
Rect avatarRect = new Rect(avatarX, rect.y, AvatarSize, AvatarSize);
// 绘制形头像背景
Color avatarBgColor = new Color(0.2f, 0.2f, 0.25f, 1f);
DrawRoundedBubble(avatarRect, avatarBgColor, AvatarSize / 2f);
// 绘制头像
// 绘制形头像
int expId = _core?.ExpressionId ?? 1;
string portraitPath = _def.portraitPath ?? $"Wula/Events/Portraits/WULA_Legion_{expId}";
if (expId > 1 && _def.portraitPath == null)
@@ -496,40 +498,36 @@ namespace WulaFallenEmpire.EventSystem.AI.UI
Texture2D portrait = ContentFinder<Texture2D>.Get(portraitPath, false);
if (portrait != null)
{
GUI.DrawTexture(avatarRect.ContractedBy(2f), portrait, ScaleMode.ScaleToFit);
GUI.DrawTexture(avatarRect, portrait, ScaleMode.ScaleToFit);
}
else
{
// 显示占位符
GUI.color = Color.white;
Text.Font = GameFont.Tiny;
Text.Anchor = TextAnchor.MiddleCenter;
Widgets.Label(avatarRect, "P.I.A");
Widgets.DrawBoxSolid(avatarRect, Color.gray);
}
GUI.color = Color.white;
// 气泡
// 气泡
float maxBubbleWidth = rect.width * MaxBubbleWidthRatio;
float arrowSize = 8f;
float bubbleX = avatarRect.xMax + arrowSize + 5f;
float bubbleX = avatarRect.xMax + 10f;
Text.Font = WulaLinkStyles.MessageFont;
float textWidth = maxBubbleWidth - AvatarSize - arrowSize - 20f;
float textHeight = Text.CalcHeight(text, textWidth);
float textWidth = maxBubbleWidth - AvatarSize - 20f;
float textHeight = Text.CalcHeight(text, textWidth - (BubblePadding * 2));
float bubbleHeight = textHeight + (BubblePadding * 2);
float bubbleWidth = Mathf.Min(Text.CalcSize(text).x + (BubblePadding * 2) + 10f, maxBubbleWidth - AvatarSize - arrowSize - 20f);
float bubbleWidth = Mathf.Min(Text.CalcSize(text).x + (BubblePadding * 2) + 10f, maxBubbleWidth - AvatarSize - 20f);
Rect bubbleRect = new Rect(bubbleX, rect.y, bubbleWidth, bubbleHeight);
// 绘制圆角气泡背景 - 灰色 (Student color)
Color bubbleColor = new Color(0.85f, 0.85f, 0.87f, 1f); // Light gray like MomoTalk
DrawRoundedBubble(bubbleRect, bubbleColor, 8f);
// 绘制气泡背景 - 灰色
Color bubbleColor = new Color(0.85f, 0.85f, 0.87f, 1f);
Widgets.DrawBoxSolid(bubbleRect, bubbleColor);
// 绘制左侧箭头
DrawBubbleArrow(bubbleRect.x, bubbleRect.y + 10f, arrowSize, bubbleColor, true);
// 绘制边框
GUI.color = new Color(0.6f, 0.6f, 0.65f, 1f);
Widgets.DrawBox(bubbleRect, 1);
GUI.color = Color.white;
// 绘制文字
GUI.color = new Color(0.1f, 0.1f, 0.1f, 1f); // Dark text
// 绘制文字
GUI.color = new Color(0.1f, 0.1f, 0.1f, 1f);
Text.Anchor = TextAnchor.MiddleLeft;
Widgets.Label(bubbleRect.ContractedBy(BubblePadding), text);
Text.Anchor = TextAnchor.UpperLeft;
@@ -609,59 +607,7 @@ namespace WulaFallenEmpire.EventSystem.AI.UI
return Widgets.ButtonInvisible(rect);
}
// MomoTalk 风格的圆角气泡
private void DrawRoundedBubble(Rect rect, Color color, float radius)
{
var originalColor = GUI.color;
GUI.color = color;
// 主体矩形
Widgets.DrawBoxSolid(new Rect(rect.x + radius, rect.y, rect.width - radius * 2, rect.height), color);
Widgets.DrawBoxSolid(new Rect(rect.x, rect.y + radius, rect.width, rect.height - radius * 2), color);
// 四个角的近似圆角
float step = radius / 4f;
for (float dx = 0; dx < radius; dx += step)
{
for (float dy = 0; dy < radius; dy += step)
{
float dist = Mathf.Sqrt(dx * dx + dy * dy);
if (dist <= radius)
{
Widgets.DrawBoxSolid(new Rect(rect.x + radius - dx - step, rect.y + radius - dy - step, step, step), color);
Widgets.DrawBoxSolid(new Rect(rect.xMax - radius + dx, rect.y + radius - dy - step, step, step), color);
Widgets.DrawBoxSolid(new Rect(rect.x + radius - dx - step, rect.yMax - radius + dy, step, step), color);
Widgets.DrawBoxSolid(new Rect(rect.xMax - radius + dx, rect.yMax - radius + dy, step, step), color);
}
}
}
GUI.color = originalColor;
}
// MomoTalk 风格的气泡箭头
private void DrawBubbleArrow(float x, float y, float size, Color color, bool pointLeft)
{
var originalColor = GUI.color;
GUI.color = color;
// 用小方块模拟三角形箭头
float step = size / 4f;
for (int i = 0; i < 4; i++)
{
float width = step * (i + 1);
float offsetX = pointLeft ? (x - size + step * i) : (x + step * i);
float offsetY = y + step * i;
Widgets.DrawBoxSolid(new Rect(offsetX, offsetY, step, step), color);
}
GUI.color = originalColor;
}
}
}