zc
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -227,4 +227,22 @@
|
||||
<!-- 营养液状态 -->
|
||||
<ARA_EquipmentIncubator.WaitingForNutrients>等待营养液...</ARA_EquipmentIncubator.WaitingForNutrients>
|
||||
<ARA_Consumed>已消耗</ARA_Consumed>
|
||||
|
||||
<!-- 双向进度条 Gizmo 翻译键 -->
|
||||
<ARA_Gizmo_SelectIncubationTarget>选择孵化目标...</ARA_Gizmo_SelectIncubationTarget>
|
||||
<ARA_Label_Quality>品质:</ARA_Label_Quality>
|
||||
<ARA_Label_Progress>进度:</ARA_Label_Progress>
|
||||
<ARA_Status_SelectTarget>点击上方选择目标</ARA_Status_SelectTarget>
|
||||
<ARA_Status_NeedResearch>需要完成研究</ARA_Status_NeedResearch>
|
||||
<ARA_Status_LarvaActivating>幼虫激活中...</ARA_Status_LarvaActivating>
|
||||
<ARA_Status_LarvaOnTheWay>幼虫赶路中...</ARA_Status_LarvaOnTheWay>
|
||||
<ARA_Days>天</ARA_Days>
|
||||
<ARA_Tooltip_Incubating>【孵化中】</ARA_Tooltip_Incubating>
|
||||
<ARA_Tooltip_Target>目标: {0}</ARA_Tooltip_Target>
|
||||
<ARA_Tooltip_Progress>进度: {0}</ARA_Tooltip_Progress>
|
||||
<ARA_Tooltip_Quality>品质: {0}{1}</ARA_Tooltip_Quality>
|
||||
<ARA_Tooltip_Remaining>剩余: {0}</ARA_Tooltip_Remaining>
|
||||
<ARA_Tooltip_Ready>【就绪】</ARA_Tooltip_Ready>
|
||||
<ARA_Tooltip_Duration>孵化时间: {0}</ARA_Tooltip_Duration>
|
||||
<ARA_Tooltip_NoTarget>【未选择目标】\n点击标题选择孵化目标</ARA_Tooltip_NoTarget>
|
||||
</LanguageData>
|
||||
|
||||
@@ -67,7 +67,7 @@ namespace ArachnaeSwarm
|
||||
}
|
||||
}
|
||||
|
||||
public class CompQueuedInteractiveProducerWithFlux : ThingComp, IFluxController, ILarvaActivatable
|
||||
public class CompQueuedInteractiveProducerWithFlux : ThingComp, IFluxController, ILarvaActivatable, IOrderGizmoProvider
|
||||
{
|
||||
// === 通量系统字段 ===
|
||||
private float neutronFlux = 0.5f;
|
||||
@@ -79,8 +79,10 @@ namespace ArachnaeSwarm
|
||||
// === 幼虫管理 ===
|
||||
private List<Pawn> assignedLarvae = new List<Pawn>();
|
||||
|
||||
// === UI 状态(供 Gizmo 使用,不保存) ===
|
||||
public float GizmoScrollPosition = 0f;
|
||||
// === IOrderGizmoProvider 实现 ===
|
||||
public float GizmoScrollPosition { get; set; } = 0f;
|
||||
public int QueueLimit => Props.productionQueueLimit;
|
||||
void IOrderGizmoProvider.ShowOrderMenu() => ShowOrderMenuPublic();
|
||||
|
||||
// === 组件引用 ===
|
||||
private CompRefuelableNutrition _fuelComp;
|
||||
@@ -160,18 +162,19 @@ namespace ArachnaeSwarm
|
||||
public void RemoveOrderByIndex(int index) { if (index >= 0 && index < orders.Count) orders.RemoveAt(index); }
|
||||
|
||||
// === Gizmo 用的订单信息 ===
|
||||
public List<OrderDisplayInfo> GetOrdersForGizmo()
|
||||
public List<PawnOrderDisplayInfo> GetOrdersForGizmo()
|
||||
{
|
||||
var result = new List<OrderDisplayInfo>();
|
||||
var result = new List<PawnOrderDisplayInfo>();
|
||||
foreach (var order in orders)
|
||||
{
|
||||
result.Add(new OrderDisplayInfo
|
||||
result.Add(new PawnOrderDisplayInfo
|
||||
{
|
||||
label = order.process?.thingDef?.LabelCap ?? "?",
|
||||
status = order.status,
|
||||
productionProgress = GetProgress(order),
|
||||
progress = GetProgress(order),
|
||||
qualityProgress = order.QualityPercent,
|
||||
estimatedQuality = GetQualityCategory(order).GetLabel()
|
||||
estimatedQuality = GetQualityCategory(order).GetLabel(),
|
||||
remainingTime = ""
|
||||
});
|
||||
}
|
||||
return result;
|
||||
@@ -394,7 +397,7 @@ namespace ArachnaeSwarm
|
||||
public override IEnumerable<Gizmo> CompGetGizmosExtra()
|
||||
{
|
||||
yield return new Gizmo_NeutronFlux(this) { Order = -150f };
|
||||
yield return new Gizmo_DualProgressBar(this) { Order = -140f };
|
||||
yield return new Gizmo_PawnProgressBar(this) { Order = -140f };
|
||||
|
||||
if (orders.Count < Props.productionQueueLimit)
|
||||
{
|
||||
|
||||
@@ -80,7 +80,7 @@ namespace ArachnaeSwarm
|
||||
}
|
||||
}
|
||||
|
||||
public class CompQueuedPawnSpawnerWithFlux : ThingComp, IFluxController, ILarvaActivatable
|
||||
public class CompQueuedPawnSpawnerWithFlux : ThingComp, IFluxController, ILarvaActivatable, IOrderGizmoProvider
|
||||
{
|
||||
// === 通量系统字段 ===
|
||||
private float neutronFlux = 0.5f;
|
||||
@@ -93,7 +93,7 @@ namespace ArachnaeSwarm
|
||||
private List<Pawn> assignedLarvae = new List<Pawn>();
|
||||
|
||||
// === UI 状态(供 Gizmo 使用,不保存) ===
|
||||
public float GizmoScrollPosition = 0f;
|
||||
public float GizmoScrollPosition { get; set; } = 0f;
|
||||
public string LarvaStatusText = null; // 幼虫状态文本
|
||||
|
||||
// === 组件引用 ===
|
||||
@@ -161,6 +161,10 @@ namespace ArachnaeSwarm
|
||||
|
||||
public int WaitingForLarvaCount => orders.Count(o => o.status == OrderStatus.WaitingForLarva);
|
||||
public int IncubatingCount => orders.Count(o => o.status == OrderStatus.Incubating);
|
||||
|
||||
// === IOrderGizmoProvider 实现 ===
|
||||
public int QueueLimit => Props.productionQueueLimit;
|
||||
void IOrderGizmoProvider.ShowOrderMenu() => ShowOrderMenuPublic();
|
||||
|
||||
// === Gizmo 用的订单信息 ===
|
||||
public List<PawnOrderDisplayInfo> GetOrdersForGizmo()
|
||||
|
||||
@@ -8,7 +8,7 @@ using System;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
public class Building_EquipmentOotheca : Building, IFluxController, ILarvaActivatable
|
||||
public class Building_EquipmentOotheca : Building, IFluxController, ILarvaActivatable, IOrderGizmoProvider
|
||||
{
|
||||
// === 通量系统字段 ===
|
||||
private float neutronFlux = 0.5f;
|
||||
@@ -85,6 +85,84 @@ namespace ArachnaeSwarm
|
||||
|
||||
public float QualityMultiplier => qualityMultiplier;
|
||||
|
||||
// === IOrderGizmoProvider 实现 ===
|
||||
private float gizmoScrollPosition = 0f;
|
||||
public float GizmoScrollPosition { get => gizmoScrollPosition; set => gizmoScrollPosition = value; }
|
||||
public int QueueLimit => 1; // 单孵化只能有1个
|
||||
|
||||
public List<PawnOrderDisplayInfo> GetOrdersForGizmo()
|
||||
{
|
||||
var list = new List<PawnOrderDisplayInfo>();
|
||||
var config = EquipmentIncubatorData?.SelectedConfig;
|
||||
|
||||
if (isIncubating && incubatingThingDef != null)
|
||||
{
|
||||
list.Add(new PawnOrderDisplayInfo
|
||||
{
|
||||
label = incubatingThingDef.LabelCap,
|
||||
progress = IncubationProgress,
|
||||
qualityProgress = QualityPercent,
|
||||
estimatedQuality = QualityPercent > 0.8f ? "优秀" : QualityPercent > 0.5f ? "良好" : "普通",
|
||||
remainingTime = incubationDuration > incubationProgress ?
|
||||
((int)(incubationDuration - incubationProgress)).ToStringTicksToPeriod() : "",
|
||||
status = OrderStatus.Incubating
|
||||
});
|
||||
}
|
||||
else if (assignedLarva != null)
|
||||
{
|
||||
// 幼虫正在前来
|
||||
string targetLabel = config?.thingDef?.LabelCap ?? "ARA_Menu_SelectProductionTarget".Translate();
|
||||
list.Add(new PawnOrderDisplayInfo
|
||||
{
|
||||
label = targetLabel,
|
||||
progress = 0f,
|
||||
qualityProgress = 0f,
|
||||
estimatedQuality = "",
|
||||
remainingTime = "",
|
||||
status = OrderStatus.WaitingForLarva
|
||||
});
|
||||
}
|
||||
else if (config != null)
|
||||
{
|
||||
// 已选目标,等待就绪
|
||||
list.Add(new PawnOrderDisplayInfo
|
||||
{
|
||||
label = config.thingDef.LabelCap,
|
||||
progress = 0f,
|
||||
qualityProgress = 0f,
|
||||
estimatedQuality = "",
|
||||
remainingTime = config.IsResearchComplete ? "ARA_Status_Ready".Translate() : "ARA_Status_NeedResearch".Translate(),
|
||||
status = OrderStatus.WaitingForLarva
|
||||
});
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public void ShowOrderMenu() => EquipmentIncubatorData?.ShowFloatMenu();
|
||||
|
||||
public void RemoveOrderByIndex(int index)
|
||||
{
|
||||
if (index != 0) return;
|
||||
|
||||
// 取消孵化中的订单
|
||||
if (isIncubating)
|
||||
{
|
||||
CancelIncubation();
|
||||
}
|
||||
// 释放幼虫
|
||||
else if (assignedLarva != null)
|
||||
{
|
||||
assignedLarva = null;
|
||||
larvaOperateTicksRemaining = 0;
|
||||
}
|
||||
// 清除已选目标
|
||||
else if (EquipmentIncubatorData?.SelectedConfig != null)
|
||||
{
|
||||
EquipmentIncubatorData.SwitchToConfig(-1); // 清除选择
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeNutrientInfo() { } // 清理完毕
|
||||
|
||||
// === Tick方法(带活性系统)===
|
||||
@@ -413,7 +491,7 @@ namespace ArachnaeSwarm
|
||||
|
||||
if (Faction == Faction.OfPlayer)
|
||||
{
|
||||
yield return new Gizmo_EquipmentIncubationProgress(this);
|
||||
yield return new Gizmo_PawnProgressBar(this);
|
||||
yield return new Gizmo_NeutronFlux(this);
|
||||
|
||||
var config = EquipmentIncubatorData?.SelectedConfig;
|
||||
|
||||
@@ -1,241 +0,0 @@
|
||||
// File: Gizmo_EquipmentIncubationProgress.cs
|
||||
// 双向进度条 Gizmo - 品质向左,进度向右(装备孵化版)
|
||||
using System.Collections.Generic;
|
||||
using RimWorld;
|
||||
using UnityEngine;
|
||||
using Verse;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
[StaticConstructorOnStartup]
|
||||
public class Gizmo_EquipmentIncubationProgress : Gizmo
|
||||
{
|
||||
private readonly Building_EquipmentOotheca building;
|
||||
|
||||
// 尺寸常量
|
||||
private const float Width = 180f;
|
||||
private const float BarHeight = 18f;
|
||||
private const float Spacing = 4f;
|
||||
private const float Padding = 8f;
|
||||
|
||||
// 进度条材质
|
||||
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));
|
||||
|
||||
public Gizmo_EquipmentIncubationProgress(Building_EquipmentOotheca building)
|
||||
{
|
||||
this.building = building;
|
||||
Order = -140f;
|
||||
}
|
||||
|
||||
public override float GetWidth(float maxWidth)
|
||||
{
|
||||
return Mathf.Min(Width, maxWidth);
|
||||
}
|
||||
|
||||
public override GizmoResult GizmoOnGUI(Vector2 topLeft, float maxWidth, GizmoRenderParms parms)
|
||||
{
|
||||
// 主矩形区域 (75px高度)
|
||||
Rect rect = new Rect(topLeft.x, topLeft.y, GetWidth(maxWidth), 75f);
|
||||
Widgets.DrawWindowBackground(rect);
|
||||
|
||||
Rect innerRect = rect.ContractedBy(Padding);
|
||||
float curY = innerRect.y;
|
||||
|
||||
// 状态判断
|
||||
bool isIncubating = building.isIncubating;
|
||||
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);
|
||||
|
||||
string title;
|
||||
if (isIncubating && building.incubatingThingDef != null)
|
||||
title = building.incubatingThingDef.LabelCap;
|
||||
else if (config != null)
|
||||
title = config.thingDef.LabelCap;
|
||||
else
|
||||
title = "ARA_Menu_SelectProductionTarget".Translate();
|
||||
|
||||
// 标题按钮(只有非孵化状态可点击)
|
||||
bool canSwitch = !isIncubating && !hasLarva && building.EquipmentIncubatorData?.IncubationConfigs?.Count > 0;
|
||||
if (canSwitch)
|
||||
{
|
||||
if (Mouse.IsOver(titleRect))
|
||||
{
|
||||
Widgets.DrawHighlight(titleRect);
|
||||
}
|
||||
|
||||
if (Widgets.ButtonInvisible(titleRect))
|
||||
{
|
||||
ShowTargetSwitchMenu();
|
||||
}
|
||||
|
||||
GUI.color = new Color(0.7f, 0.9f, 1f);
|
||||
Widgets.Label(titleRect, title.Truncate(titleRect.width - 20f) + " ▼");
|
||||
GUI.color = Color.white;
|
||||
}
|
||||
else
|
||||
{
|
||||
Widgets.Label(titleRect, title.Truncate(titleRect.width));
|
||||
}
|
||||
curY += Text.LineHeight + Spacing;
|
||||
|
||||
// === 双向进度条区域 ===
|
||||
if (isIncubating)
|
||||
{
|
||||
// 标签行:品质进度: :孵化进度
|
||||
Text.Font = GameFont.Tiny;
|
||||
Rect labelRect = new Rect(innerRect.x, curY, innerRect.width, 14f);
|
||||
|
||||
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());
|
||||
|
||||
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
|
||||
? "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;
|
||||
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);
|
||||
GUI.color = Color.white;
|
||||
}
|
||||
|
||||
// 工具提示(整体)
|
||||
if (Mouse.IsOver(rect) && !isIncubating)
|
||||
{
|
||||
Widgets.DrawHighlight(rect);
|
||||
}
|
||||
|
||||
Text.Font = GameFont.Small;
|
||||
return new GizmoResult(GizmoState.Clear);
|
||||
}
|
||||
|
||||
private void ShowTargetSwitchMenu()
|
||||
{
|
||||
var configs = building.EquipmentIncubatorData?.IncubationConfigs;
|
||||
if (configs == null || configs.Count == 0) return;
|
||||
|
||||
List<FloatMenuOption> options = new List<FloatMenuOption>();
|
||||
|
||||
for (int i = 0; i < configs.Count; i++)
|
||||
{
|
||||
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));
|
||||
}
|
||||
else
|
||||
{
|
||||
label += $" ({cfg.DaysRequired}" + "ARA_Days".Translate() + ")";
|
||||
options.Add(new FloatMenuOption(label, () =>
|
||||
{
|
||||
building.EquipmentIncubatorData.SwitchToConfig(index);
|
||||
}, icon, Color.white));
|
||||
}
|
||||
}
|
||||
|
||||
Find.WindowStack.Add(new FloatMenu(options));
|
||||
}
|
||||
|
||||
private string GetTooltip()
|
||||
{
|
||||
var sb = new System.Text.StringBuilder();
|
||||
bool isIncubating = building.isIncubating;
|
||||
|
||||
if (isIncubating && building.incubatingThingDef != null)
|
||||
{
|
||||
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("ARA_Tooltip_Remaining".Translate(((int)remaining).ToStringTicksToPeriod()));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var config = building.EquipmentIncubatorData?.SelectedConfig;
|
||||
if (config != null)
|
||||
{
|
||||
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("ARA_Tooltip_NoTarget".Translate());
|
||||
}
|
||||
}
|
||||
|
||||
return sb.ToString().TrimEndNewlines();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ using Verse.AI;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
public class Building_Ootheca : Building, IFluxController, ILarvaActivatable
|
||||
public class Building_Ootheca : Building, IFluxController, ILarvaActivatable, IOrderGizmoProvider
|
||||
{
|
||||
// === 通量系统字段 ===
|
||||
private float neutronFlux = 0.5f;
|
||||
@@ -86,6 +86,84 @@ namespace ArachnaeSwarm
|
||||
public float QualityPercent => qualityTotal > 0 ? qualityProgress / qualityTotal : 0f;
|
||||
public float AdjustedProgressPercent => incubationDuration > 0 ? incubationProgress / incubationDuration : 0f;
|
||||
|
||||
// === IOrderGizmoProvider 实现 ===
|
||||
private float gizmoScrollPosition = 0f;
|
||||
public float GizmoScrollPosition { get => gizmoScrollPosition; set => gizmoScrollPosition = value; }
|
||||
public int QueueLimit => 1; // 单孵化只能有1个
|
||||
|
||||
public List<PawnOrderDisplayInfo> GetOrdersForGizmo()
|
||||
{
|
||||
var list = new List<PawnOrderDisplayInfo>();
|
||||
var config = IncubatorData?.SelectedConfig;
|
||||
|
||||
if (isIncubating && incubatingPawnKind != null)
|
||||
{
|
||||
list.Add(new PawnOrderDisplayInfo
|
||||
{
|
||||
label = incubatingPawnKind.LabelCap,
|
||||
progress = AdjustedProgressPercent,
|
||||
qualityProgress = QualityPercent,
|
||||
estimatedQuality = QualityPercent > 0.8f ? "优秀" : QualityPercent > 0.5f ? "良好" : "普通",
|
||||
remainingTime = GetRemainingDays() > 0 ? GetRemainingDays().ToString("F1") + " " + "ARA_Days".Translate() : "",
|
||||
status = OrderStatus.Incubating
|
||||
});
|
||||
}
|
||||
else if (assignedLarva != null)
|
||||
{
|
||||
// 幼虫正在前来
|
||||
string targetLabel = config?.pawnKind?.LabelCap ?? "ARA_Gizmo_SelectIncubationTarget".Translate();
|
||||
list.Add(new PawnOrderDisplayInfo
|
||||
{
|
||||
label = targetLabel,
|
||||
progress = 0f,
|
||||
qualityProgress = 0f,
|
||||
estimatedQuality = "",
|
||||
remainingTime = "",
|
||||
status = OrderStatus.WaitingForLarva
|
||||
});
|
||||
}
|
||||
else if (config != null)
|
||||
{
|
||||
// 已选目标,等待就绪(研究完成则显示就绪状态)
|
||||
list.Add(new PawnOrderDisplayInfo
|
||||
{
|
||||
label = config.pawnKind.LabelCap,
|
||||
progress = 0f,
|
||||
qualityProgress = 0f,
|
||||
estimatedQuality = "",
|
||||
remainingTime = config.IsResearchComplete ? "ARA_Status_Ready".Translate() : "ARA_Status_NeedResearch".Translate(),
|
||||
status = OrderStatus.WaitingForLarva
|
||||
});
|
||||
}
|
||||
// 如果没有选择目标,返回空列表(Gizmo 会显示"选择目标"状态)
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public void ShowOrderMenu() => IncubatorData?.ShowFloatMenu();
|
||||
|
||||
public void RemoveOrderByIndex(int index)
|
||||
{
|
||||
if (index != 0) return;
|
||||
|
||||
// 取消孵化中的订单
|
||||
if (isIncubating)
|
||||
{
|
||||
CancelIncubation();
|
||||
}
|
||||
// 释放幼虫
|
||||
else if (assignedLarva != null)
|
||||
{
|
||||
assignedLarva = null;
|
||||
larvaOperateTicksRemaining = 0;
|
||||
}
|
||||
// 清除已选目标
|
||||
else if (IncubatorData?.SelectedConfig != null)
|
||||
{
|
||||
IncubatorData.SwitchToConfig(-1); // 清除选择
|
||||
}
|
||||
}
|
||||
|
||||
// === 描述方法 ===
|
||||
public string GetSpeedFactorsDescription()
|
||||
{
|
||||
@@ -428,7 +506,7 @@ namespace ArachnaeSwarm
|
||||
|
||||
if (Faction == Faction.OfPlayer)
|
||||
{
|
||||
yield return new Gizmo_IncubationProgress(this);
|
||||
yield return new Gizmo_PawnProgressBar(this);
|
||||
yield return new Gizmo_NeutronFlux(this);
|
||||
|
||||
var config = IncubatorData?.SelectedConfig;
|
||||
|
||||
@@ -1,210 +0,0 @@
|
||||
using RimWorld;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Verse;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
/// <summary>
|
||||
/// 双向进度条 Gizmo - 用于物品孵化池
|
||||
/// 样式与旧版 Gizmo_IncubationProgress 统一
|
||||
/// </summary>
|
||||
[StaticConstructorOnStartup]
|
||||
public class Gizmo_DualProgressBar : Gizmo
|
||||
{
|
||||
private const float Width = 200f;
|
||||
private const float BarHeight = 18f;
|
||||
private const float Spacing = 4f;
|
||||
private const float Padding = 8f;
|
||||
private const float MaxVisibleOrders = 3;
|
||||
|
||||
private static readonly Texture2D ProgressBarTex = 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));
|
||||
|
||||
private readonly CompQueuedInteractiveProducerWithFlux comp;
|
||||
// scrollPosition 现在存储在 comp 中以在刷新间保持
|
||||
|
||||
public Gizmo_DualProgressBar(CompQueuedInteractiveProducerWithFlux comp)
|
||||
{
|
||||
this.comp = comp;
|
||||
this.Order = -140f;
|
||||
}
|
||||
|
||||
public override float GetWidth(float maxWidth) => Mathf.Min(Width, maxWidth);
|
||||
|
||||
public override GizmoResult GizmoOnGUI(Vector2 topLeft, float maxWidth, GizmoRenderParms parms)
|
||||
{
|
||||
var orders = comp.GetOrdersForGizmo();
|
||||
int orderCount = orders.Count;
|
||||
|
||||
// 计算高度
|
||||
int visibleCount = Mathf.Min(orderCount, (int)MaxVisibleOrders);
|
||||
float contentHeight = Padding * 2 + Text.LineHeight + Spacing;
|
||||
contentHeight += Mathf.Max(1, visibleCount) * (BarHeight + Spacing + 14f);
|
||||
float totalHeight = Mathf.Max(75f, contentHeight);
|
||||
|
||||
Rect rect = new Rect(topLeft.x, topLeft.y - (totalHeight - 75f), GetWidth(maxWidth), totalHeight);
|
||||
Widgets.DrawWindowBackground(rect);
|
||||
|
||||
Rect innerRect = rect.ContractedBy(Padding);
|
||||
float curY = innerRect.y;
|
||||
|
||||
// === 标题区域(可点击打开菜单) ===
|
||||
Text.Font = GameFont.Small;
|
||||
Rect titleRect = new Rect(innerRect.x, curY, innerRect.width, Text.LineHeight);
|
||||
|
||||
string title;
|
||||
bool canAdd = orderCount < comp.Props.productionQueueLimit;
|
||||
|
||||
if (orderCount > 0)
|
||||
{
|
||||
title = orders[0].label;
|
||||
if (orderCount > 1) title += $" (+{orderCount - 1})";
|
||||
}
|
||||
else
|
||||
{
|
||||
title = "ARA_Menu_SelectProductionTarget".Translate();
|
||||
}
|
||||
|
||||
if (canAdd)
|
||||
{
|
||||
if (Mouse.IsOver(titleRect))
|
||||
{
|
||||
Widgets.DrawHighlight(titleRect);
|
||||
}
|
||||
|
||||
if (Widgets.ButtonInvisible(titleRect))
|
||||
{
|
||||
comp.ShowOrderMenuPublic();
|
||||
}
|
||||
|
||||
GUI.color = new Color(0.7f, 0.9f, 1f);
|
||||
Widgets.Label(titleRect, title.Truncate(titleRect.width - 20f) + " ▼");
|
||||
GUI.color = Color.white;
|
||||
}
|
||||
else
|
||||
{
|
||||
GUI.color = new Color(0.5f, 0.5f, 0.5f);
|
||||
Widgets.Label(titleRect, title.Truncate(titleRect.width) + " " + "ARA_Gizmo_QueueFull".Translate());
|
||||
GUI.color = Color.white;
|
||||
}
|
||||
curY += Text.LineHeight + Spacing;
|
||||
|
||||
// === 订单列表 ===
|
||||
if (orderCount > 0)
|
||||
{
|
||||
float itemHeight = BarHeight + Spacing + 14f;
|
||||
float listHeight = Mathf.Min(visibleCount, orderCount) * itemHeight;
|
||||
float totalContentHeight = orderCount * itemHeight;
|
||||
bool needsScrollbar = orderCount > MaxVisibleOrders;
|
||||
|
||||
float scrollbarWidth = needsScrollbar ? 12f : 0f;
|
||||
Rect listRect = new Rect(innerRect.x, curY, innerRect.width - scrollbarWidth, listHeight);
|
||||
|
||||
// 滚动条
|
||||
if (needsScrollbar)
|
||||
{
|
||||
Rect scrollbarRect = new Rect(innerRect.xMax - scrollbarWidth, curY, scrollbarWidth, listHeight);
|
||||
float scrollMax = totalContentHeight - listHeight;
|
||||
comp.GizmoScrollPosition = GUI.VerticalScrollbar(scrollbarRect, comp.GizmoScrollPosition, listHeight, 0f, totalContentHeight);
|
||||
|
||||
if (Mouse.IsOver(listRect))
|
||||
{
|
||||
comp.GizmoScrollPosition -= Event.current.delta.y * 1.5f;
|
||||
comp.GizmoScrollPosition = Mathf.Clamp(comp.GizmoScrollPosition, 0f, scrollMax);
|
||||
}
|
||||
}
|
||||
|
||||
GUI.BeginClip(listRect);
|
||||
float drawY = -comp.GizmoScrollPosition;
|
||||
|
||||
for (int i = 0; i < orderCount; i++)
|
||||
{
|
||||
var order = orders[i];
|
||||
Rect itemRect = new Rect(0, drawY, listRect.width, itemHeight - Spacing);
|
||||
|
||||
if (itemRect.yMax > 0 && itemRect.y < listRect.height)
|
||||
{
|
||||
DrawOrderItem(itemRect, order, i);
|
||||
}
|
||||
drawY += itemHeight;
|
||||
}
|
||||
|
||||
GUI.EndClip();
|
||||
}
|
||||
else
|
||||
{
|
||||
Text.Font = GameFont.Tiny;
|
||||
GUI.color = new Color(0.7f, 0.7f, 0.7f);
|
||||
Widgets.Label(new Rect(innerRect.x, curY, innerRect.width, 20f), "ARA_Status_Ready".Translate());
|
||||
GUI.color = Color.white;
|
||||
}
|
||||
|
||||
Text.Font = GameFont.Small;
|
||||
return new GizmoResult(GizmoState.Clear);
|
||||
}
|
||||
|
||||
private void DrawOrderItem(Rect rect, OrderDisplayInfo order, int index)
|
||||
{
|
||||
float labelHeight = 14f;
|
||||
|
||||
Text.Font = GameFont.Tiny;
|
||||
Rect labelRect = new Rect(rect.x, rect.y, rect.width - 20f, labelHeight);
|
||||
|
||||
if (order.status == OrderStatus.WaitingForLarva)
|
||||
{
|
||||
GUI.color = new Color(1f, 0.8f, 0.4f);
|
||||
Widgets.Label(labelRect, $"{order.label} [" + "ARA_Status_WaitingForLarva".Translate() + "]");
|
||||
}
|
||||
else
|
||||
{
|
||||
GUI.color = Color.white;
|
||||
Widgets.Label(labelRect, $"{order.label} {order.productionProgress.ToStringPercent("F0")}");
|
||||
}
|
||||
GUI.color = Color.white;
|
||||
|
||||
Rect cancelRect = new Rect(rect.xMax - 16f, rect.y, 16f, labelHeight);
|
||||
if (Widgets.ButtonText(cancelRect, "×", false))
|
||||
{
|
||||
comp.RemoveOrderByIndex(index);
|
||||
}
|
||||
|
||||
Rect barRect = new Rect(rect.x, rect.y + labelHeight, rect.width, BarHeight);
|
||||
|
||||
if (order.status == OrderStatus.Incubating)
|
||||
{
|
||||
float midX = barRect.x + barRect.width / 2f;
|
||||
float halfWidth = barRect.width / 2f;
|
||||
|
||||
GUI.DrawTexture(barRect, EmptyBarTex);
|
||||
|
||||
float qualityWidth = halfWidth * order.qualityProgress;
|
||||
Rect qualityRect = new Rect(midX - qualityWidth, barRect.y, qualityWidth, barRect.height);
|
||||
GUI.DrawTexture(qualityRect, QualityBarTex);
|
||||
|
||||
float progressWidth = halfWidth * order.productionProgress;
|
||||
Rect progressRect = new Rect(midX, barRect.y, progressWidth, barRect.height);
|
||||
GUI.DrawTexture(progressRect, ProgressBarTex);
|
||||
|
||||
Widgets.DrawLineVertical(midX, barRect.y, barRect.height);
|
||||
|
||||
// Tooltip
|
||||
string tooltip = $"{order.label}\n" +
|
||||
"ARA_Tooltip_Quality".Translate(order.qualityProgress.ToStringPercent(), order.estimatedQuality) + "\n" +
|
||||
"ARA_Tooltip_Progress".Translate(order.productionProgress.ToStringPercent());
|
||||
TooltipHandler.TipRegion(barRect, tooltip);
|
||||
}
|
||||
else
|
||||
{
|
||||
GUI.DrawTexture(barRect, EmptyBarTex);
|
||||
Text.Font = GameFont.Tiny;
|
||||
Text.Anchor = TextAnchor.MiddleCenter;
|
||||
GUI.color = new Color(0.8f, 0.6f, 0.2f);
|
||||
Widgets.Label(barRect, "ARA_Status_WaitingForLarva".Translate());
|
||||
GUI.color = Color.white;
|
||||
Text.Anchor = TextAnchor.UpperLeft;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,239 +0,0 @@
|
||||
// File: Gizmo_IncubationProgress.cs
|
||||
// 双向进度条 Gizmo - 品质向左,进度向右
|
||||
using System.Collections.Generic;
|
||||
using RimWorld;
|
||||
using UnityEngine;
|
||||
using Verse;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
[StaticConstructorOnStartup]
|
||||
public class Gizmo_IncubationProgress : Gizmo
|
||||
{
|
||||
private readonly Building_Ootheca ootheca;
|
||||
|
||||
// 尺寸常量
|
||||
private const float Width = 180f;
|
||||
private const float BarHeight = 18f;
|
||||
private const float Spacing = 4f;
|
||||
private const float Padding = 8f;
|
||||
|
||||
// 进度条材质
|
||||
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));
|
||||
|
||||
public Gizmo_IncubationProgress(Building_Ootheca ootheca)
|
||||
{
|
||||
this.ootheca = ootheca;
|
||||
Order = -140f;
|
||||
}
|
||||
|
||||
public override float GetWidth(float maxWidth)
|
||||
{
|
||||
return Mathf.Min(Width, maxWidth);
|
||||
}
|
||||
|
||||
public override GizmoResult GizmoOnGUI(Vector2 topLeft, float maxWidth, GizmoRenderParms parms)
|
||||
{
|
||||
// 主矩形区域 (75px高度)
|
||||
Rect rect = new Rect(topLeft.x, topLeft.y, GetWidth(maxWidth), 75f);
|
||||
Widgets.DrawWindowBackground(rect);
|
||||
|
||||
Rect innerRect = rect.ContractedBy(Padding);
|
||||
float curY = innerRect.y;
|
||||
|
||||
// 状态判断
|
||||
bool isIncubating = ootheca.isIncubating;
|
||||
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);
|
||||
|
||||
string title;
|
||||
if (isIncubating && ootheca.incubatingPawnKind != null)
|
||||
title = ootheca.incubatingPawnKind.LabelCap;
|
||||
else if (config != null)
|
||||
title = config.pawnKind.LabelCap;
|
||||
else
|
||||
title = "ARA_Gizmo_SelectIncubationTarget".Translate();
|
||||
|
||||
// 标题按钮(只有非孵化状态可点击)
|
||||
bool canSwitch = !isIncubating && !hasLarva && ootheca.IncubatorData?.IncubationConfigs?.Count > 0;
|
||||
if (canSwitch)
|
||||
{
|
||||
if (Mouse.IsOver(titleRect))
|
||||
{
|
||||
Widgets.DrawHighlight(titleRect);
|
||||
}
|
||||
|
||||
if (Widgets.ButtonInvisible(titleRect))
|
||||
{
|
||||
ShowTargetSwitchMenu();
|
||||
}
|
||||
|
||||
GUI.color = new Color(0.7f, 0.9f, 1f);
|
||||
Widgets.Label(titleRect, title.Truncate(titleRect.width - 20f) + " ▼");
|
||||
GUI.color = Color.white;
|
||||
}
|
||||
else
|
||||
{
|
||||
Widgets.Label(titleRect, title.Truncate(titleRect.width));
|
||||
}
|
||||
curY += Text.LineHeight + Spacing;
|
||||
|
||||
// === 双向进度条区域 ===
|
||||
if (isIncubating)
|
||||
{
|
||||
// 标签行:品质进度: :孵化进度
|
||||
Text.Font = GameFont.Tiny;
|
||||
Rect labelRect = new Rect(innerRect.x, curY, innerRect.width, 14f);
|
||||
|
||||
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());
|
||||
|
||||
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
|
||||
? "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;
|
||||
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);
|
||||
GUI.color = Color.white;
|
||||
}
|
||||
|
||||
// 工具提示(整体)
|
||||
if (Mouse.IsOver(rect) && !isIncubating)
|
||||
{
|
||||
Widgets.DrawHighlight(rect);
|
||||
}
|
||||
|
||||
Text.Font = GameFont.Small;
|
||||
return new GizmoResult(GizmoState.Clear);
|
||||
}
|
||||
|
||||
private void ShowTargetSwitchMenu()
|
||||
{
|
||||
var configs = ootheca.IncubatorData?.IncubationConfigs;
|
||||
if (configs == null || configs.Count == 0) return;
|
||||
|
||||
List<FloatMenuOption> options = new List<FloatMenuOption>();
|
||||
|
||||
for (int i = 0; i < configs.Count; i++)
|
||||
{
|
||||
var cfg = configs[i];
|
||||
int index = i;
|
||||
|
||||
string label = cfg.pawnKind.LabelCap;
|
||||
if (cfg.requiredResearch != null && !cfg.requiredResearch.IsFinished)
|
||||
{
|
||||
label += $" ({cfg.requiredResearch.LabelCap})";
|
||||
options.Add(new FloatMenuOption(label, null));
|
||||
}
|
||||
else
|
||||
{
|
||||
label += $" ({cfg.daysRequired}" + "ARA_Days".Translate() + ")";
|
||||
options.Add(new FloatMenuOption(label, () =>
|
||||
{
|
||||
ootheca.IncubatorData.SwitchToConfig(index);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
Find.WindowStack.Add(new FloatMenu(options));
|
||||
}
|
||||
|
||||
private string GetTooltip()
|
||||
{
|
||||
var sb = new System.Text.StringBuilder();
|
||||
bool isIncubating = ootheca.isIncubating;
|
||||
|
||||
if (isIncubating && ootheca.incubatingPawnKind != null)
|
||||
{
|
||||
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("ARA_Tooltip_Remaining".Translate(daysRemaining.ToString("F1") + " " + "ARA_Days".Translate()));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var config = ootheca.IncubatorData?.SelectedConfig;
|
||||
if (config != null)
|
||||
{
|
||||
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("ARA_Tooltip_NoTarget".Translate());
|
||||
}
|
||||
}
|
||||
|
||||
return sb.ToString().TrimEndNewlines();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,8 +6,7 @@ using Verse;
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
/// <summary>
|
||||
/// 双向进度条 Gizmo - 用于督虫孵化池
|
||||
/// 样式与旧版 Gizmo_IncubationProgress 统一
|
||||
/// 统一的双向进度条 Gizmo - 用于所有孵化建筑/组件
|
||||
/// </summary>
|
||||
[StaticConstructorOnStartup]
|
||||
public class Gizmo_PawnProgressBar : Gizmo
|
||||
@@ -22,12 +21,11 @@ namespace ArachnaeSwarm
|
||||
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));
|
||||
|
||||
private readonly CompQueuedPawnSpawnerWithFlux comp;
|
||||
// scrollPosition 现在存储在 comp 中以在刷新间保持
|
||||
private readonly IOrderGizmoProvider provider;
|
||||
|
||||
public Gizmo_PawnProgressBar(CompQueuedPawnSpawnerWithFlux comp)
|
||||
public Gizmo_PawnProgressBar(IOrderGizmoProvider provider)
|
||||
{
|
||||
this.comp = comp;
|
||||
this.provider = provider;
|
||||
this.Order = -140f;
|
||||
}
|
||||
|
||||
@@ -35,7 +33,7 @@ namespace ArachnaeSwarm
|
||||
|
||||
public override GizmoResult GizmoOnGUI(Vector2 topLeft, float maxWidth, GizmoRenderParms parms)
|
||||
{
|
||||
var orders = comp.GetOrdersForGizmo();
|
||||
var orders = provider.GetOrdersForGizmo();
|
||||
int orderCount = orders.Count;
|
||||
|
||||
// 计算高度
|
||||
@@ -55,7 +53,7 @@ namespace ArachnaeSwarm
|
||||
Rect titleRect = new Rect(innerRect.x, curY, innerRect.width, Text.LineHeight);
|
||||
|
||||
string title;
|
||||
bool canAdd = orderCount < comp.Props.productionQueueLimit;
|
||||
bool canAdd = orderCount < provider.QueueLimit;
|
||||
|
||||
if (orderCount > 0)
|
||||
{
|
||||
@@ -78,7 +76,7 @@ namespace ArachnaeSwarm
|
||||
|
||||
if (Widgets.ButtonInvisible(titleRect))
|
||||
{
|
||||
comp.ShowOrderMenuPublic();
|
||||
provider.ShowOrderMenu();
|
||||
}
|
||||
|
||||
// 带下拉箭头的标题
|
||||
@@ -111,18 +109,18 @@ namespace ArachnaeSwarm
|
||||
{
|
||||
Rect scrollbarRect = new Rect(innerRect.xMax - scrollbarWidth, curY, scrollbarWidth, listHeight);
|
||||
float scrollMax = totalContentHeight - listHeight;
|
||||
comp.GizmoScrollPosition = GUI.VerticalScrollbar(scrollbarRect, comp.GizmoScrollPosition, listHeight, 0f, totalContentHeight);
|
||||
provider.GizmoScrollPosition = GUI.VerticalScrollbar(scrollbarRect, provider.GizmoScrollPosition, listHeight, 0f, totalContentHeight);
|
||||
|
||||
// 也支持滚轮
|
||||
if (Mouse.IsOver(listRect))
|
||||
{
|
||||
comp.GizmoScrollPosition -= Event.current.delta.y * 1.5f;
|
||||
comp.GizmoScrollPosition = Mathf.Clamp(comp.GizmoScrollPosition, 0f, scrollMax);
|
||||
provider.GizmoScrollPosition -= Event.current.delta.y * 1.5f;
|
||||
provider.GizmoScrollPosition = Mathf.Clamp(provider.GizmoScrollPosition, 0f, scrollMax);
|
||||
}
|
||||
}
|
||||
|
||||
GUI.BeginClip(listRect);
|
||||
float drawY = -comp.GizmoScrollPosition;
|
||||
float drawY = -provider.GizmoScrollPosition;
|
||||
|
||||
for (int i = 0; i < orderCount; i++)
|
||||
{
|
||||
@@ -175,7 +173,7 @@ namespace ArachnaeSwarm
|
||||
Rect cancelRect = new Rect(rect.xMax - 16f, rect.y, 16f, labelHeight);
|
||||
if (Widgets.ButtonText(cancelRect, "×", false))
|
||||
{
|
||||
comp.RemoveOrderByIndex(index);
|
||||
provider.RemoveOrderByIndex(index);
|
||||
}
|
||||
|
||||
// 进度条
|
||||
@@ -202,6 +200,21 @@ namespace ArachnaeSwarm
|
||||
|
||||
// 中线
|
||||
Widgets.DrawLineVertical(midX, barRect.y, barRect.height);
|
||||
|
||||
// 百分比文字(在进度条内部)
|
||||
Text.Font = GameFont.Tiny;
|
||||
Text.Anchor = TextAnchor.MiddleLeft;
|
||||
GUI.color = new Color(0.8f, 0.9f, 1f);
|
||||
Widgets.Label(new Rect(barRect.x + 2f, barRect.y, halfWidth - 4f, barRect.height),
|
||||
order.qualityProgress.ToStringPercent("F0"));
|
||||
|
||||
Text.Anchor = TextAnchor.MiddleRight;
|
||||
GUI.color = new Color(0.8f, 1f, 0.8f);
|
||||
Widgets.Label(new Rect(midX + 2f, barRect.y, halfWidth - 4f, barRect.height),
|
||||
order.progress.ToStringPercent("F0"));
|
||||
|
||||
Text.Anchor = TextAnchor.UpperLeft;
|
||||
GUI.color = Color.white;
|
||||
|
||||
// Tooltip
|
||||
string tooltip = $"{order.label}\n" +
|
||||
|
||||
27
Source/ArachnaeSwarm/Buildings/IOrderGizmoProvider.cs
Normal file
27
Source/ArachnaeSwarm/Buildings/IOrderGizmoProvider.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
// File: IOrderGizmoProvider.cs
|
||||
// 订单 Gizmo 数据提供者接口 - 让所有孵化建筑使用同一个 Gizmo
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
/// <summary>
|
||||
/// 订单 Gizmo 数据提供者接口
|
||||
/// </summary>
|
||||
public interface IOrderGizmoProvider
|
||||
{
|
||||
/// <summary>获取订单列表用于 Gizmo 显示</summary>
|
||||
List<PawnOrderDisplayInfo> GetOrdersForGizmo();
|
||||
|
||||
/// <summary>最大队列数量(单孵化为1)</summary>
|
||||
int QueueLimit { get; }
|
||||
|
||||
/// <summary>显示添加订单菜单</summary>
|
||||
void ShowOrderMenu();
|
||||
|
||||
/// <summary>移除指定索引的订单</summary>
|
||||
void RemoveOrderByIndex(int index);
|
||||
|
||||
/// <summary>Gizmo 滚动位置(用于多订单时)</summary>
|
||||
float GizmoScrollPosition { get; set; }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user