Skip to content

Commit 98a7241

Browse files
committed
Make decimal places configurable
Make decimal places configurable (from 0 to 3) and make the text scaling and positioning work with the variable label sizes. No code changes for dark fog were needed, only a rebuild against the new game files.
1 parent 1082f6a commit 98a7241

File tree

8 files changed

+163
-37
lines changed

8 files changed

+163
-37
lines changed

DSP_AssemblerUI/AssemblerSpeedUI/AssemblerSpeedUIMod.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ public class AssemblerSpeedUIMod : BaseUnityPlugin
1919
public static ConfigEntry<bool> configInputSpeedsPerSecond;
2020
public static ConfigEntry<bool> configOutputSpeedsPerSecond;
2121
public static ConfigEntry<bool> configShowLiveSpeed;
22+
public static ConfigEntry<uint> configShownDecimalPlaces;
2223

2324
public static ConfigEntry<bool> configShowMinerSpeed;
2425
public static ConfigEntry<bool> configShowMinerLiveSpeed;
@@ -39,6 +40,13 @@ internal void Awake()
3940

4041
configShowLiveSpeed = Config.Bind("General", "ShowLiveSpeedInfo", false, "True: shows current speed of production building. False: shows regular recipe speed of production building.");
4142

43+
configShownDecimalPlaces = Config.Bind("General", "NumberOfDecimalsShown", (uint)1,
44+
new ConfigDescription(
45+
$"Sets the number of decimal places shown for speed values. Value must be in range [{Constants.MIN_DECIMAL_PLACES},{Constants.MAX_DECIMAL_PLACES}].",
46+
new AcceptableValueRange<uint>(Constants.MIN_DECIMAL_PLACES, Constants.MAX_DECIMAL_PLACES)
47+
)
48+
);
49+
4250
configShowMinerSpeed = Config.Bind("Miner", "EnableMinerSpeedInfo", true, "Enables the speed information below the output area in the Miner Window.");
4351
configShowMinerLiveSpeed = Config.Bind("Miner", "ShowMinerLiveSpeedInfo", false, "True: shows current speed of production building. False: shows regular recipe speed of production building.");
4452
configMinerSpeedsPerSecond = Config.Bind("Miner", "EnableMinerOutputSpeedInfoPerSecond", false, "Sets the output speeds shown in Miners to items/s (default: items/min).");

DSP_AssemblerUI/AssemblerSpeedUI/Constants.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,23 @@ internal static class Constants
77
public static readonly string AssemblerWindowSpeedTextPath = $"{AssemblerWindowPath}/produce/speed/speed-text";
88
public static readonly string MinerWindowPath = $"{BaseWindowsPath}/Miner Window";
99
public static readonly string MinerWindowSpeedTextPath = $"{MinerWindowPath}/produce/speed/speed-text";
10+
11+
public const uint MIN_DECIMAL_PLACES = 0;
12+
public const uint MAX_DECIMAL_PLACES = 3;
13+
14+
15+
public const float INPUT_YPOS = 25f;
16+
public const float OUTPUT_YPOS = -50f;
17+
18+
public const float INPUT_FIRST_X_OFFSET = 130f; //Text width/2 is deducted from this so that text is justified right
19+
public const float OUTPUT_FIRST_X_OFFSET = 1f;
20+
21+
public const float INPUT_X_ITEMSIZE = 50f;
22+
public const float OUTPUT_X_ITEMSIZE = 64f;
23+
24+
public const float INPUT_MAXWIDTH = 48f;
25+
public const float OUTPUT_MAXWIDTH = 62f;
26+
27+
public const int MAX_FONTSIZE = 12;
1028
}
1129
}

DSP_AssemblerUI/AssemblerSpeedUI/ModInfo.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ public static class ModInfo
55
public const string ModID = "dsp.assemblerUI.speedMod";
66
public const string ModName = "Assembler UI Speed Info Mod";
77
public const string majorVersion = "2";
8-
public const string minorVersion = "2";
9-
public const string hotfixVersion = "1";
8+
public const string minorVersion = "3";
9+
public const string hotfixVersion = "0";
1010
public const string buildVersion = "0";
1111
public const string VersionString = majorVersion + "." + minorVersion + "." + hotfixVersion + "." + buildVersion;
1212
}

