This commit is contained in:
2025-12-25 17:42:02 +08:00
parent fcd98c9bfc
commit efee26e83c
3 changed files with 64 additions and 91 deletions

Binary file not shown.

Binary file not shown.

View File

@@ -1,5 +1,5 @@
// File: Gizmo_NeutronFlux.cs // File: Gizmo_NeutronFlux.cs
// 向滑动条样式的孵化活性调节 Gizmo(带刻度) // 向滑动条样式的孵化活性调节 Gizmo
// 支持实现 IFluxController 接口的所有建筑 // 支持实现 IFluxController 接口的所有建筑
using UnityEngine; using UnityEngine;
using Verse; using Verse;
@@ -10,22 +10,19 @@ namespace ArachnaeSwarm
public class Gizmo_NeutronFlux : Gizmo public class Gizmo_NeutronFlux : Gizmo
{ {
private readonly IFluxController controller; private readonly IFluxController controller;
private readonly Thing parentThing; // 用于获取 Thing 属性 private readonly Thing parentThing;
// 尺寸常量 // 尺寸常量
private const float Width = 100f; private const float Width = 200f;
private const float GizmoHeight = 140f; private const float GizmoHeight = 78f;
private const float Padding = 6f; private const float Padding = 6f;
private const float BarHeight = 28f;
// 材质 // 材质
private static readonly Texture2D FluxBarTex = SolidColorMaterials.NewSolidColorTexture(new Color(0.9f, 0.5f, 0.1f, 0.9f)); private static readonly Texture2D FluxBarTex = SolidColorMaterials.NewSolidColorTexture(new Color(0.9f, 0.5f, 0.1f, 0.9f));
private static readonly Texture2D EmptyBarTex = SolidColorMaterials.NewSolidColorTexture(new Color(0.15f, 0.15f, 0.15f, 0.8f)); private static readonly Texture2D EmptyBarTex = SolidColorMaterials.NewSolidColorTexture(new Color(0.15f, 0.15f, 0.15f, 0.8f));
private static readonly Texture2D AutoOnTex = SolidColorMaterials.NewSolidColorTexture(new Color(0.2f, 0.7f, 0.2f, 0.9f));
private static readonly Texture2D AutoOffTex = SolidColorMaterials.NewSolidColorTexture(new Color(0.5f, 0.3f, 0.3f, 0.7f));
private static readonly Texture2D TickMarkTex = SolidColorMaterials.NewSolidColorTexture(new Color(0.4f, 0.4f, 0.4f, 0.8f)); private static readonly Texture2D TickMarkTex = SolidColorMaterials.NewSolidColorTexture(new Color(0.4f, 0.4f, 0.4f, 0.8f));
private static readonly Texture2D CursorTex = SolidColorMaterials.NewSolidColorTexture(new Color(0.9f, 0.9f, 0.9f, 1f));
// 构造函数接受接口
public Gizmo_NeutronFlux(IFluxController controller) public Gizmo_NeutronFlux(IFluxController controller)
{ {
this.controller = controller; this.controller = controller;
@@ -33,40 +30,33 @@ namespace ArachnaeSwarm
Order = -150f; Order = -150f;
} }
public override float GetWidth(float maxWidth) public override float GetWidth(float maxWidth) => Mathf.Min(Width, maxWidth);
{
return Mathf.Min(Width, maxWidth);
}
public override GizmoResult GizmoOnGUI(Vector2 topLeft, float maxWidth, GizmoRenderParms parms) public override GizmoResult GizmoOnGUI(Vector2 topLeft, float maxWidth, GizmoRenderParms parms)
{ {
// 主矩形区域(向上偏移使其更高) Rect rect = new Rect(topLeft.x, topLeft.y - (GizmoHeight - 75f), GetWidth(maxWidth), GizmoHeight);
Rect rect = new Rect(topLeft.x, topLeft.y - 65f, GetWidth(maxWidth), GizmoHeight);
Widgets.DrawWindowBackground(rect); Widgets.DrawWindowBackground(rect);
Rect innerRect = rect.ContractedBy(Padding); Rect innerRect = rect.ContractedBy(Padding);
float curY = innerRect.y;
// === 标题行 === // === 标题行 ===
Text.Font = GameFont.Small; Text.Font = GameFont.Small;
Text.Anchor = TextAnchor.MiddleLeft; Text.Anchor = TextAnchor.MiddleLeft;
Rect titleRect = new Rect(innerRect.x, innerRect.y, innerRect.width - 24f, 18f); float buttonSize = 18f;
Rect titleRect = new Rect(innerRect.x, curY, innerRect.width - buttonSize - 4f, Text.LineHeight);
Widgets.Label(titleRect, "ARA_Gizmo_NeutronFlux_Title".Translate()); Widgets.Label(titleRect, "ARA_Gizmo_NeutronFlux_Title".Translate());
// === 右上角模式切换按钮 === // 模式按钮 [B]
float buttonSize = 20f; Rect modeRect = new Rect(innerRect.xMax - buttonSize, curY + 1f, buttonSize, buttonSize);
Rect modeRect = new Rect(innerRect.xMax - buttonSize, innerRect.y, buttonSize, buttonSize); Color modeColor = controller.CurrentFluxMode switch
// 根据模式显示不同颜色
Color modeColor;
switch (controller.CurrentFluxMode)
{ {
case FluxMode.Manual: modeColor = new Color(0.5f, 0.5f, 0.5f, 0.9f); break; FluxMode.Manual => new Color(0.5f, 0.5f, 0.5f, 0.9f),
case FluxMode.Quality: modeColor = new Color(0.3f, 0.6f, 0.9f, 0.9f); break; FluxMode.Quality => new Color(0.3f, 0.6f, 0.9f, 0.9f),
case FluxMode.Balance: modeColor = new Color(0.9f, 0.5f, 0.2f, 0.9f); break; FluxMode.Balance => new Color(0.9f, 0.5f, 0.2f, 0.9f),
case FluxMode.Speed: modeColor = new Color(0.2f, 0.7f, 0.2f, 0.9f); break; FluxMode.Speed => new Color(0.2f, 0.7f, 0.2f, 0.9f),
default: modeColor = Color.gray; break; _ => Color.gray
} };
GUI.DrawTexture(modeRect, SolidColorMaterials.NewSolidColorTexture(modeColor)); GUI.DrawTexture(modeRect, SolidColorMaterials.NewSolidColorTexture(modeColor));
Widgets.DrawBox(modeRect, 1); Widgets.DrawBox(modeRect, 1);
@@ -80,41 +70,65 @@ namespace ArachnaeSwarm
controller.CycleFluxMode(); controller.CycleFluxMode();
} }
// === 竖向计量条 === curY += Text.LineHeight + 2f;
float barWidth = 32f;
float barHeight = 90f; // === 信息行50% 速度 1.0x 品质 1.0x ===
float barX = innerRect.x + 8f; Text.Font = GameFont.Tiny;
float barY = innerRect.y + 24f; Text.Anchor = TextAnchor.MiddleLeft;
Rect barRect = new Rect(barX, barY, barWidth, barHeight);
float infoY = curY;
float segment = innerRect.width / 3f;
// 百分比
GUI.color = controller.IsDormant ? Color.red : Color.white;
Rect percentRect = new Rect(innerRect.x, infoY, segment, 14f);
Widgets.Label(percentRect, (controller.NeutronFlux * 100f).ToString("0") + "%");
// 速度
float speedMult = controller.FluxEfficiency;
GUI.color = speedMult >= 1f ? new Color(0.5f, 1f, 0.5f) : new Color(1f, 0.7f, 0.5f);
Rect speedRect = new Rect(innerRect.x + segment, infoY, segment, 14f);
Widgets.Label(speedRect, "ARA_Status_Speed".Translate() + " " + speedMult.ToString("0.0") + "x");
// 品质
float qualCoeff = IncubatorUtils.GetQualityCoefficient(controller.NeutronFlux);
GUI.color = qualCoeff >= 1f ? new Color(0.5f, 0.7f, 1f) : new Color(1f, 0.7f, 0.5f);
Rect qualRect = new Rect(innerRect.x + segment * 2f, infoY, segment, 14f);
Widgets.Label(qualRect, "ARA_Status_Quality".Translate() + " " + qualCoeff.ToString("0.0") + "x");
GUI.color = Color.white;
curY += 16f;
// === 横向滑条 ===
Rect barRect = new Rect(innerRect.x, curY, innerRect.width, BarHeight);
// 非孵化时显示灰色锁定状态
bool isLocked = !controller.IsIncubating; bool isLocked = !controller.IsIncubating;
// 绘制背景 // 背景
GUI.color = isLocked ? new Color(0.3f, 0.3f, 0.3f, 0.5f) : Color.white; GUI.color = isLocked ? new Color(0.3f, 0.3f, 0.3f, 0.5f) : Color.white;
GUI.DrawTexture(barRect, EmptyBarTex); GUI.DrawTexture(barRect, EmptyBarTex);
// 绘制填充(从底部向上)- 使用 RawFlux 显示预设值 // 填充(从左到右)
float displayFlux = controller.RawFlux; float displayFlux = controller.RawFlux;
float fillHeight = barRect.height * displayFlux; float fillWidth = barRect.width * displayFlux;
Rect fillRect = new Rect(barRect.x, barRect.yMax - fillHeight, barRect.width, fillHeight); Rect fillRect = new Rect(barRect.x, barRect.y, fillWidth, barRect.height);
GUI.color = isLocked ? new Color(0.5f, 0.35f, 0.1f, 0.5f) : Color.white; GUI.color = isLocked ? new Color(0.5f, 0.35f, 0.1f, 0.5f) : Color.white;
GUI.DrawTexture(fillRect, FluxBarTex); GUI.DrawTexture(fillRect, FluxBarTex);
GUI.color = Color.white; GUI.color = Color.white;
// 绘制刻度线10格 // 刻度线10格
for (int i = 1; i < 10; i++) for (int i = 1; i < 10; i++)
{ {
float tickY = barRect.y + barRect.height * (1f - i / 10f); float tickX = barRect.x + barRect.width * (i / 10f);
float tickWidth = (i == 5) ? barRect.width * 0.6f : barRect.width * 0.3f; float tickHeight = (i == 5) ? barRect.height * 0.6f : barRect.height * 0.3f;
Rect tickRect = new Rect(barRect.x, tickY - 0.5f, tickWidth, 1f); Rect tickRect = new Rect(tickX - 0.5f, barRect.y, 1f, tickHeight);
GUI.DrawTexture(tickRect, TickMarkTex); GUI.DrawTexture(tickRect, TickMarkTex);
} }
// 绘制边框 // 边框
Widgets.DrawBox(barRect, 1); Widgets.DrawBox(barRect, 1);
// === 直接在计量条上点击/拖动 === // === 拖动交互 ===
int controlId = GUIUtility.GetControlID(FocusType.Passive); int controlId = GUIUtility.GetControlID(FocusType.Passive);
Event evt = Event.current; Event evt = Event.current;
@@ -124,7 +138,7 @@ namespace ArachnaeSwarm
if (barRect.Contains(evt.mousePosition) && evt.button == 0) if (barRect.Contains(evt.mousePosition) && evt.button == 0)
{ {
GUIUtility.hotControl = controlId; GUIUtility.hotControl = controlId;
UpdateFluxFromMouse(barRect, evt.mousePosition.y); UpdateFluxFromMouse(barRect, evt.mousePosition.x);
evt.Use(); evt.Use();
} }
break; break;
@@ -132,7 +146,7 @@ namespace ArachnaeSwarm
case EventType.MouseDrag: case EventType.MouseDrag:
if (GUIUtility.hotControl == controlId) if (GUIUtility.hotControl == controlId)
{ {
UpdateFluxFromMouse(barRect, evt.mousePosition.y); UpdateFluxFromMouse(barRect, evt.mousePosition.x);
evt.Use(); evt.Use();
} }
break; break;
@@ -146,39 +160,6 @@ namespace ArachnaeSwarm
break; break;
} }
// === 右侧信息显示 ===
float infoX = barRect.xMax + 6f;
float infoWidth = innerRect.xMax - infoX;
Text.Font = GameFont.Small;
Text.Anchor = TextAnchor.MiddleLeft;
// 百分比(大字)
GUI.color = controller.IsDormant ? Color.red : Color.white;
Rect percentRect = new Rect(infoX, barRect.y, infoWidth, 20f);
Widgets.Label(percentRect, (controller.NeutronFlux * 100f).ToString("0") + "%");
Text.Font = GameFont.Tiny;
// 速度倍率
GUI.color = new Color(0.7f, 0.7f, 0.7f);
Rect speedLabelRect = new Rect(infoX, barRect.y + 22f, infoWidth, 14f);
Widgets.Label(speedLabelRect, "ARA_Status_Speed".Translate());
float speedMultiplier = controller.FluxEfficiency;
Rect speedValRect = new Rect(infoX, barRect.y + 36f, infoWidth, 14f);
GUI.color = speedMultiplier >= 1f ? new Color(0.5f, 1f, 0.5f) : new Color(1f, 0.7f, 0.5f);
Widgets.Label(speedValRect, speedMultiplier.ToString("0.0") + "x");
// 品质倍率
GUI.color = new Color(0.7f, 0.7f, 0.7f);
float qualityCoeff = IncubatorUtils.GetQualityCoefficient(controller.NeutronFlux);
Rect qualLabelRect = new Rect(infoX, barRect.y + 54f, infoWidth, 14f);
Widgets.Label(qualLabelRect, "ARA_Status_Quality".Translate());
Rect qualValRect = new Rect(infoX, barRect.y + 68f, infoWidth, 14f);
GUI.color = qualityCoeff >= 1f ? new Color(0.5f, 0.7f, 1f) : new Color(1f, 0.7f, 0.5f);
Widgets.Label(qualValRect, qualityCoeff.ToString("0.0") + "x");
GUI.color = Color.white;
Text.Anchor = TextAnchor.UpperLeft; Text.Anchor = TextAnchor.UpperLeft;
Text.Font = GameFont.Small; Text.Font = GameFont.Small;
@@ -192,9 +173,9 @@ namespace ArachnaeSwarm
return new GizmoResult(GizmoState.Clear); return new GizmoResult(GizmoState.Clear);
} }
private void UpdateFluxFromMouse(Rect barRect, float mouseY) private void UpdateFluxFromMouse(Rect barRect, float mouseX)
{ {
float percent = 1f - (mouseY - barRect.y) / barRect.height; float percent = (mouseX - barRect.x) / barRect.width;
controller.SetNeutronFlux(Mathf.Clamp01(percent)); controller.SetNeutronFlux(Mathf.Clamp01(percent));
} }
@@ -204,17 +185,11 @@ namespace ArachnaeSwarm
sb.AppendLine("ARA_Gizmo_NeutronFlux_TooltipTitle".Translate()); sb.AppendLine("ARA_Gizmo_NeutronFlux_TooltipTitle".Translate());
sb.AppendLine(); sb.AppendLine();
// 核心机制
sb.AppendLine("ARA_Gizmo_NeutronFlux_CoreMechanic".Translate()); sb.AppendLine("ARA_Gizmo_NeutronFlux_CoreMechanic".Translate());
sb.AppendLine(); sb.AppendLine();
// 当前状态
sb.AppendLine("ARA_Status_CurrentFlux".Translate(controller.RawFlux.ToStringPercent("0"))); sb.AppendLine("ARA_Status_CurrentFlux".Translate(controller.RawFlux.ToStringPercent("0")));
sb.AppendLine("ARA_Status_IncubationSpeed".Translate((controller.FluxEfficiency * 5f).ToString("0.0"))); sb.AppendLine("ARA_Status_IncubationSpeed".Translate((controller.FluxEfficiency * 5f).ToString("0.0")));
sb.AppendLine(); sb.AppendLine();
// 模式说明
sb.AppendLine("ARA_Status_Mode".Translate(controller.GetModeName())); sb.AppendLine("ARA_Status_Mode".Translate(controller.GetModeName()));
string modeDescKey = controller.CurrentFluxMode switch string modeDescKey = controller.CurrentFluxMode switch
@@ -230,8 +205,6 @@ namespace ArachnaeSwarm
sb.AppendLine(" " + modeDescKey.Translate()); sb.AppendLine(" " + modeDescKey.Translate());
} }
sb.AppendLine(); sb.AppendLine();
// 操作
sb.AppendLine("ARA_Gizmo_NeutronFlux_Operations".Translate()); sb.AppendLine("ARA_Gizmo_NeutronFlux_Operations".Translate());
if (controller.IsDormant) if (controller.IsDormant)