1
This commit is contained in:
@@ -0,0 +1,409 @@
|
||||
using RimWorld;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using Verse;
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
public class ITab_ResourceSubmitterContents : ITab
|
||||
{
|
||||
private Vector2 scrollPosition;
|
||||
private float scrollViewHeight;
|
||||
|
||||
private static readonly Vector2 WinSize = new Vector2(420f, 480f);
|
||||
|
||||
protected Building_ResourceSubmitter SelSubmitter => (Building_ResourceSubmitter)base.SelThing;
|
||||
|
||||
public ITab_ResourceSubmitterContents()
|
||||
{
|
||||
size = WinSize;
|
||||
labelKey = "WULA_SubmitterContents";
|
||||
tutorTag = "SubmitterContents";
|
||||
}
|
||||
|
||||
protected override void FillTab()
|
||||
{
|
||||
Rect mainRect = new Rect(0f, 0f, WinSize.x, WinSize.y).ContractedBy(10f);
|
||||
|
||||
// 标题区域
|
||||
Text.Font = GameFont.Medium;
|
||||
Widgets.Label(new Rect(mainRect.x, mainRect.y, mainRect.width, 30f), "WULA_SubmitterContents".Translate());
|
||||
Text.Font = GameFont.Small;
|
||||
|
||||
// 状态信息
|
||||
Rect statusRect = new Rect(mainRect.x, mainRect.y + 35f, mainRect.width, 40f);
|
||||
DoStatusInfo(statusRect);
|
||||
|
||||
// 存储物品列表
|
||||
Rect itemsRect = new Rect(mainRect.x, mainRect.y + 80f, mainRect.width, mainRect.height - 120f);
|
||||
DoItemsListing(itemsRect);
|
||||
|
||||
// 操作按钮区域
|
||||
Rect buttonsRect = new Rect(mainRect.x, mainRect.yMax - 35f, mainRect.width, 30f);
|
||||
DoActionButtons(buttonsRect);
|
||||
}
|
||||
|
||||
private void DoStatusInfo(Rect rect)
|
||||
{
|
||||
Widgets.DrawMenuSection(rect);
|
||||
Rect innerRect = rect.ContractedBy(5f);
|
||||
|
||||
// 运行状态
|
||||
string statusText = SelSubmitter.IsOperational ?
|
||||
"WULA_Operational".Translate() : "WULA_Inoperative".Translate();
|
||||
Color statusColor = SelSubmitter.IsOperational ? Color.green : Color.red;
|
||||
|
||||
Text.Anchor = TextAnchor.MiddleLeft;
|
||||
Rect statusLabelRect = new Rect(innerRect.x, innerRect.y, innerRect.width * 0.6f, innerRect.height);
|
||||
Widgets.Label(statusLabelRect, "WULA_Status".Translate() + ": " + statusText);
|
||||
|
||||
// 物品数量
|
||||
var storedItems = SelSubmitter.GetStoredItems();
|
||||
int totalItems = storedItems.Count;
|
||||
int totalStacks = storedItems.Sum(item => item.stackCount);
|
||||
|
||||
Rect countRect = new Rect(innerRect.x + innerRect.width * 0.6f, innerRect.y, innerRect.width * 0.4f, innerRect.height);
|
||||
Widgets.Label(countRect, $"{totalItems} {"WULA_Items".Translate()} ({totalStacks} {"WULA_Stacks".Translate()})");
|
||||
Text.Anchor = TextAnchor.UpperLeft;
|
||||
|
||||
// 状态颜色指示
|
||||
GUI.color = statusColor;
|
||||
Widgets.DrawBox(new Rect(statusLabelRect.x - 15f, statusLabelRect.y + 7f, 10f, 10f), 1);
|
||||
GUI.color = Color.white;
|
||||
}
|
||||
|
||||
private void DoItemsListing(Rect rect)
|
||||
{
|
||||
Widgets.DrawMenuSection(rect);
|
||||
Rect outRect = rect.ContractedBy(5f);
|
||||
Rect viewRect = new Rect(0f, 0f, outRect.width - 16f, scrollViewHeight);
|
||||
|
||||
var storedItems = SelSubmitter.GetStoredItems();
|
||||
|
||||
Widgets.BeginScrollView(outRect, ref scrollPosition, viewRect);
|
||||
|
||||
float curY = 0f;
|
||||
|
||||
// 列标题
|
||||
Rect headerRect = new Rect(0f, curY, viewRect.width, 25f);
|
||||
DoColumnHeaders(headerRect);
|
||||
curY += 30f;
|
||||
|
||||
if (storedItems.Count == 0)
|
||||
{
|
||||
Rect emptyRect = new Rect(0f, curY, viewRect.width, 30f);
|
||||
Text.Anchor = TextAnchor.MiddleCenter;
|
||||
Widgets.Label(emptyRect, "WULA_NoItemsInStorage".Translate());
|
||||
Text.Anchor = TextAnchor.UpperLeft;
|
||||
curY += 35f;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 按物品类型分组显示
|
||||
var groupedItems = storedItems
|
||||
.GroupBy(item => item.def)
|
||||
.OrderByDescending(g => g.Sum(item => item.stackCount))
|
||||
.ThenBy(g => g.Key.label);
|
||||
|
||||
foreach (var group in groupedItems)
|
||||
{
|
||||
ThingDef thingDef = group.Key;
|
||||
int totalCount = group.Sum(item => item.stackCount);
|
||||
int stackCount = group.Count();
|
||||
|
||||
Rect itemRect = new Rect(0f, curY, viewRect.width, 28f);
|
||||
if (DoItemRow(itemRect, thingDef, totalCount, stackCount))
|
||||
{
|
||||
// 鼠标悬停时显示详细信息
|
||||
string tooltip = GetItemTooltip(thingDef, totalCount, stackCount);
|
||||
TooltipHandler.TipRegion(itemRect, tooltip);
|
||||
}
|
||||
|
||||
curY += 32f;
|
||||
|
||||
// 分隔线
|
||||
if (curY < viewRect.height - 5f)
|
||||
{
|
||||
Widgets.DrawLineHorizontal(0f, curY - 2f, viewRect.width);
|
||||
curY += 5f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Event.current.type == EventType.Layout)
|
||||
{
|
||||
scrollViewHeight = curY;
|
||||
}
|
||||
|
||||
Widgets.EndScrollView();
|
||||
}
|
||||
|
||||
private void DoColumnHeaders(Rect rect)
|
||||
{
|
||||
float columnWidth = rect.width / 4f;
|
||||
|
||||
// 物品名称列
|
||||
Rect nameRect = new Rect(rect.x, rect.y, columnWidth * 2f, rect.height);
|
||||
Text.Anchor = TextAnchor.MiddleLeft;
|
||||
Widgets.Label(nameRect, "WULA_ItemName".Translate());
|
||||
|
||||
// 数量列
|
||||
Rect countRect = new Rect(rect.x + columnWidth * 2f, rect.y, columnWidth, rect.height);
|
||||
Text.Anchor = TextAnchor.MiddleCenter;
|
||||
Widgets.Label(countRect, "WULA_Count".Translate());
|
||||
|
||||
// 堆叠列
|
||||
Rect stacksRect = new Rect(rect.x + columnWidth * 3f, rect.y, columnWidth, rect.height);
|
||||
Widgets.Label(stacksRect, "WULA_Stacks".Translate());
|
||||
Text.Anchor = TextAnchor.UpperLeft;
|
||||
|
||||
// 标题下划线
|
||||
Widgets.DrawLineHorizontal(rect.x, rect.yMax - 2f, rect.width);
|
||||
}
|
||||
|
||||
private bool DoItemRow(Rect rect, ThingDef thingDef, int totalCount, int stackCount)
|
||||
{
|
||||
Widgets.DrawHighlightIfMouseover(rect);
|
||||
|
||||
float columnWidth = rect.width / 4f;
|
||||
|
||||
// 物品图标
|
||||
Rect iconRect = new Rect(rect.x + 2f, rect.y + 2f, 24f, 24f);
|
||||
Widgets.ThingIcon(iconRect, thingDef);
|
||||
|
||||
// 物品名称
|
||||
Rect nameRect = new Rect(rect.x + 30f, rect.y, columnWidth * 2f - 30f, rect.height);
|
||||
Text.Anchor = TextAnchor.MiddleLeft;
|
||||
string label = thingDef.LabelCap;
|
||||
if (label.Length > 25)
|
||||
{
|
||||
label = label.Substring(0, 25) + "...";
|
||||
}
|
||||
Widgets.Label(nameRect, label);
|
||||
|
||||
// 总数量
|
||||
Rect countRect = new Rect(rect.x + columnWidth * 2f, rect.y, columnWidth, rect.height);
|
||||
Text.Anchor = TextAnchor.MiddleCenter;
|
||||
Widgets.Label(countRect, totalCount.ToString());
|
||||
|
||||
// 堆叠数量
|
||||
Rect stacksRect = new Rect(rect.x + columnWidth * 3f, rect.y, columnWidth, rect.height);
|
||||
Widgets.Label(stacksRect, stackCount.ToString());
|
||||
Text.Anchor = TextAnchor.UpperLeft;
|
||||
|
||||
return Mouse.IsOver(rect);
|
||||
}
|
||||
|
||||
private string GetItemTooltip(ThingDef thingDef, int totalCount, int stackCount)
|
||||
{
|
||||
return string.Format("WULA_ItemTooltip".Translate(),
|
||||
thingDef.LabelCap,
|
||||
totalCount,
|
||||
stackCount,
|
||||
thingDef.BaseMarketValue * totalCount);
|
||||
}
|
||||
|
||||
private void DoActionButtons(Rect rect)
|
||||
{
|
||||
float buttonWidth = rect.width / 2f - 5f;
|
||||
|
||||
// 提交按钮
|
||||
Rect submitRect = new Rect(rect.x, rect.y, buttonWidth, rect.height);
|
||||
bool hasItems = SelSubmitter.GetStoredItems().Count > 0;
|
||||
bool isOperational = SelSubmitter.IsOperational;
|
||||
|
||||
string submitLabel = "WULA_SubmitToStorage".Translate();
|
||||
string submitDesc = "WULA_SubmitToStorageDesc".Translate();
|
||||
|
||||
if (!isOperational)
|
||||
{
|
||||
submitLabel = "WULA_DeviceInoperative".Translate();
|
||||
submitDesc = GetInoperativeReason();
|
||||
}
|
||||
else if (!hasItems)
|
||||
{
|
||||
submitLabel = "WULA_NoItemsToSubmit".Translate();
|
||||
submitDesc = "WULA_NoItemsToSubmitDesc".Translate();
|
||||
}
|
||||
|
||||
if (Widgets.ButtonText(submitRect, submitLabel))
|
||||
{
|
||||
if (isOperational && hasItems)
|
||||
{
|
||||
SelSubmitter.SubmitContentsToStorage();
|
||||
}
|
||||
else if (!isOperational)
|
||||
{
|
||||
Messages.Message(GetInoperativeReason(), MessageTypeDefOf.RejectInput);
|
||||
}
|
||||
else
|
||||
{
|
||||
Messages.Message("WULA_NoItemsToSubmit".Translate(), MessageTypeDefOf.RejectInput);
|
||||
}
|
||||
}
|
||||
|
||||
// 工具提示
|
||||
if (Mouse.IsOver(submitRect))
|
||||
{
|
||||
TooltipHandler.TipRegion(submitRect, submitDesc);
|
||||
}
|
||||
|
||||
// 查看全局存储按钮
|
||||
Rect storageRect = new Rect(rect.x + buttonWidth + 10f, rect.y, buttonWidth, rect.height);
|
||||
if (Widgets.ButtonText(storageRect, "WULA_ViewGlobalStorage".Translate()))
|
||||
{
|
||||
Find.WindowStack.Add(new Dialog_GlobalStorage());
|
||||
}
|
||||
|
||||
if (Mouse.IsOver(storageRect))
|
||||
{
|
||||
TooltipHandler.TipRegion(storageRect, "WULA_ViewGlobalStorageDesc".Translate());
|
||||
}
|
||||
}
|
||||
|
||||
private string GetInoperativeReason()
|
||||
{
|
||||
var submitter = SelSubmitter;
|
||||
|
||||
if (submitter.powerComp != null && !submitter.powerComp.PowerOn)
|
||||
return "WULA_NoPower".Translate();
|
||||
|
||||
if (submitter.refuelableComp != null && !submitter.refuelableComp.HasFuel)
|
||||
return "WULA_NoFuel".Translate();
|
||||
|
||||
if (submitter.flickableComp != null && !submitter.flickableComp.SwitchIsOn)
|
||||
return "WULA_SwitchOff".Translate();
|
||||
|
||||
return "WULA_UnknownReason".Translate();
|
||||
}
|
||||
|
||||
public override void TabUpdate()
|
||||
{
|
||||
base.TabUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
// 简单的全局存储查看对话框
|
||||
public class Dialog_GlobalStorage : Window
|
||||
{
|
||||
private Vector2 scrollPosition;
|
||||
private float scrollViewHeight;
|
||||
|
||||
public override Vector2 InitialSize => new Vector2(500f, 600f);
|
||||
|
||||
public Dialog_GlobalStorage()
|
||||
{
|
||||
forcePause = false;
|
||||
doCloseX = true;
|
||||
doCloseButton = true;
|
||||
closeOnClickedOutside = true;
|
||||
absorbInputAroundWindow = true;
|
||||
}
|
||||
|
||||
public override void DoWindowContents(Rect inRect)
|
||||
{
|
||||
var globalStorage = Find.World.GetComponent<GlobalStorageWorldComponent>();
|
||||
if (globalStorage == null)
|
||||
{
|
||||
Widgets.Label(inRect, "WULA_NoGlobalStorage".Translate());
|
||||
return;
|
||||
}
|
||||
|
||||
Rect titleRect = new Rect(0f, 0f, inRect.width, 30f);
|
||||
Text.Font = GameFont.Medium;
|
||||
Widgets.Label(titleRect, "WULA_GlobalStorage".Translate());
|
||||
Text.Font = GameFont.Small;
|
||||
|
||||
// 输入存储
|
||||
Rect inputRect = new Rect(0f, 40f, inRect.width, (inRect.height - 100f) / 2f);
|
||||
DoStorageSection(inputRect, globalStorage.inputStorage, "WULA_InputStorage".Translate());
|
||||
|
||||
// 输出存储
|
||||
Rect outputRect = new Rect(0f, 40f + (inRect.height - 100f) / 2f + 10f, inRect.width, (inRect.height - 100f) / 2f);
|
||||
DoStorageSection(outputRect, globalStorage.outputStorage, "WULA_OutputStorage".Translate());
|
||||
}
|
||||
|
||||
private void DoStorageSection(Rect rect, Dictionary<ThingDef, int> storage, string label)
|
||||
{
|
||||
Widgets.DrawMenuSection(rect);
|
||||
Rect innerRect = rect.ContractedBy(5f);
|
||||
|
||||
// 标题
|
||||
Text.Font = GameFont.Medium;
|
||||
Widgets.Label(new Rect(innerRect.x, innerRect.y, innerRect.width, 25f), label);
|
||||
Text.Font = GameFont.Small;
|
||||
|
||||
Rect listRect = new Rect(innerRect.x, innerRect.y + 30f, innerRect.width, innerRect.height - 35f);
|
||||
DoStorageList(listRect, storage);
|
||||
}
|
||||
|
||||
private void DoStorageList(Rect rect, Dictionary<ThingDef, int> storage)
|
||||
{
|
||||
Rect outRect = rect;
|
||||
Rect viewRect = new Rect(0f, 0f, rect.width - 16f, scrollViewHeight);
|
||||
|
||||
var items = storage
|
||||
.Where(kvp => kvp.Value > 0)
|
||||
.OrderByDescending(kvp => kvp.Value)
|
||||
.ThenBy(kvp => kvp.Key.label)
|
||||
.ToList();
|
||||
|
||||
Widgets.BeginScrollView(outRect, ref scrollPosition, viewRect);
|
||||
|
||||
float curY = 0f;
|
||||
|
||||
if (items.Count == 0)
|
||||
{
|
||||
Rect emptyRect = new Rect(0f, curY, viewRect.width, 30f);
|
||||
Text.Anchor = TextAnchor.MiddleCenter;
|
||||
Widgets.Label(emptyRect, "WULA_NoItems".Translate());
|
||||
Text.Anchor = TextAnchor.UpperLeft;
|
||||
curY += 35f;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var kvp in items)
|
||||
{
|
||||
Rect itemRect = new Rect(0f, curY, viewRect.width, 25f);
|
||||
DoStorageItemRow(itemRect, kvp.Key, kvp.Value);
|
||||
curY += 28f;
|
||||
}
|
||||
}
|
||||
|
||||
if (Event.current.type == EventType.Layout)
|
||||
{
|
||||
scrollViewHeight = curY;
|
||||
}
|
||||
|
||||
Widgets.EndScrollView();
|
||||
}
|
||||
|
||||
private void DoStorageItemRow(Rect rect, ThingDef thingDef, int count)
|
||||
{
|
||||
Widgets.DrawHighlightIfMouseover(rect);
|
||||
|
||||
// 图标
|
||||
Rect iconRect = new Rect(rect.x + 2f, rect.y + 2f, 20f, 20f);
|
||||
Widgets.ThingIcon(iconRect, thingDef);
|
||||
|
||||
// 名称
|
||||
Rect nameRect = new Rect(rect.x + 25f, rect.y, rect.width - 80f, rect.height);
|
||||
Text.Anchor = TextAnchor.MiddleLeft;
|
||||
Widgets.Label(nameRect, thingDef.LabelCap);
|
||||
|
||||
// 数量
|
||||
Rect countRect = new Rect(rect.xMax - 50f, rect.y, 50f, rect.height);
|
||||
Text.Anchor = TextAnchor.MiddleRight;
|
||||
Widgets.Label(countRect, count.ToString());
|
||||
Text.Anchor = TextAnchor.UpperLeft;
|
||||
|
||||
// 工具提示
|
||||
if (Mouse.IsOver(rect))
|
||||
{
|
||||
string tooltip = $"{thingDef.LabelCap}\n{count} {"WULA_Items".Translate()}\n{"WULA_Value".Translate()}: {thingDef.BaseMarketValue * count}";
|
||||
TooltipHandler.TipRegion(rect, tooltip);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user