diff --git a/1.6/1.6/Assemblies/ArachnaeSwarm.dll b/1.6/1.6/Assemblies/ArachnaeSwarm.dll index e4ab335..1565622 100644 Binary files a/1.6/1.6/Assemblies/ArachnaeSwarm.dll and b/1.6/1.6/Assemblies/ArachnaeSwarm.dll differ diff --git a/1.6/1.6/Assemblies/ArachnaeSwarm.pdb b/1.6/1.6/Assemblies/ArachnaeSwarm.pdb index e8974e3..bc46b46 100644 Binary files a/1.6/1.6/Assemblies/ArachnaeSwarm.pdb and b/1.6/1.6/Assemblies/ArachnaeSwarm.pdb differ diff --git a/Source/ArachnaeSwarm/Building_Comps/ARA_CompInteractiveProducer/CompQueuedInteractiveProducerWithFlux.cs b/Source/ArachnaeSwarm/Building_Comps/ARA_CompInteractiveProducer/CompQueuedInteractiveProducerWithFlux.cs index 432c956..b21af57 100644 --- a/Source/ArachnaeSwarm/Building_Comps/ARA_CompInteractiveProducer/CompQueuedInteractiveProducerWithFlux.cs +++ b/Source/ArachnaeSwarm/Building_Comps/ARA_CompInteractiveProducer/CompQueuedInteractiveProducerWithFlux.cs @@ -8,18 +8,22 @@ using Verse.AI; namespace ArachnaeSwarm { - // 带状态和品质的物品订单(通量品质系统) + // 带状态和品质的物品订单(与 Building_Ootheca 统一的累计进度模式) public class QueuedItemOrder : IExposable { public ProcessDef process; public string tempThingDefName; public OrderStatus status = OrderStatus.WaitingForLarva; - public int productionUntilTick = -1; + + // 进度系统(累计模式,与 Building_Ootheca 统一) + public float incubationProgress = 0f; + public float incubationDuration = 0f; // 通量品质系统 public float qualityProgress = 0f; public float qualityTotal = 0f; + public float ProgressPercent => incubationDuration > 0 ? incubationProgress / incubationDuration : 0f; public float QualityPercent => qualityTotal > 0 ? qualityProgress / qualityTotal : 0f; public void ExposeData() @@ -30,7 +34,8 @@ namespace ArachnaeSwarm } Scribe_Values.Look(ref tempThingDefName, "thingDefName"); Scribe_Values.Look(ref status, "status", OrderStatus.WaitingForLarva); - Scribe_Values.Look(ref productionUntilTick, "productionUntilTick", -1); + Scribe_Values.Look(ref incubationProgress, "incubationProgress", 0f); + Scribe_Values.Look(ref incubationDuration, "incubationDuration", 0f); Scribe_Values.Look(ref qualityProgress, "qualityProgress", 0f); Scribe_Values.Look(ref qualityTotal, "qualityTotal", 0f); } @@ -159,10 +164,8 @@ namespace ArachnaeSwarm private float GetProgress(QueuedItemOrder order) { - if (order.status != OrderStatus.Incubating || order.process == null) return 0f; - int totalTicks = order.process.productionTicks; - int elapsed = totalTicks - order.productionUntilTick; - return totalTicks > 0 ? Mathf.Clamp01((float)elapsed / totalTicks) : 0f; + // 使用累计进度模式 + return order.ProgressPercent; } private QualityCategory GetQualityCategory(QueuedItemOrder order) @@ -253,8 +256,10 @@ namespace ArachnaeSwarm if (waitingOrder != null) { waitingOrder.status = OrderStatus.Incubating; - waitingOrder.productionUntilTick = waitingOrder.process.productionTicks; - waitingOrder.qualityTotal = waitingOrder.process.productionTicks; + // 使用累计进度模式(与 Building_Ootheca 统一) + waitingOrder.incubationDuration = waitingOrder.process.productionTicks; + waitingOrder.incubationProgress = 0f; + waitingOrder.qualityTotal = waitingOrder.incubationDuration; waitingOrder.qualityProgress = 0f; } assignedLarvae.Remove(larva); @@ -286,50 +291,43 @@ namespace ArachnaeSwarm CalculateAutoFlux(); } - // 消耗燃料 + // 消耗燃料(只有活性>0时) if (IsIncubating && FuelComp != null && neutronFlux > 0.01f) { float fuelPerTick = (80f * FluxEfficiency * IncubatingCount) / 60000f; FuelComp.ConsumeFuel(fuelPerTick); } - // 处理正在生产的订单 - if (hasFuel && !IsDormant) + // 进度和品质处理(与 Building_Ootheca 统一) + foreach (var order in orders.Where(o => o.status == OrderStatus.Incubating)) { - float speedFactor = 1f + (FacilitiesComp?.GetStatOffset(StatDef.Named("ARA_IncubationSpeedFactor")) ?? 0f); - float fluxSpeed = speedFactor * FluxEfficiency * 5f; - - foreach (var order in orders.Where(o => o.status == OrderStatus.Incubating && o.productionUntilTick > 0)) + if (IsDormant) { - // 进度推进 - float extraProgress = fluxSpeed - 1f; - if (extraProgress > 0) - { - int extraTicks = Mathf.FloorToInt(extraProgress); - if (Rand.Value < (extraProgress - extraTicks)) extraTicks++; - order.productionUntilTick = Mathf.Max(0, order.productionUntilTick - extraTicks); - } - - // 通量品质系统:低通量时品质增长快 + // 休眠时:不推进进度,品质衰减 + float qualityDecay = (order.qualityTotal * 0.1f) / 60000f; + order.qualityProgress = Mathf.Max(0f, order.qualityProgress - qualityDecay); + } + else + { + // 正常工作:推进进度和品质 + float speedFactor = 1f + (FacilitiesComp?.GetStatOffset(StatDef.Named("ARA_IncubationSpeedFactor")) ?? 0f); + float fluxSpeed = speedFactor * FluxEfficiency * 5f; + + // 进度推进(累计模式) + order.incubationProgress += fluxSpeed; + + // 品质增长 - 低活性时品质增长更快 float qualityBonus = 1f + (1f - neutronFlux) * 0.5f; float qualityGain = speedFactor * qualityBonus; order.qualityProgress = Mathf.Min(order.qualityProgress + qualityGain, order.qualityTotal); } } - else if (IsDormant) - { - // 休眠时品质下降 - foreach (var order in orders.Where(o => o.status == OrderStatus.Incubating)) - { - float qualityDecay = (order.qualityTotal * 0.1f) / 60000f; - order.qualityProgress = Mathf.Max(0f, order.qualityProgress - qualityDecay); - } - } - // 完成订单 + // 完成检查(进度达到持续时间时完成) orders.RemoveAll(order => { - if (order.status == OrderStatus.Incubating && order.productionUntilTick == 0) + if (order.status == OrderStatus.Incubating && + order.incubationProgress >= order.incubationDuration) { FinishProduction(order); return true; @@ -447,17 +445,23 @@ namespace ArachnaeSwarm var options = new List(); foreach (var process in Processes) { + Texture2D icon = process.thingDef?.uiIcon; + string label = process.thingDef.LabelCap; + if (process.requiredResearch != null && !process.requiredResearch.IsFinished) { - options.Add(new FloatMenuOption(process.thingDef.LabelCap + " (需要研究: " + process.requiredResearch.LabelCap + ")", null)); + label += $" (需要研究: {process.requiredResearch.LabelCap})"; + options.Add(new FloatMenuOption(label, null, icon, Color.white)); } else { var capturedProcess = process; - options.Add(new FloatMenuOption(process.thingDef.LabelCap, () => { + float days = capturedProcess.productionTicks / 60000f; + label += $" ({days:F1}天)"; + options.Add(new FloatMenuOption(label, () => { AddOrder(capturedProcess); if (orders.Count < Props.productionQueueLimit) ShowOrderMenu(); - })); + }, icon, Color.white)); } } diff --git a/Source/ArachnaeSwarm/Building_Comps/ARA_SpawnPawnFromList/CompQueuedPawnSpawnerWithFlux.cs b/Source/ArachnaeSwarm/Building_Comps/ARA_SpawnPawnFromList/CompQueuedPawnSpawnerWithFlux.cs index 19c26f9..eaf4fad 100644 --- a/Source/ArachnaeSwarm/Building_Comps/ARA_SpawnPawnFromList/CompQueuedPawnSpawnerWithFlux.cs +++ b/Source/ArachnaeSwarm/Building_Comps/ARA_SpawnPawnFromList/CompQueuedPawnSpawnerWithFlux.cs @@ -28,21 +28,26 @@ namespace ArachnaeSwarm // 带状态和品质的督虫订单 public class QueuedPawnOrder : IExposable { - public IncubationConfig config; // 使用 IncubationConfig 而不是 QueuedPawnSpawnEntry + public IncubationConfig config; public OrderStatus status = OrderStatus.WaitingForLarva; - public int spawnUntilTick = -1; + + // 进度系统(与 Building_Ootheca 统一) + public float incubationProgress = 0f; + public float incubationDuration = 0f; // 品质系统 public float qualityProgress = 0f; public float qualityTotal = 0f; + public float ProgressPercent => incubationDuration > 0 ? incubationProgress / incubationDuration : 0f; public float QualityPercent => qualityTotal > 0 ? qualityProgress / qualityTotal : 0f; public void ExposeData() { Scribe_Deep.Look(ref config, "config"); Scribe_Values.Look(ref status, "status", OrderStatus.WaitingForLarva); - Scribe_Values.Look(ref spawnUntilTick, "spawnUntilTick", -1); + Scribe_Values.Look(ref incubationProgress, "incubationProgress", 0f); + Scribe_Values.Look(ref incubationDuration, "incubationDuration", 0f); Scribe_Values.Look(ref qualityProgress, "qualityProgress", 0f); Scribe_Values.Look(ref qualityTotal, "qualityTotal", 0f); } @@ -154,8 +159,8 @@ namespace ArachnaeSwarm status = order.status, progress = prodProgress, qualityProgress = order.QualityPercent, - remainingTime = order.status == OrderStatus.Incubating && order.spawnUntilTick > 0 - ? (order.spawnUntilTick - Find.TickManager.TicksGame).ToStringTicksToPeriod() + remainingTime = order.status == OrderStatus.Incubating + ? ((int)GetRemainingTicks(order)).ToStringTicksToPeriod() : "等待中", estimatedQuality = GetEstimatedQuality(order.QualityPercent) }); @@ -165,11 +170,17 @@ namespace ArachnaeSwarm private float GetProgress(QueuedPawnOrder order) { - if (order.status != OrderStatus.Incubating || order.spawnUntilTick <= 0 || order.config == null) return 0f; - int totalTicks = Mathf.RoundToInt(order.config.daysRequired * 60000); - int startTick = order.spawnUntilTick - totalTicks; - int elapsed = Find.TickManager.TicksGame - startTick; - return totalTicks > 0 ? Mathf.Clamp01((float)elapsed / totalTicks) : 0f; + // 使用累计进度模式 + return order.ProgressPercent; + } + + private float GetRemainingTicks(QueuedPawnOrder order) + { + if (order.status != OrderStatus.Incubating || order.incubationDuration <= 0) return 0f; + float remaining = order.incubationDuration - order.incubationProgress; + float speedFactor = 1f + (FacilitiesComp?.GetStatOffset(StatDef.Named("ARA_IncubationSpeedFactor")) ?? 0f); + float fluxSpeed = speedFactor * FluxEfficiency * 5f; + return fluxSpeed > 0 ? remaining / fluxSpeed : remaining; } private string GetEstimatedQuality(float qualityPercent) @@ -260,9 +271,10 @@ namespace ArachnaeSwarm if (waitingOrder != null && waitingOrder.config != null) { waitingOrder.status = OrderStatus.Incubating; - int totalTicks = Mathf.RoundToInt(waitingOrder.config.daysRequired * 60000); - waitingOrder.spawnUntilTick = Find.TickManager.TicksGame + totalTicks; - waitingOrder.qualityTotal = totalTicks; + // 使用累计进度模式(与 Building_Ootheca 统一) + waitingOrder.incubationDuration = waitingOrder.config.daysRequired * 60000f; + waitingOrder.incubationProgress = 0f; + waitingOrder.qualityTotal = waitingOrder.incubationDuration; waitingOrder.qualityProgress = 0f; } assignedLarvae.Remove(larva); @@ -293,38 +305,43 @@ namespace ArachnaeSwarm CalculateAutoFlux(); } + // 消耗燃料(只有活性>0时) if (IsIncubating && FuelComp != null && neutronFlux > 0.01f) { float fuelPerTick = (50f * FluxEfficiency * IncubatingCount) / 60000f; FuelComp.ConsumeFuel(fuelPerTick); } - if (hasFuel && !IsDormant) + // 进度和品质处理(与 Building_Ootheca 统一) + foreach (var order in orders.Where(o => o.status == OrderStatus.Incubating)) { - float speedFactor = 1f + (FacilitiesComp?.GetStatOffset(StatDef.Named("ARA_IncubationSpeedFactor")) ?? 0f); - float fluxSpeed = speedFactor * FluxEfficiency * 5f; - - foreach (var order in orders.Where(o => o.status == OrderStatus.Incubating)) + if (IsDormant) { - float extraProgress = fluxSpeed - 1f; - if (extraProgress > 0) - { - int extraTicks = Mathf.FloorToInt(extraProgress); - if (Rand.Value < (extraProgress - extraTicks)) extraTicks++; - order.spawnUntilTick -= extraTicks; - } - + // 休眠时:不推进进度,品质衰减 + float qualityDecay = (order.qualityTotal * 0.1f) / 60000f; + order.qualityProgress = Mathf.Max(0f, order.qualityProgress - qualityDecay); + } + else + { + // 正常工作:推进进度和品质 + float speedFactor = 1f + (FacilitiesComp?.GetStatOffset(StatDef.Named("ARA_IncubationSpeedFactor")) ?? 0f); + float fluxSpeed = speedFactor * FluxEfficiency * 5f; + + // 进度推进(累计模式) + order.incubationProgress += fluxSpeed; + + // 品质增长 - 低活性时品质增长更快 float qualityBonus = 1f + (1f - neutronFlux) * 0.5f; float qualityGain = speedFactor * qualityBonus; order.qualityProgress = Mathf.Min(order.qualityProgress + qualityGain, order.qualityTotal); } } + // 完成检查(进度达到持续时间时完成) orders.RemoveAll(order => { if (order.status == OrderStatus.Incubating && - order.spawnUntilTick > 0 && - Find.TickManager.TicksGame >= order.spawnUntilTick) + order.incubationProgress >= order.incubationDuration) { CompleteOrder(order); return true; diff --git a/Source/ArachnaeSwarm/Buildings/Building_ARANutrientDispenser/Building_ARANutrientDispenser.cs b/Source/ArachnaeSwarm/Buildings/Building_ARANutrientDispenser/Building_ARANutrientDispenser.cs index b225481..3a7cd4e 100644 --- a/Source/ArachnaeSwarm/Buildings/Building_ARANutrientDispenser/Building_ARANutrientDispenser.cs +++ b/Source/ArachnaeSwarm/Buildings/Building_ARANutrientDispenser/Building_ARANutrientDispenser.cs @@ -1,8 +1,9 @@ using RimWorld; using Verse; -using Verse.Sound; // Ensure this is present +using Verse.Sound; using System.Collections.Generic; using System.Linq; +using System.Text; namespace ArachnaeSwarm { @@ -73,5 +74,35 @@ namespace ArachnaeSwarm !(gizmo is Designator_Build designator && designator.PlacingDef == ThingDefOf.Hopper) ); } + + // 覆盖 GetInspectString 以隐藏电力和进料口相关的提示 + public override string GetInspectString() + { + StringBuilder sb = new StringBuilder(); + + // 只显示燃料信息,不显示电力相关信息 + if (nutritionComp != null && dispenserProps != null) + { + float fuel = nutritionComp.Fuel; + float cost = dispenserProps.nutritionCostPerDispense; + int mealsAvailable = (int)(fuel / cost); + sb.AppendLine($"可制作: {mealsAvailable} 份"); + } + + // 添加其他 Comp 的信息,但排除 CompPower 类型 + foreach (var comp in AllComps) + { + // 跳过电力相关的组件 + if (comp is CompPower) continue; + + string compString = comp.CompInspectStringExtra(); + if (!compString.NullOrEmpty()) + { + sb.AppendLine(compString); + } + } + + return sb.ToString().TrimEndNewlines(); + } } -} \ No newline at end of file +} diff --git a/Source/ArachnaeSwarm/Buildings/Building_ARANutrientDispenser/Patch_DispenserFoodSearch.cs b/Source/ArachnaeSwarm/Buildings/Building_ARANutrientDispenser/Patch_DispenserFoodSearch.cs index 8c7671e..3d4824b 100644 --- a/Source/ArachnaeSwarm/Buildings/Building_ARANutrientDispenser/Patch_DispenserFoodSearch.cs +++ b/Source/ArachnaeSwarm/Buildings/Building_ARANutrientDispenser/Patch_DispenserFoodSearch.cs @@ -2,6 +2,7 @@ using RimWorld; using Verse; using System.Linq; +using System.Collections.Generic; namespace ArachnaeSwarm { @@ -167,4 +168,20 @@ namespace ArachnaeSwarm return bestDispenser; } } -} \ No newline at end of file + + /// + /// Patch to exclude our custom dispenser from the "needs hopper" alert. + /// The Alert checks all ThingsInGroup(ThingRequestGroup.FoodDispenser) and warns if they don't have adjacent hoppers. + /// We filter out our custom dispenser from the result. + /// + [HarmonyPatch(typeof(Alert_PasteDispenserNeedsHopper), "BadDispensers", MethodType.Getter)] + public static class Patch_AlertPasteDispenserNeedsHopper + { + [HarmonyPostfix] + public static void Postfix(ref List __result) + { + // Remove all instances of our custom dispenser from the "bad" list + __result.RemoveAll(t => t is Building_ARANutrientDispenser); + } + } +} diff --git a/Source/ArachnaeSwarm/Buildings/Building_EquipmentOotheca/Gizmo_EquipmentIncubationProgress.cs b/Source/ArachnaeSwarm/Buildings/Building_EquipmentOotheca/Gizmo_EquipmentIncubationProgress.cs index a0c7bc8..0235d33 100644 --- a/Source/ArachnaeSwarm/Buildings/Building_EquipmentOotheca/Gizmo_EquipmentIncubationProgress.cs +++ b/Source/ArachnaeSwarm/Buildings/Building_EquipmentOotheca/Gizmo_EquipmentIncubationProgress.cs @@ -60,7 +60,7 @@ namespace ArachnaeSwarm else if (config != null) title = config.thingDef.LabelCap; else - title = "选择孵化目标..."; + title = "选择生产目标..."; // 标题按钮(只有非孵化状态可点击) bool canSwitch = !isIncubating && !hasLarva && building.EquipmentIncubatorData?.IncubationConfigs?.Count > 0; @@ -225,12 +225,8 @@ namespace ArachnaeSwarm else { sb.AppendLine("【未选择目标】"); - sb.AppendLine("点击上方标题选择孵化目标"); + sb.AppendLine("点击上方标题选择生产目标"); } - - sb.AppendLine(); - sb.AppendLine("当前速度加成: " + building.SpeedMultiplier.ToStringPercent()); - sb.AppendLine("当前质量加成: " + building.QualityMultiplier.ToStringPercent()); } return sb.ToString().TrimEndNewlines(); diff --git a/Source/ArachnaeSwarm/Buildings/Building_Ootheca/Gizmo_DualProgressBar.cs b/Source/ArachnaeSwarm/Buildings/Building_Ootheca/Gizmo_DualProgressBar.cs index 2e948d0..adef01e 100644 --- a/Source/ArachnaeSwarm/Buildings/Building_Ootheca/Gizmo_DualProgressBar.cs +++ b/Source/ArachnaeSwarm/Buildings/Building_Ootheca/Gizmo_DualProgressBar.cs @@ -94,14 +94,26 @@ namespace ArachnaeSwarm // === 订单列表 === if (orderCount > 0) { - float listHeight = Mathf.Min(visibleCount, orderCount) * (BarHeight + Spacing + 14f); - Rect listRect = new Rect(innerRect.x, curY, innerRect.width, listHeight); - - if (orderCount > MaxVisibleOrders && Mouse.IsOver(listRect)) + 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) { - float scrollMax = (orderCount - MaxVisibleOrders) * (BarHeight + Spacing + 14f); - scrollPosition -= Event.current.delta.y * 0.5f; - scrollPosition = Mathf.Clamp(scrollPosition, 0f, scrollMax); + Rect scrollbarRect = new Rect(innerRect.xMax - scrollbarWidth, curY, scrollbarWidth, listHeight); + float scrollMax = totalContentHeight - listHeight; + scrollPosition = GUI.VerticalScrollbar(scrollbarRect, scrollPosition, listHeight, 0f, totalContentHeight); + + if (Mouse.IsOver(listRect)) + { + scrollPosition -= Event.current.delta.y * 1.5f; + scrollPosition = Mathf.Clamp(scrollPosition, 0f, scrollMax); + } } GUI.BeginClip(listRect); @@ -110,14 +122,13 @@ namespace ArachnaeSwarm for (int i = 0; i < orderCount; i++) { var order = orders[i]; - float itemHeight = BarHeight + 14f; - Rect itemRect = new Rect(0, drawY, listRect.width, itemHeight); + Rect itemRect = new Rect(0, drawY, listRect.width, itemHeight - Spacing); if (itemRect.yMax > 0 && itemRect.y < listRect.height) { DrawOrderItem(itemRect, order, i); } - drawY += itemHeight + Spacing; + drawY += itemHeight; } GUI.EndClip(); diff --git a/Source/ArachnaeSwarm/Buildings/Building_Ootheca/Gizmo_IncubationProgress.cs b/Source/ArachnaeSwarm/Buildings/Building_Ootheca/Gizmo_IncubationProgress.cs index f3a0a2d..ff01bd4 100644 --- a/Source/ArachnaeSwarm/Buildings/Building_Ootheca/Gizmo_IncubationProgress.cs +++ b/Source/ArachnaeSwarm/Buildings/Building_Ootheca/Gizmo_IncubationProgress.cs @@ -224,10 +224,6 @@ namespace ArachnaeSwarm sb.AppendLine("【未选择目标】"); sb.AppendLine("点击上方标题选择孵化目标"); } - - sb.AppendLine(); - sb.AppendLine("当前速度加成: " + ootheca.SpeedMultiplier.ToStringPercent()); - sb.AppendLine("当前质量加成: " + ootheca.QualityMultiplier.ToStringPercent()); } return sb.ToString().TrimEndNewlines(); diff --git a/Source/ArachnaeSwarm/Buildings/Building_Ootheca/Gizmo_PawnProgressBar.cs b/Source/ArachnaeSwarm/Buildings/Building_Ootheca/Gizmo_PawnProgressBar.cs index 4ca140c..3219c06 100644 --- a/Source/ArachnaeSwarm/Buildings/Building_Ootheca/Gizmo_PawnProgressBar.cs +++ b/Source/ArachnaeSwarm/Buildings/Building_Ootheca/Gizmo_PawnProgressBar.cs @@ -97,15 +97,28 @@ namespace ArachnaeSwarm // === 订单列表 === if (orderCount > 0) { - float listHeight = Mathf.Min(visibleCount, orderCount) * (BarHeight + Spacing + 14f); - Rect listRect = new Rect(innerRect.x, curY, innerRect.width, listHeight); - - // 滚动支持 - if (orderCount > MaxVisibleOrders && Mouse.IsOver(listRect)) + 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); + Rect viewRect = new Rect(0, 0, listRect.width, totalContentHeight); + + // 滚动条区域 + if (needsScrollbar) { - float scrollMax = (orderCount - MaxVisibleOrders) * (BarHeight + Spacing + 14f); - scrollPosition -= Event.current.delta.y * 0.5f; - scrollPosition = Mathf.Clamp(scrollPosition, 0f, scrollMax); + Rect scrollbarRect = new Rect(innerRect.xMax - scrollbarWidth, curY, scrollbarWidth, listHeight); + float scrollMax = totalContentHeight - listHeight; + scrollPosition = GUI.VerticalScrollbar(scrollbarRect, scrollPosition, listHeight, 0f, totalContentHeight); + + // 也支持滚轮 + if (Mouse.IsOver(listRect)) + { + scrollPosition -= Event.current.delta.y * 1.5f; + scrollPosition = Mathf.Clamp(scrollPosition, 0f, scrollMax); + } } GUI.BeginClip(listRect); @@ -114,14 +127,13 @@ namespace ArachnaeSwarm for (int i = 0; i < orderCount; i++) { var order = orders[i]; - float itemHeight = BarHeight + 14f; - Rect itemRect = new Rect(0, drawY, listRect.width, itemHeight); + Rect itemRect = new Rect(0, drawY, listRect.width, itemHeight - Spacing); if (itemRect.yMax > 0 && itemRect.y < listRect.height) { DrawOrderItem(itemRect, order, i); } - drawY += itemHeight + Spacing; + drawY += itemHeight; } GUI.EndClip();