DSP_AssemblerUI/AssemblerSpeedUI/Patchers/UiAssemblerWindowPatch.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Collections.Generic;
1+
using System;
2+
using System.Collections.Generic;
23
using System.Reflection;
34
using System.Reflection.Emit;
45
using BepInEx.Configuration;
@@ -11,6 +12,12 @@ public static class UiAssemblerWindowPatch
1112
{
1213
internal static AdditionalSpeedLabels additionalSpeedLabels;
1314

15+
/// <summary>
16+
/// This has no call shown in visual studio, but is manually called by the transpiler with a CALL-Operation.
17+
/// </summary>
18+
/// <param name="baseSpeed"></param>
19+
/// <param name="productCounts"></param>
20+
/// <param name="requireCounts"></param>
1421
public static void UpdateSpeedLabels(float baseSpeed, int[] productCounts, int[] requireCounts)
1522
{
1623
additionalSpeedLabels.UpdateSpeedLabels(baseSpeed, productCounts, requireCounts);
@@ -162,7 +169,10 @@ public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstructio
162169
new CodeInstruction(OpCodes.Ldfld, typeof(AssemblerComponent).GetField("productCounts")), //load product counts array on stack
163170
new CodeInstruction(OpCodes.Ldloc_0),
164171
new CodeInstruction(OpCodes.Ldfld, typeof(AssemblerComponent).GetField("requireCounts")), //load require counts array on stack
165-
new CodeInstruction(OpCodes.Call, typeof(UiAssemblerWindowPatch).GetMethod("UpdateSpeedLabels")) //UpdateSpeedLabels(baseSpeed, productCounts[], requireCounts[])
172+
new CodeInstruction(OpCodes.Call, typeof(UiAssemblerWindowPatch).GetMethod(
173+
"UpdateSpeedLabels",
174+
new Type[] { typeof(float), typeof(int[]), typeof(int[]) })
175+
) //UpdateSpeedLabels(baseSpeed, productCounts[], requireCounts[])
166176
);
167177

168178
AssemblerSpeedUIMod.ModLogger.DebugLog($"UIAssemblerWindowTranspiler Matcher Codes Count: {matcher.Instructions().Count}, Matcher Pos: {matcher.Pos}!");

DSP_AssemblerUI/AssemblerSpeedUI/Patchers/UiMinerWindowPatch.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,10 @@ public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstructio
159159
return matcher.Instructions();
160160
}
161161

