This way the panel looks a bit better. But as for fixing the hitbox further — I don't have enough brainpower for that :(

using System;
using System.Linq;
using Mafi;
using Mafi.Core.Entities.Static;
using Mafi.Core.Products;
using Mafi.Core.Syncers;
using Mafi.Localization;
using Mafi.Unity.Ui;
using Mafi.Unity.Ui.Library;
using Mafi.Unity.Ui.Library.Inspectors;
using Mafi.Unity.UiToolkit;
using Mafi.Unity.UiToolkit.Component;
using Mafi.Unity.UiToolkit.Library;
namespace Bagger288Mod
{
// Token: 0x02000008 RID: 8
public sealed class Bagger288Inspector : BaseInspector<Bagger288>
{
// Token: 0x0600007C RID: 124
public Bagger288Inspector(UiContext context)
: base(context)
{
Label traveledValue = new Label(default(LocStrFormatted)).FontBold<Label>();
Label maxAdvanceValue = new Label(default(LocStrFormatted)).MinWidth(28.px()).TextCenterMiddle<Label>().FontBold<Label>();
ButtonText minus10Btn = new ButtonText(Button.General, "-10".AsLoc(), delegate
{
this.stepMaxAdvance(-10);
}).Compact<ButtonText>().Padding(4.px());
ButtonText minus1Btn = new ButtonText(Button.General, "-1".AsLoc(), delegate
{
this.stepMaxAdvance(-1);
}).Compact<ButtonText>().Padding(4.px());
ButtonText plus1Btn = new ButtonText(Button.General, "+1".AsLoc(), delegate
{
this.stepMaxAdvance(1);
}).Compact<ButtonText>().Padding(4.px());
ButtonText plus10Btn = new ButtonText(Button.General, "+10".AsLoc(), delegate
{
this.stepMaxAdvance(10);
}).Compact<ButtonText>().Padding(4.px());
Row row = new Row(1.pt()).AlignItemsCenterMiddle<Row>();
row.Add(new UiComponent[]
{
new Label("Дистанция хода".AsLoc()).NoShrink<Label>().Width(140.px()),
minus10Btn,
minus1Btn,
maxAdvanceValue,
plus1Btn,
plus10Btn
});
Toggle reverseToggle = new Toggle(true).Label("Начать движение задним ходом после достижения заданного расстояния".AsLoc());
reverseToggle.OnValueChanged(delegate(bool enabled)
{
if (!base.IsActive || base.Entity == null)
{
return;
}
base.Entity.ReverseAfterMaxAdvance = enabled;
if (!enabled)
{
base.Entity.IsReversing = false;
}
if (base.Entity.Phase == Bagger288Phase.Finished)
{
base.Entity.Phase = Bagger288Phase.NotReady;
}
});
Column column3 = new Column(null, null, null);
Row row2 = new Row(52.px()).AlignItemsCenterMiddle<Row>();
row2.Add(Bagger288Inspector.statusRow("Пройдено вперёд:", traveledValue));
row2.Add(new Label("".AsLoc()));
row2.Add(row);
column3.Add(row2);
column3.Add(reverseToggle);
Column column2 = column3;
base.AddPanelWithHeader(new UiComponent[] { column2 }).Title("Планировщик".AsLoc());
Grid buffersGrid = new Grid(2, new Px?(1.pt()), new Px?(2.pt()), default(Option<Action<Column>>));
base.AddPanelWithHeader(new UiComponent[]
{
new ScrollColumn { buffersGrid.Component }
}).Title("Добываемая порода".AsLoc());
Row portsRow = new Row(null, null, null).AlignSelfCenter<Row>().Wrap(true);
base.AddPanelWithHeader(new UiComponent[] { portsRow }).Title("Выходные порты".AsLoc()).FlexShrink(0f);
this.Observe<int>(() => base.Entity.TraveledForwardTiles).Do(delegate(int n)
{
traveledValue.Value((n.ToStringCached() + " " + Bagger288Inspector.tilesWord(n)).AsLoc());
});
this.Observe<int>(() => base.Entity.MaxAdvanceForwardTiles).Observe<int>(() => base.Entity.TraveledForwardTiles).Do(delegate(int maxAdvance, int traveled)
{
Bagger288Inspector.syncMaxAdvanceUi(maxAdvanceValue, minus10Btn, minus1Btn, plus1Btn, plus10Btn, maxAdvance, traveled);
});
this.Observe<bool>(() => base.Entity.ReverseAfterMaxAdvance).Do(delegate(bool enabled)
{
if (reverseToggle.GetValue() != enabled)
{
reverseToggle.Value(enabled);
}
});
this.Observe<Bagger288>(() => base.Entity).Observe<int>(() => base.Entity.OutputBuffers.Count<IProductBuffer>()).Do(delegate(Bagger288 entity, int _)
{
buffersGrid.Clear();
if (entity == null)
{
return;
}
foreach (IProductBuffer productBuffer in entity.OutputBuffers)
{
buffersGrid.AddCached<Bagger288Inspector.BufferRow>(() => new Bagger288Inspector.BufferRow()).Value(productBuffer, entity);
}
});
this.Observe<Bagger288>(() => base.Entity).Observe<int>(() => base.Entity.OutputPortsCount).Do(delegate(Bagger288 entity, int portsCount)
{
portsRow.Clear();
if (entity == null)
{
return;
}
for (int i = 0; i < portsCount; i++)
{
char c = entity.OutputPortNames[i];
portsRow.AddCached<Bagger288Inspector.SinglePortMap>(() => new Bagger288Inspector.SinglePortMap()).Value(entity, i, c);
}
});
}
// Token: 0x0600007D RID: 125 RVA: 0x00003EEC File Offset: 0x000020EC
private void stepMaxAdvance(int delta)
{
if (!base.IsActive || base.Entity == null)
{
return;
}
int traveledForwardTiles = base.Entity.TraveledForwardTiles;
int num = 200;
int num2 = (base.Entity.MaxAdvanceForwardTiles + delta).Clamp(traveledForwardTiles, num);
if (num2 == base.Entity.MaxAdvanceForwardTiles)
{
return;
}
base.Entity.MaxAdvanceForwardTiles = num2;
base.Entity.IsReversing = false;
base.Entity.Phase = Bagger288Phase.NotReady;
}
// Token: 0x0600007E RID: 126 RVA: 0x00003F64 File Offset: 0x00002164
private static string formatTargetLocalXy(RelTile2f? target)
{
if (target == null)
{
return "—";
}
RelTile2f value = target.Value;
return string.Format("({0}, {1})", value.X.ToIntRounded(), value.Y.ToIntRounded());
}
// Token: 0x0600007F RID: 127 RVA: 0x00003FB4 File Offset: 0x000021B4
private static void syncMaxAdvanceUi(Label valueLabel, ButtonText minus10Btn, ButtonText minus1Btn, ButtonText plus1Btn, ButtonText plus10Btn, int maxAdvance, int traveled)
{
int num = 200;
valueLabel.Value(maxAdvance.ToStringCached().AsLoc());
minus10Btn.Enabled(maxAdvance > traveled);
minus1Btn.Enabled(maxAdvance > traveled);
plus1Btn.Enabled(maxAdvance < num);
plus10Btn.Enabled(maxAdvance < num);
}
// Token: 0x06000080 RID: 128 RVA: 0x0000400E File Offset: 0x0000220E
private static Row statusRow(string title, Label value)
{
return new Row(6.px())
{
new Label(title.AsLoc()).Width(140.px()),
value
};
}
// Token: 0x06000121 RID: 289
private static string tilesWord(int n)
{
int abs = Math.Abs(n) % 100;
int last = abs % 10;
if (abs >= 11 && abs <= 14)
{
return "плиток";
}
if (last == 1)
{
return "плитка";
}
if (last >= 2 && last <= 4)
{
return "плитки";
}
return "плиток";
}
// Token: 0x0200001C RID: 28
private sealed class SinglePortMap : Row
{
// Token: 0x060000F9 RID: 249 RVA: 0x00007320 File Offset: 0x00005520
public SinglePortMap()
: base(null, null, null)
{
this.StyleGroup<Bagger288Inspector.SinglePortMap>().MarginRightBottom(2.pt());
this.m_portNameLabel = base.AddAndReturn<Label>(new Label(default(LocStrFormatted)).Class(Cls.groupHeader).AlignSelfStretch<Label>().Width(20)
.TextCenterMiddle<Label>());
MultipleProductsPickerUi multipleProductsPickerUi = base.AddAndReturn<MultipleProductsPickerUi>(new MultipleProductsPickerUi(delegate
{
if (this.m_entity != null)
{
return this.m_entity.AllSupportedProducts;
}
return Enumerable.Empty<ProductProto>();
}, delegate
{
if (this.m_entity != null)
{
return this.m_entity.GetPortProducts(this.m_portIndex);
}
return Enumerable.Empty<ProductProto>();
}, delegate(ProductProto p)
{
if (this.m_entity != null)
{
this.m_entity.AddProductPortIndex(p, this.m_portIndex);
}
}, delegate(ProductProto p)
{
if (this.m_entity != null)
{
this.m_entity.RemoveProductPortIndex(p, this.m_portIndex);
}
}, LocStrFormatted.Empty, Button.IconOnly, true, true, false));
multipleProductsPickerUi.MarginLeftRight(1.pt());
multipleProductsPickerUi.InsertAt(0, new Icon("Assets/Unity/UserInterface/General/Empty128.png").Size(32.px()).Color(new ColorRgba?(Theme.InactiveColor)).ObserveVisible(this, () => this.m_entity == null || this.m_entity.GetPortProducts(this.m_portIndex).IsEnumerableEmpty<ProductProto>()), false);
multipleProductsPickerUi.InsertAt(2, new VerticalDivider().MarginTopBottom(6.px()), false);
}
// Token: 0x060000FA RID: 250 RVA: 0x00007437 File Offset: 0x00005637
public Bagger288Inspector.SinglePortMap Value(Bagger288 entity, int portIndex, char portId)
{
this.m_entity = entity;
this.m_portIndex = portIndex;
this.m_portNameLabel.Value(portId.ToString().AsLoc());
return this;
}
// Token: 0x04000097 RID: 151
private int m_portIndex;
// Token: 0x04000098 RID: 152
private Bagger288 m_entity;
// Token: 0x04000099 RID: 153
private readonly Label m_portNameLabel;
}
// Token: 0x0200001D RID: 29
private sealed class BufferRow : Column
{
// Token: 0x06000100 RID: 256 RVA: 0x000074F8 File Offset: 0x000056F8
public BufferRow()
: base(null, null, null)
{
this.Class(Cls.hoverContainer).StyleGroup<Bagger288Inspector.BufferRow>().PaddingTopBottom(1.pt())
.PaddingLeftRight(2.pt());
this.m_bufferUi = base.AddAndReturn<ProductBufferUi>(new ProductBufferUi(false).Fill<ProductBufferUi>());
this.m_bufferUi.HideTitle();
this.m_errorIcon = this.m_bufferUi.Icon.AddAndReturn<Icon>(new Icon("Assets/Unity/UserInterface/EntityIcons/Warning.png").Medium<Icon>().AbsolutePosition(null, new Px?(-4.px()), new Px?(-4.px()), null, false));
this.Observe<ProductProto>(delegate
{
IProductBuffer buffer = this.m_buffer;
if (buffer == null)
{
return null;
}
return buffer.Product;
}).Observe<bool>(() => this.m_entity != null && this.m_buffer != null && !this.m_entity.IsPortSetForProduct(this.m_buffer.Product)).Do(delegate(ProductProto product, bool portNotSet)
{
if (product == null || product.IsPhantom)
{
this.m_errorIcon.Visible(false);
return;
}
this.m_errorIcon.Visible(portNotSet);
this.m_errorIcon.Color(new ColorRgba?(Theme.DangerColor));
this.m_bufferUi.Icon.Tooltip(new LocStrFormatted?(portNotSet ? "Назначьте этот продукт на выходной порт.".AsLoc() : product.Strings.Name), true, portNotSet, false);
});
this.Observe<ProductProto>(delegate
{
IProductBuffer buffer2 = this.m_buffer;
if (buffer2 == null)
{
return null;
}
return buffer2.Product;
}).Observe<Quantity>(delegate
{
IProductBuffer buffer3 = this.m_buffer;
if (buffer3 == null)
{
return Quantity.Zero;
}
return buffer3.Quantity;
}).Observe<Quantity>(delegate
{
IProductBuffer buffer4 = this.m_buffer;
if (buffer4 == null)
{
return Quantity.Zero;
}
return buffer4.Capacity;
})
.Observe<bool>(() => this.m_entity != null && this.m_buffer != null && !this.m_entity.IsPortSetForProduct(this.m_buffer.Product))
.Do(delegate(ProductProto p, Quantity q, Quantity c, bool portNotSet)
{
if (p == null || p.IsPhantom)
{
this.m_bufferUi.Values(Option.None, Quantity.Zero, Quantity.Zero, false);
this.m_bufferUi.StateInactive<ProductBufferUi>();
return;
}
this.m_bufferUi.Values(p, q, c, true);
this.m_bufferUi.State(portNotSet ? DisplayState.Danger : ((q >= c) ? DisplayState.Warning : DisplayState.Neutral));
});
}
// Token: 0x06000101 RID: 257 RVA: 0x00007647 File Offset: 0x00005847
public Bagger288Inspector.BufferRow Value(IProductBuffer buffer, Bagger288 entity)
{
this.m_buffer = buffer;
this.m_entity = entity;
return this;
}
// Token: 0x0400009A RID: 154
private IProductBuffer m_buffer;
// Token: 0x0400009B RID: 155
private Bagger288 m_entity;
// Token: 0x0400009C RID: 156
private readonly ProductBufferUi m_bufferUi;
// Token: 0x0400009D RID: 157
private readonly Icon m_errorIcon;
}
}
}