This commit is contained in:
2025-12-25 16:23:38 +08:00
parent 58233d9909
commit e3ffa7f920
6 changed files with 161 additions and 142 deletions

Binary file not shown.

Binary file not shown.

View File

@@ -180,14 +180,14 @@ namespace ArachnaeSwarm
var configs = IncubationConfigs;
if (configs.Count == 0) return null;
// 初始化选择
// 如果未选择返回null和孵化池一样的行为
if (selectedIndex == -1)
{
selectedIndex = Mathf.Clamp(Props.defaultIndex, 0, configs.Count - 1);
return null;
}
if (selectedIndex < 0 || selectedIndex >= configs.Count)
selectedIndex = 0;
return null;
return configs[selectedIndex];
}

View File

@@ -1,5 +1,5 @@
// File: Gizmo_EquipmentIncubationProgress.cs
// 装备孵化进度 Gizmo - 与 Gizmo_IncubationProgress 样式完全一致
// 双向进度 Gizmo - 品质向左,进度向右(装备孵化版)
using System.Collections.Generic;
using RimWorld;
using UnityEngine;
@@ -12,14 +12,13 @@ namespace ArachnaeSwarm
{
private readonly Building_EquipmentOotheca building;
// 尺寸常量(与 Gizmo_IncubationProgress 相同)
// 尺寸常量
private const float Width = 180f;
private const float BarHeight = 14f;
private const float LabelHeight = 14f;
private const float BarHeight = 18f;
private const float Spacing = 4f;
private const float Padding = 8f;
// 进度条材质(与 Gizmo_IncubationProgress 相同)
// 进度条材质
private static readonly Texture2D IncubationBarTex = SolidColorMaterials.NewSolidColorTexture(new Color(0.2f, 0.7f, 0.2f, 0.8f));
private static readonly Texture2D QualityBarTex = SolidColorMaterials.NewSolidColorTexture(new Color(0.2f, 0.5f, 0.9f, 0.8f));
private static readonly Texture2D EmptyBarTex = SolidColorMaterials.NewSolidColorTexture(new Color(0.1f, 0.1f, 0.1f, 0.5f));
@@ -37,11 +36,10 @@ namespace ArachnaeSwarm
public override GizmoResult GizmoOnGUI(Vector2 topLeft, float maxWidth, GizmoRenderParms parms)
{
// 主矩形区域
Rect rect = new Rect(topLeft.x, topLeft.y - 25f, GetWidth(maxWidth), 100f);
// 主矩形区域 (75px高度)
Rect rect = new Rect(topLeft.x, topLeft.y, GetWidth(maxWidth), 75f);
Widgets.DrawWindowBackground(rect);
// 内部区域
Rect innerRect = rect.ContractedBy(Padding);
float curY = innerRect.y;
@@ -50,7 +48,7 @@ namespace ArachnaeSwarm
bool hasLarva = building.assignedLarva != null;
var config = building.EquipmentIncubatorData?.SelectedConfig;
// === 标题(可点击切换目标) ===
// === 标题(可点击切换目标) ===
Text.Font = GameFont.Small;
Rect titleRect = new Rect(innerRect.x, curY, innerRect.width, Text.LineHeight);
@@ -60,13 +58,12 @@ namespace ArachnaeSwarm
else if (config != null)
title = config.thingDef.LabelCap;
else
title = "选择生产目标...";
title = "ARA_Menu_SelectProductionTarget".Translate();
// 标题按钮(只有非孵化状态可点击)
bool canSwitch = !isIncubating && !hasLarva && building.EquipmentIncubatorData?.IncubationConfigs?.Count > 0;
if (canSwitch)
{
// 绘制按钮背景
if (Mouse.IsOver(titleRect))
{
Widgets.DrawHighlight(titleRect);
@@ -77,9 +74,8 @@ namespace ArachnaeSwarm
ShowTargetSwitchMenu();
}
// 带下划线的标题(表示可点击)
GUI.color = new Color(0.7f, 0.9f, 1f);
Widgets.Label(titleRect, title.Truncate(titleRect.width - 10f) + " ▼");
Widgets.Label(titleRect, title.Truncate(titleRect.width - 20f) + " ▼");
GUI.color = Color.white;
}
else
@@ -88,42 +84,85 @@ namespace ArachnaeSwarm
}
curY += Text.LineHeight + Spacing;
// === 内容绘制 ===
// === 双向进度条区域 ===
if (isIncubating)
{
// 孵化进度标签
DrawLabeledProgressBar(ref curY, innerRect.x, innerRect.width,
"孵化进度:", building.IncubationProgress, IncubationBarTex);
// 标签行:品质进度: :孵化进度
Text.Font = GameFont.Tiny;
Rect labelRect = new Rect(innerRect.x, curY, innerRect.width, 14f);
curY += Spacing;
GUI.color = new Color(0.6f, 0.7f, 0.9f);
Text.Anchor = TextAnchor.MiddleLeft;
Widgets.Label(new Rect(labelRect.x, labelRect.y, labelRect.width / 2f, labelRect.height),
"ARA_Label_Quality".Translate());
// 品质进度标签
DrawLabeledProgressBar(ref curY, innerRect.x, innerRect.width,
"品质进度:", building.QualityPercent, QualityBarTex);
GUI.color = new Color(0.6f, 0.9f, 0.6f);
Text.Anchor = TextAnchor.MiddleRight;
Widgets.Label(new Rect(labelRect.x + labelRect.width / 2f, labelRect.y, labelRect.width / 2f, labelRect.height),
"ARA_Label_Progress".Translate());
Text.Anchor = TextAnchor.UpperLeft;
GUI.color = Color.white;
curY += 14f;
// 双向进度条
Rect barRect = new Rect(innerRect.x, curY, innerRect.width, BarHeight);
float midX = barRect.x + barRect.width / 2f;
float halfWidth = barRect.width / 2f;
// 背景
GUI.DrawTexture(barRect, EmptyBarTex);
// 品质进度(向左)
float qualityWidth = halfWidth * building.QualityPercent;
Rect qualityRect = new Rect(midX - qualityWidth, barRect.y, qualityWidth, barRect.height);
GUI.DrawTexture(qualityRect, QualityBarTex);
// 孵化进度(向右)
float progressWidth = halfWidth * building.IncubationProgress;
Rect progressRect = new Rect(midX, barRect.y, progressWidth, barRect.height);
GUI.DrawTexture(progressRect, IncubationBarTex);
// 中线
Widgets.DrawLineVertical(midX, barRect.y, barRect.height);
// 进度条边框
Widgets.DrawBox(barRect, 1);
// Tooltip
string tooltip = GetTooltip();
TooltipHandler.TipRegion(barRect, tooltip);
}
else if (hasLarva)
{
Text.Font = GameFont.Tiny;
GUI.color = new Color(0.9f, 0.9f, 0.5f);
string statusText = building.larvaOperateTicksRemaining > 0 ? "幼虫激活中..." : "幼虫赶路中...";
string statusText = building.larvaOperateTicksRemaining > 0
? "ARA_Status_LarvaActivating".Translate()
: "ARA_Status_LarvaOnTheWay".Translate();
Widgets.Label(new Rect(innerRect.x, curY, innerRect.width, 30f), statusText);
GUI.color = Color.white;
}
else
{
// 无目标或等待状态
Text.Font = GameFont.Tiny;
GUI.color = new Color(0.7f, 0.7f, 0.7f);
string statusText = (config != null && config.IsResearchComplete) ? "就绪 - 点击上方切换目标" : "需要研究";
string statusText;
if (config == null)
statusText = "ARA_Status_SelectTarget".Translate();
else if (!config.IsResearchComplete)
statusText = "ARA_Status_NeedResearch".Translate();
else
statusText = "ARA_Status_Ready".Translate();
Widgets.Label(new Rect(innerRect.x, curY, innerRect.width, 20f), statusText);
curY += 20f;
GUI.color = Color.white;
}
// === 工具提示 ===
if (Mouse.IsOver(rect) && !Mouse.IsOver(titleRect))
// 工具提示(整体)
if (Mouse.IsOver(rect) && !isIncubating)
{
Widgets.DrawHighlight(rect);
TooltipHandler.TipRegion(rect, GetTooltip());
}
Text.Font = GameFont.Small;
@@ -142,18 +181,17 @@ namespace ArachnaeSwarm
var cfg = configs[i];
int index = i;
// 获取物品图标
Texture2D icon = cfg.thingDef?.uiIcon;
string label = cfg.thingDef.LabelCap;
if (cfg.requiredResearch != null && !cfg.requiredResearch.IsFinished)
{
label += $" (需要: {cfg.requiredResearch.LabelCap})";
options.Add(new FloatMenuOption(label, null, icon, Color.white)); // 禁用但有图标
label += $" ({cfg.requiredResearch.LabelCap})";
options.Add(new FloatMenuOption(label, null, icon, Color.white));
}
else
{
label += $" ({cfg.daysRequired})";
label += $" ({cfg.DaysRequired}" + "ARA_Days".Translate() + ")";
options.Add(new FloatMenuOption(label, () =>
{
building.EquipmentIncubatorData.SwitchToConfig(index);
@@ -163,28 +201,6 @@ namespace ArachnaeSwarm
Find.WindowStack.Add(new FloatMenu(options));
}
// 带标签的进度条
private void DrawLabeledProgressBar(ref float curY, float x, float width, string label, float percent, Texture2D barTex)
{
// 标签
Text.Font = GameFont.Tiny;
GUI.color = new Color(0.8f, 0.8f, 0.8f);
Widgets.Label(new Rect(x, curY, width, LabelHeight), label);
GUI.color = Color.white;
curY += LabelHeight;
// 进度条
Rect barRect = new Rect(x, curY, width, BarHeight);
Widgets.FillableBar(barRect, percent, barTex, EmptyBarTex, true);
// 百分比文字
Text.Font = GameFont.Tiny;
Text.Anchor = TextAnchor.MiddleCenter;
Widgets.Label(barRect, percent.ToStringPercent("0"));
Text.Anchor = TextAnchor.UpperLeft;
curY += BarHeight;
}
private string GetTooltip()
{
@@ -193,36 +209,29 @@ namespace ArachnaeSwarm
if (isIncubating && building.incubatingThingDef != null)
{
// 孵化中状态
sb.AppendLine("【孵化中】");
sb.AppendLine("目标: " + building.incubatingThingDef.LabelCap);
sb.AppendLine("孵化进度: " + building.IncubationProgress.ToStringPercent());
sb.AppendLine("品质进度: " + building.QualityPercent.ToStringPercent());
sb.AppendLine("ARA_Tooltip_Incubating".Translate());
sb.AppendLine("ARA_Tooltip_Target".Translate(building.incubatingThingDef.LabelCap));
sb.AppendLine("ARA_Tooltip_Progress".Translate(building.IncubationProgress.ToStringPercent()));
sb.AppendLine("ARA_Tooltip_Quality".Translate(building.QualityPercent.ToStringPercent(), ""));
float remaining = building.incubationDuration - building.incubationProgress;
if (remaining > 0)
{
sb.AppendLine("剩余时间: " + ((int)remaining).ToStringTicksToPeriod());
sb.AppendLine("ARA_Tooltip_Remaining".Translate(((int)remaining).ToStringTicksToPeriod()));
}
sb.AppendLine();
sb.AppendLine("速度: " + building.SpeedMultiplier.ToStringPercent());
sb.AppendLine("质量: " + building.QualityMultiplier.ToStringPercent());
}
else
{
// 空闲状态
var config = building.EquipmentIncubatorData?.SelectedConfig;
if (config != null)
{
sb.AppendLine("【就绪】");
sb.AppendLine("目标: " + config.thingDef.LabelCap);
sb.AppendLine("孵化时间: " + config.daysRequired + " ");
sb.AppendLine("ARA_Tooltip_Ready".Translate());
sb.AppendLine("ARA_Tooltip_Target".Translate(config.thingDef.LabelCap));
sb.AppendLine("ARA_Tooltip_Duration".Translate(config.DaysRequired + " " + "ARA_Days".Translate()));
}
else
{
sb.AppendLine("【未选择目标】");
sb.AppendLine("点击上方标题选择生产目标");
sb.AppendLine("ARA_Tooltip_NoTarget".Translate());
}
}

View File

@@ -344,14 +344,14 @@ namespace ArachnaeSwarm
var configs = IncubationConfigs;
if (configs.Count == 0) return null;
// 初始化选择
// 如果未选择返回null和孵化池一样的行为
if (selectedIndex == -1)
{
selectedIndex = Mathf.Clamp(Props.defaultIndex, 0, configs.Count - 1);
return null;
}
if (selectedIndex < 0 || selectedIndex >= configs.Count)
selectedIndex = 0;
return null;
return configs[selectedIndex];
}

View File

@@ -1,5 +1,5 @@
// File: Gizmo_IncubationProgress.cs
// 类似原版 Refuelable 的双进度条 Gizmo显示孵化进度和品质
// 双向进度条 Gizmo - 品质向左,进度向右
using System.Collections.Generic;
using RimWorld;
using UnityEngine;
@@ -14,8 +14,7 @@ namespace ArachnaeSwarm
// 尺寸常量
private const float Width = 180f;
private const float BarHeight = 14f;
private const float LabelHeight = 14f;
private const float BarHeight = 18f;
private const float Spacing = 4f;
private const float Padding = 8f;
@@ -37,11 +36,10 @@ namespace ArachnaeSwarm
public override GizmoResult GizmoOnGUI(Vector2 topLeft, float maxWidth, GizmoRenderParms parms)
{
// 主矩形区域
Rect rect = new Rect(topLeft.x, topLeft.y - 25f, GetWidth(maxWidth), 100f);
// 主矩形区域 (75px高度)
Rect rect = new Rect(topLeft.x, topLeft.y, GetWidth(maxWidth), 75f);
Widgets.DrawWindowBackground(rect);
// 内部区域
Rect innerRect = rect.ContractedBy(Padding);
float curY = innerRect.y;
@@ -50,7 +48,7 @@ namespace ArachnaeSwarm
bool hasLarva = ootheca.assignedLarva != null;
var config = ootheca.IncubatorData?.SelectedConfig;
// === 标题(可点击切换目标) ===
// === 标题(可点击切换目标) ===
Text.Font = GameFont.Small;
Rect titleRect = new Rect(innerRect.x, curY, innerRect.width, Text.LineHeight);
@@ -60,13 +58,12 @@ namespace ArachnaeSwarm
else if (config != null)
title = config.pawnKind.LabelCap;
else
title = "选择孵化目标...";
title = "ARA_Gizmo_SelectIncubationTarget".Translate();
// 标题按钮(只有非孵化状态可点击)
bool canSwitch = !isIncubating && !hasLarva && ootheca.IncubatorData?.IncubationConfigs?.Count > 0;
if (canSwitch)
{
// 绘制按钮背景
if (Mouse.IsOver(titleRect))
{
Widgets.DrawHighlight(titleRect);
@@ -77,9 +74,8 @@ namespace ArachnaeSwarm
ShowTargetSwitchMenu();
}
// 带下划线的标题(表示可点击)
GUI.color = new Color(0.7f, 0.9f, 1f);
Widgets.Label(titleRect, title.Truncate(titleRect.width - 10f) + " ▼");
Widgets.Label(titleRect, title.Truncate(titleRect.width - 20f) + " ▼");
GUI.color = Color.white;
}
else
@@ -88,42 +84,85 @@ namespace ArachnaeSwarm
}
curY += Text.LineHeight + Spacing;
// === 内容绘制 ===
// === 双向进度条区域 ===
if (isIncubating)
{
// 孵化进度标签
DrawLabeledProgressBar(ref curY, innerRect.x, innerRect.width,
"孵化进度:", ootheca.AdjustedProgressPercent, IncubationBarTex);
// 标签行:品质进度: :孵化进度
Text.Font = GameFont.Tiny;
Rect labelRect = new Rect(innerRect.x, curY, innerRect.width, 14f);
curY += Spacing;
GUI.color = new Color(0.6f, 0.7f, 0.9f);
Text.Anchor = TextAnchor.MiddleLeft;
Widgets.Label(new Rect(labelRect.x, labelRect.y, labelRect.width / 2f, labelRect.height),
"ARA_Label_Quality".Translate());
// 品质进度标签
DrawLabeledProgressBar(ref curY, innerRect.x, innerRect.width,
"品质进度:", ootheca.QualityPercent, QualityBarTex);
GUI.color = new Color(0.6f, 0.9f, 0.6f);
Text.Anchor = TextAnchor.MiddleRight;
Widgets.Label(new Rect(labelRect.x + labelRect.width / 2f, labelRect.y, labelRect.width / 2f, labelRect.height),
"ARA_Label_Progress".Translate());
Text.Anchor = TextAnchor.UpperLeft;
GUI.color = Color.white;
curY += 14f;
// 双向进度条
Rect barRect = new Rect(innerRect.x, curY, innerRect.width, BarHeight);
float midX = barRect.x + barRect.width / 2f;
float halfWidth = barRect.width / 2f;
// 背景
GUI.DrawTexture(barRect, EmptyBarTex);
// 品质进度(向左)
float qualityWidth = halfWidth * ootheca.QualityPercent;
Rect qualityRect = new Rect(midX - qualityWidth, barRect.y, qualityWidth, barRect.height);
GUI.DrawTexture(qualityRect, QualityBarTex);
// 孵化进度(向右)
float progressWidth = halfWidth * ootheca.AdjustedProgressPercent;
Rect progressRect = new Rect(midX, barRect.y, progressWidth, barRect.height);
GUI.DrawTexture(progressRect, IncubationBarTex);
// 中线
Widgets.DrawLineVertical(midX, barRect.y, barRect.height);
// 进度条边框
Widgets.DrawBox(barRect, 1);
// Tooltip
string tooltip = GetTooltip();
TooltipHandler.TipRegion(barRect, tooltip);
}
else if (hasLarva)
{
Text.Font = GameFont.Tiny;
GUI.color = new Color(0.9f, 0.9f, 0.5f);
string statusText = ootheca.larvaOperateTicksRemaining > 0 ? "幼虫激活中..." : "幼虫赶路中...";
string statusText = ootheca.larvaOperateTicksRemaining > 0
? "ARA_Status_LarvaActivating".Translate()
: "ARA_Status_LarvaOnTheWay".Translate();
Widgets.Label(new Rect(innerRect.x, curY, innerRect.width, 30f), statusText);
GUI.color = Color.white;
}
else
{
// 无目标或等待状态
Text.Font = GameFont.Tiny;
GUI.color = new Color(0.7f, 0.7f, 0.7f);
string statusText = (config != null && config.IsResearchComplete) ? "就绪 - 点击上方切换目标" : "需要研究";
string statusText;
if (config == null)
statusText = "ARA_Status_SelectTarget".Translate();
else if (!config.IsResearchComplete)
statusText = "ARA_Status_NeedResearch".Translate();
else
statusText = "ARA_Status_Ready".Translate();
Widgets.Label(new Rect(innerRect.x, curY, innerRect.width, 20f), statusText);
curY += 20f;
GUI.color = Color.white;
}
// === 工具提示 ===
if (Mouse.IsOver(rect) && !Mouse.IsOver(titleRect))
// 工具提示(整体)
if (Mouse.IsOver(rect) && !isIncubating)
{
Widgets.DrawHighlight(rect);
TooltipHandler.TipRegion(rect, GetTooltip());
}
Text.Font = GameFont.Small;
@@ -145,12 +184,12 @@ namespace ArachnaeSwarm
string label = cfg.pawnKind.LabelCap;
if (cfg.requiredResearch != null && !cfg.requiredResearch.IsFinished)
{
label += $" (需要: {cfg.requiredResearch.LabelCap})";
options.Add(new FloatMenuOption(label, null)); // 禁用
label += $" ({cfg.requiredResearch.LabelCap})";
options.Add(new FloatMenuOption(label, null));
}
else
{
label += $" ({cfg.daysRequired})";
label += $" ({cfg.daysRequired}" + "ARA_Days".Translate() + ")";
options.Add(new FloatMenuOption(label, () =>
{
ootheca.IncubatorData.SwitchToConfig(index);
@@ -160,28 +199,6 @@ namespace ArachnaeSwarm
Find.WindowStack.Add(new FloatMenu(options));
}
// 带标签的进度条
private void DrawLabeledProgressBar(ref float curY, float x, float width, string label, float percent, Texture2D barTex)
{
// 标签
Text.Font = GameFont.Tiny;
GUI.color = new Color(0.8f, 0.8f, 0.8f);
Widgets.Label(new Rect(x, curY, width, LabelHeight), label);
GUI.color = Color.white;
curY += LabelHeight;
// 进度条
Rect barRect = new Rect(x, curY, width, BarHeight);
Widgets.FillableBar(barRect, percent, barTex, EmptyBarTex, true);
// 百分比文字
Text.Font = GameFont.Tiny;
Text.Anchor = TextAnchor.MiddleCenter;
Widgets.Label(barRect, percent.ToStringPercent("0"));
Text.Anchor = TextAnchor.UpperLeft;
curY += BarHeight;
}
private string GetTooltip()
{
@@ -190,36 +207,29 @@ namespace ArachnaeSwarm
if (isIncubating && ootheca.incubatingPawnKind != null)
{
// 孵化中状态
sb.AppendLine("【孵化中】");
sb.AppendLine("目标: " + ootheca.incubatingPawnKind.LabelCap);
sb.AppendLine("孵化进度: " + ootheca.AdjustedProgressPercent.ToStringPercent());
sb.AppendLine("品质进度: " + ootheca.QualityPercent.ToStringPercent());
sb.AppendLine("ARA_Tooltip_Incubating".Translate());
sb.AppendLine("ARA_Tooltip_Target".Translate(ootheca.incubatingPawnKind.LabelCap));
sb.AppendLine("ARA_Tooltip_Progress".Translate(ootheca.AdjustedProgressPercent.ToStringPercent()));
sb.AppendLine("ARA_Tooltip_Quality".Translate(ootheca.QualityPercent.ToStringPercent(), ""));
float daysRemaining = ootheca.GetRemainingDays();
if (daysRemaining > 0 && daysRemaining < float.MaxValue)
{
sb.AppendLine("剩余时间: " + daysRemaining.ToString("F1") + " ");
sb.AppendLine("ARA_Tooltip_Remaining".Translate(daysRemaining.ToString("F1") + " " + "ARA_Days".Translate()));
}
sb.AppendLine();
sb.AppendLine("速度: " + ootheca.SpeedMultiplier.ToStringPercent());
sb.AppendLine("质量: " + ootheca.QualityMultiplier.ToStringPercent());
}
else
{
// 空闲状态
var config = ootheca.IncubatorData?.SelectedConfig;
if (config != null)
{
sb.AppendLine("【就绪】");
sb.AppendLine("目标: " + config.pawnKind.LabelCap);
sb.AppendLine("孵化时间: " + config.daysRequired + " 天");
sb.AppendLine("ARA_Tooltip_Ready".Translate());
sb.AppendLine("ARA_Tooltip_Target".Translate(config.pawnKind.LabelCap));
sb.AppendLine("ARA_Tooltip_Duration".Translate(config.daysRequired + " " + "ARA_Days".Translate()));
}
else
{
sb.AppendLine("【未选择目标】");
sb.AppendLine("点击上方标题选择孵化目标");
sb.AppendLine("ARA_Tooltip_NoTarget".Translate());
}
}