162+
/// <summary>
163+
/// This has no call shown in visual studio, but is manually called by the transpiler with a CALL-Operation.
164+
/// </summary>
165+
/// <param name="baseSpeed"></param>
162166
public static void UpdateSpeedLabel(float baseSpeed)
163167
{
164168
additionalSpeedLabels.UpdateSpeedLabel($"assembler-speed-out-item0", baseSpeed, AssemblerSpeedUIMod.configMinerSpeedsPerSecond.Value);

DSP_AssemblerUI/AssemblerSpeedUI/Util/AdditionalSpeedLabels.cs

Lines changed: 114 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,44 @@ public class AdditionalSpeedLabels
1818
private int speedInfosInCount = 0;
1919
private Vector3? vanillaSpeedPos = null;
2020

21+
private int currentOutputs = 1;
22+
private int currentInputs = 1;
23+
2124
private ModLogger modLogger;
2225
private bool setupOutputLabels;
2326
private bool setupInputLabels;
27+
28+
/// <summary>
29+
/// The actual formatstring. Gets the value directly to avoid the extra call to ShownDecimals' getter.
30+
/// No idea if that would even affect anything, but still.
31+
/// </summary>
32+
private string DecimalFormatString
33+
{
34+
get
35+
{
36+
return "F" + AssemblerSpeedUIMod.configShownDecimalPlaces.Value;
37+
}
38+
}
2439

2540
public AdditionalSpeedLabels(ModLogger modLogger, bool setupOutputLabels, bool setupInputLabels, string speedTextPath)
2641
{
2742
this.modLogger = modLogger;
2843
this.setupOutputLabels = setupOutputLabels;
2944
this.setupInputLabels = setupInputLabels;
3045
this.speedTextPath = speedTextPath;
46+
47+
//Devices without inputs will be created with 0 current inputs, just in case
48+
this.currentInputs = setupInputLabels ? 1 : 0;
49+
}
50+
51+
/// <summary>
52+
/// Pad The numbers with 2 leading spaces so that there is spacing between values.
53+
/// </summary>
54+
/// <param name="f">The value to be formatted.</param>
55+
/// <returns>The formatted string.</returns>
56+
private string MakeFormattedPaddedLabelString(float f)
57+
{
58+
return " " + f.ToString(DecimalFormatString);
3159
}
3260

3361
private static string ItemInputKey(int index)
@@ -74,6 +102,15 @@ public void SetupSidedLabels(int itemCount, bool isInput)
74102
Func<int, string> keyFunc = isInput ? (Func<int, string>)ItemInputKey : ItemOutputKey;
75103
int loopCap = Math.Min(itemCount, safetyIndexLimit);
76104

105+
if (isInput)
106+
{
107+
currentInputs = loopCap;
108+
}
109+
else
110+
{
111+
currentOutputs = loopCap;
112+
}
113+
77114
for (int cnt = 0; cnt < loopCap; cnt++)
78115
{
79116
if (!speedInfos.ContainsKey(keyFunc(cnt)))
@@ -99,9 +136,9 @@ public void SetupSidedLabels(int itemCount, bool isInput)
99136
if (cnt2 < itemCount)
100137
{
101138
//If it is a label that should be visible, set it up
102-
PositionSpeedLabel(speedInfos[keyFunc(cnt2)].GameObject, cnt2, loopCap, isInput);
139+
speedInfos[keyFunc(cnt2)].Value.text = MakeFormattedPaddedLabelString(0f) + perMinuteString;
103140
speedInfos[keyFunc(cnt2)].GameObject.SetActive(true);
104-
speedInfos[keyFunc(cnt2)].Value.text = " 0.0" + perMinuteString;
141+
TryStartPositioningOnLabel(speedInfos[keyFunc(cnt2)], loopCap);
105142
}
106143
else
107144
{
@@ -128,10 +165,17 @@ public void AddSpeedLabel(string id, int num, int ofNum, bool input)
128165

129166
GameObject gameObject = null;
130167
var originalDetailLabelText = originalDetailLabel.GetComponent<Text>();
168+
modLogger.DebugLog($"originalDetailLabelText was:{originalDetailLabelText.text}");
131169

170+
//Object.Instantiate creates a copy of an original object
132171
gameObject = Object.Instantiate(originalDetailLabel, originalDetailLabel.transform.position, Quaternion.identity);
133172
Object.Destroy(gameObject.GetComponentInChildren<Localizer>());
134173

174+
//ContentSizeFitter to somewhat accurately measure text label size
175+
ContentSizeFitter fitter = gameObject.AddComponent<ContentSizeFitter>();
176+
fitter.horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
177+
fitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
178+
135179
gameObject.name = id;
136180
gameObject.transform.SetParent(originalDetailLabel.transform.parent);
137181

@@ -144,21 +188,19 @@ public void AddSpeedLabel(string id, int num, int ofNum, bool input)
144188
}
145189

146190
gameObject.transform.localScale = new Vector3(1f, 1f, 1f);
147-
PositionSpeedLabel(gameObject, num, ofNum, input);
148191
gameObject.transform.right = originalDetailLabel.transform.right;
149192

150-
//Input area is smaller, decrease font size
151-
if (input || ofNum > 1)
152-
{
153-
value.fontSize -= 2;
154-
}
155-
156193
ItemSpeedInfoLabel newItemSpeedInfo = new ItemSpeedInfoLabel()
157194
{
158195
GameObject = gameObject,
159-
Value = value
196+
Value = value,
197+
Index = num,
198+
IsInput = input,
199+
Fitter = fitter
160200
};
161201
speedInfos.Add(id, newItemSpeedInfo);
202+
203+
TryStartPositioningOnLabel(newItemSpeedInfo, ofNum);
162204
}
163205

164206
/// <summary>
@@ -168,14 +210,50 @@ public void AddSpeedLabel(string id, int num, int ofNum, bool input)
168210
/// <param name="num">Index of the label (0-based)</param>
169211
/// <param name="ofNum">Count of total labels (max index + 1)</param>
170212
/// <param name="input">Whether the label is on the input or output side.</param>
171-
private void PositionSpeedLabel(GameObject gameObject, int num, int ofNum, bool input)
213+
private System.Collections.IEnumerator PositionSpeedLabel(ItemSpeedInfoLabel labelData, int ofNum)
172214
{
215+
modLogger.DebugLog($"Working on label {labelData.GameObject.name} which is input? {labelData.IsInput}");
216+
modLogger.DebugLog($"OgPosition:{labelData.Fitter.transform.localPosition}");
217+
218+
RectTransform targetTransform = (RectTransform)labelData.Fitter.transform;
219+
float sizeLimit = labelData.IsInput ? Constants.INPUT_MAXWIDTH : Constants.OUTPUT_MAXWIDTH;
220+
221+
yield return null;
222+
223+
//Increase somewhat fast up to 12
224+
while(targetTransform.rect.width < (sizeLimit - 5) && labelData.Value.fontSize < 12)
225+
{
226+
labelData.Value.fontSize = Math.Min(12, labelData.Value.fontSize + 4);
227+
yield return null;
228+
}
229+
230+
//Approach size from above
231+
while(targetTransform.rect.width > sizeLimit)
232+
{
233+
labelData.Value.fontSize -= 1;
234+
yield return null;
235+
}
236+
237+
Vector3 shiftVector = GetPos(labelData.Index, ofNum, labelData.IsInput, vanillaSpeedPos.Value.z, targetTransform.rect.width);
173238

174-
modLogger.DebugLog($"OgPosition:{gameObject.transform.localPosition}");
175-
Vector3 shiftVector = GetPosShift(num, ofNum, input);
176-
modLogger.DebugLog($"ShiftedBy:{shiftVector}");
239+
modLogger.DebugLog($"Shifted to:{shiftVector} from {targetTransform.localPosition}");
177240

178-
gameObject.transform.localPosition = vanillaSpeedPos.Value + shiftVector;
241+
targetTransform.localPosition = shiftVector;
242+
}
243+
244+
/// <summary>
245+
/// Safely call the coroutine on the labels.
246+
/// This is done by checking if the corresponding GameObject is acually active before starting the coroutine.
247+
/// </summary>
248+
/// <param name="labelData">The label to position.</param>
249+
/// <param name="ofNum">The number of given labels.</param>
250+
private void TryStartPositioningOnLabel(ItemSpeedInfoLabel labelData, int ofNum)
251+
{
252+
if (labelData.GameObject.activeInHierarchy)
253+
{
254+
modLogger.DebugLog($"Starting coroutine on {labelData.GameObject.name} since it is active and all its parents are too.");
255+
labelData.Fitter.StartCoroutine(PositionSpeedLabel(labelData, ofNum));
256+
}
179257
}
180258

181259
/// <summary>
@@ -185,12 +263,13 @@ private void PositionSpeedLabel(GameObject gameObject, int num, int ofNum, bool
185263
/// <param name="ofNum">Count of total labels (max index + 1)</param>
186264
/// <param name="input">Whether the label is on the input or output side.</param>
187265
/// <returns>The Vector3 by which the label shall be shifted</returns>
188-
private static Vector3 GetPosShift(int num, int ofNum, bool input)
266+
private static Vector3 GetPos(int num, int ofNum, bool input, float z, float width)
189267
{
190-
float yShift = input ? 25f : -50f;
191-
float xShift = GetXShift(num, ofNum, input);
192268

193-
return new Vector3(xShift, yShift, 0f);
269+
float yPos = input ? Constants.INPUT_YPOS : Constants.OUTPUT_YPOS;
270+
float xPos = GetXShift(num, ofNum, input, width);
271+
272+
return new Vector3(xPos, yPos, z);
194273
}
195274

196275
/// <summary>
@@ -200,22 +279,19 @@ private static Vector3 GetPosShift(int num, int ofNum, bool input)
200279
/// <param name="ofNum">Count of total labels (max index + 1)</param>
201280
/// <param name="input">Whether the label is on the input or output side.</param>
202281
/// <returns>The x-Shift of the label</returns>
203-
private static float GetXShift(int num, int ofNum, bool input)
282+
private static float GetXShift(int num, int ofNum, bool input, float width)
204283
{
205-
//based on:
206-
//float[][] xOutputLookup = new float[][] { new float[] { -60f }, new float[] { -125f, -60f }, new float[] { -190f, -125f, -60f } };
207-
//float[][] xInputLookup = new float[][] { new float[] { 74 }, new float[] { 74f, 125f }, new float[] { 74f, 125f, 176f } };
208284
if (input)
209285
{
210-
float baseX = 74f;
211-
float itemStep = 49f;
212-
return baseX + num * itemStep;
286+
float baseX = Constants.INPUT_FIRST_X_OFFSET;
287+
float itemStep = Constants.INPUT_X_ITEMSIZE;
288+
return baseX - width/2 + num * itemStep;
213289
}
214290
else
215291
{
216-
float baseX = -60f;
217-
float itemStep = -65f;
218-
return baseX + (ofNum - 1 - num) * itemStep;
292+
float baseX = Constants.OUTPUT_FIRST_X_OFFSET;
293+
float itemStep = -Constants.OUTPUT_X_ITEMSIZE;
294+
return baseX - width/2 + (ofNum - 1 - num) * itemStep;
219295
}
220296
}
221297

@@ -232,14 +308,20 @@ public void UpdateSpeedLabel(string id, float value, bool perSecond)
232308
string speedText;
233309
if (perSecond)
234310
{
235-
speedText = (value/60f).ToString("0.0").PadLeft(5) + perSecondString;
311+
speedText = MakeFormattedPaddedLabelString(value/60f) + perSecondString;
236312
}
237313
else
238314
{
239-
speedText = value.ToString("0.0").PadLeft(5) + perMinuteString;
315+
speedText = MakeFormattedPaddedLabelString(value) + perMinuteString;
240316
}
241317

242-
speedInfos[id].Value.text = speedText;
318+
bool labelChange = speedText != speedInfos[id].Value.text;
319+
320+
if (labelChange)
321+
{
322+
speedInfos[id].Value.text = speedText;
323+
TryStartPositioningOnLabel(speedInfos[id], speedInfos[id].IsInput ? currentInputs : currentOutputs);
324+
}
243325
}
244326

245327
public void UpdateSpeedLabels(float baseSpeed, int[] productCounts, int[] requireCounts)

DSP_AssemblerUI/AssemblerSpeedUI/Util/ItemSpeedInfoLabel.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,8 @@ internal class ItemSpeedInfoLabel
77
{
88
public GameObject GameObject { get; set; }
99
public Text Value { get; set; }
10+
public int Index { get; set; }
11+
public bool IsInput { get; set; }
12+
public ContentSizeFitter Fitter { get; set; }
1013
}
1114
}

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
You can also decide whether you want to display the speed with which the device currently creates or consumes resources,
1212
or if you want to display the recipe speed for the device without impact of power and full or empty slots.
1313

14-
Speeds can also be configured to show in an items/s scale instead of items/min.
14+
Speeds can also be configured to show in an items/s scale instead of items/min, and can be configured to use 0 to 3 decimal places.
1515

1616

1717
## Version History
@@ -22,3 +22,4 @@
2222
- v2.1.0 Updated to be compatible with new game version and be more resistant to future updates. Restructured Project files and code.
2323
- v2.2.0 Updated to avoid a rare error when pasting recipes under specific circumstances. Should also ensure more compatibility with Nebula when another player changes the recipe of an open Assembler Window.
2424
- v2.2.1 Updated for compatibility with the Mecha Customization Update due to the changes added to production buffs.
25+
- v2.3.0 Updated to allow for configurable decimal places and adaptive text positioning. The release for this version will be built against the Dark Fog Update. It should also be possible to manually build it against older versions of the game, if needed.

0 commit comments

Comments
 (0)