diff --git a/.gitignore b/.gitignore
index af18acd..64f54e0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,3 +9,6 @@
# CUSTOM
/*.DotSettings.user
+/RELEASES/
+/Folder.DotSettings.user
+Folder.DotSettings.user
diff --git a/DevTools.Humankind.GUITools.csproj b/DevTools.Humankind.GUITools.csproj
index e095c16..6b3f576 100644
--- a/DevTools.Humankind.GUITools.csproj
+++ b/DevTools.Humankind.GUITools.csproj
@@ -419,6 +419,10 @@
$(HUMANKIND_REFERENCED_LIBRARIES_PATH)\UnityEngine.XRModule.dll
false
+
+ $(HUMANKIND_REFERENCED_LIBRARIES_PATH)\Amplitude.Wwise.dll
+ false
+
$(DevToolsPATH)
false
diff --git a/Folder.DotSettings.user b/Folder.DotSettings.user
deleted file mode 100644
index ae077c4..0000000
--- a/Folder.DotSettings.user
+++ /dev/null
@@ -1,2 +0,0 @@
-
- True
\ No newline at end of file
diff --git a/GUITools.cs b/GUITools.cs
index 1b4bc29..057c5bf 100644
--- a/GUITools.cs
+++ b/GUITools.cs
@@ -4,7 +4,7 @@
namespace DevTools.Humankind.GUITools
{
- [BepInPlugin(PLUGIN_GUID, "GUITools", "1.2.1.0")]
+ [BepInPlugin(PLUGIN_GUID, "GUITools", "1.3.0.0")]
[BepInDependency("Modding.Humankind.DevTools")]
[BepInDependency("DevTools.Humankind.SharedAssets")]
public class GUITools : BaseUnityPlugin
diff --git a/MainTools.cs b/MainTools.cs
index 9bce016..4825793 100644
--- a/MainTools.cs
+++ b/MainTools.cs
@@ -1,14 +1,9 @@
using System;
-using System.IO;
-using System.Linq;
using Modding.Humankind.DevTools;
using Modding.Humankind.DevTools.DeveloperTools.UI;
using DevTools.Humankind.GUITools.UI;
-using HarmonyLib;
-using Amplitude.Mercury.Presentation;
-using BepInEx;
-using BepInEx.Configuration;
using DevTools.Humankind.GUITools.UI.PauseMenu;
+using StyledGUI;
namespace DevTools.Humankind.GUITools
{
@@ -29,11 +24,14 @@ public static class MainTools
public static FameToolWindow FameWindow { get; set; }
public static EndGameToolWindow EndGameWindow { get; set; }
public static GameStatsWindow StatsWindow { get; set; }
+ public static BackScreenWindow BackScreen { get; set; }
public static void Main()
{
if (IsDebugModeEnabled) Debug();
+ UIController.OnceGUIHasLoaded(() => StyledGUIUtility.DefaultSkin = UIController.DefaultSkin);
+ PopupToolWindow.Open(w => BackScreen = w);
PopupToolWindow.Open(w => Toolbar = w);
PopupToolWindow.Open(w => InGameMenu = w);
@@ -45,24 +43,31 @@ public static void Main()
// PopupToolWindow.Open(w => EndGameWindow = w);
// PopupToolWindow.Open(w => StatsWindow = w);
- // HumankindDevTools.RegisterAction(new KeyboardShortcut(UnityEngine.KeyCode.Home), "ToggleBasicToolWindow", ToggleBasicToolWindow);
- HumankindDevTools.RegisterAction(new KeyboardShortcut(UnityEngine.KeyCode.Home), "ToggleHideToolbarWindow", ToggleHideToolbarWindow);
- HumankindDevTools.RegisterAction(new KeyboardShortcut(UnityEngine.KeyCode.Tab), "ToggleGameOverviewWindow", ToggleGameOverviewWindow);
-
- HumankindDevTools.RegisterAction(
+ // HumankindDevTools.RegisterAction(new KeyboardShortcut(UnityEngine.KeyCode.UpArrow, UnityEngine.KeyCode.LeftControl), "ToggleBasicToolWindow", ToggleBasicToolWindow);
+ // HumankindDevTools.RegisterAction(new KeyboardShortcut(UnityEngine.KeyCode.Home), "ToggleHideToolbarWindow", ToggleHideToolbarWindow);
+ // HumankindDevTools.RegisterAction(new KeyboardShortcut(UnityEngine.KeyCode.Tab), "ToggleGameOverviewWindow", ToggleGameOverviewWindow);
+
+ /*HumankindDevTools.RegisterAction(
new KeyboardShortcut(UnityEngine.KeyCode.Insert),
"ToggleHideAllGUITools",
- ToggleHideAllUIWindows);
-
+ ToggleHideAllUIWindows);*/
+
// Maps [ESC] key to: GodMode.Enabled = false
// HumankindDevTools.RegisterAction(new KeyboardShortcut(UnityEngine.KeyCode.Escape), "CancelGodMode", CancelGodMode);
- // ToggleGameOverviewWindow();
+ // ToggleGameOverviewWindow();
+ // ToggleBasicToolWindow();
+
+ /*HumankindDevTools.RegisterAction(
+ new KeyboardShortcut(UnityEngine.KeyCode.F4, UnityEngine.KeyCode.LeftShift),
+ "RebuildConstructibles",
+ ConstructibleStore.Rebuild);*/
}
public static void ToggleHideToolbarWindow() => GlobalSettings.HideToolbarWindow.Value = !GlobalSettings.HideToolbarWindow.Value;
- public static void ToggleHideAllUIWindows() => FloatingToolWindow.HideAllGUITools = !FloatingToolWindow.HideAllGUITools;
+ public static void ToggleHideAllUIWindows() =>
+ Loggr.Log("HIDDING ALL GUI TOOLS WINDOWS IS TEMPORARILY DISABLED", ConsoleColor.Magenta); //FloatingToolWindow.HideAllGUITools = !FloatingToolWindow.HideAllGUITools);
// public static void CancelGodMode() => AccessTools.PropertySetter(typeof(GodMode), "Enabled")?.Invoke(null, new object[] { false });
@@ -103,20 +108,22 @@ public static void Unload(bool saveState = false) {
FameWindow?.Close();
EndGameWindow?.Close();
StatsWindow?.Close();
+ BackScreen?.Close();
+ ScreenLocker.Unload();
}
private static void Debug()
{
- var scriptsPath = Path.Combine(Paths.GameRootPath, "scripts");
+ /*var scriptsPath = Path.Combine(Paths.GameRootPath, "scripts");
var files = Directory.GetFiles(scriptsPath, "*.cs", SearchOption.AllDirectories)
.Where(path => path.Substring(scriptsPath.Length, 5) != "\\obj\\");
- Loggr.Log(string.Join("\n", files), ConsoleColor.DarkYellow);
+ Loggr.Log(string.Join("\n", files), ConsoleColor.DarkYellow);*/
// When true, draws a colored border for all UIOverlays backing a FloatingToolWindow derived class
UIOverlay.DEBUG_DRAW_OVERLAY = false;
// When not true, adds more verbosity to console output
- Modding.Humankind.DevTools.DevTools.QuietMode = true;
+ Modding.Humankind.DevTools.DevTools.QuietMode = false;
}
}
}
diff --git a/StyledGUI/Graphics.cs b/StyledGUI/Graphics.cs
new file mode 100644
index 0000000..097e37c
--- /dev/null
+++ b/StyledGUI/Graphics.cs
@@ -0,0 +1,36 @@
+using UnityEngine;
+
+namespace StyledGUI
+{
+ public static class Graphics
+ {
+ public static Texture2D WhiteTexture = CreateSinglePixelTexture2D(new Color(1f, 1f, 1f, 1f));
+ public static Texture2D BlackTexture = CreateSinglePixelTexture2D(new Color(0, 0, 0, 1f));
+ public static Texture2D TransparentTexture = CreateSinglePixelTexture2D(new Color(1f, 1f, 1f, 0f));
+
+ public static Texture2D CreateSinglePixelTexture2D(Color color)
+ {
+ Texture2D tex = new Texture2D(1,1);
+ tex.SetPixel(0, 0, color);
+ tex.Apply();
+
+ return tex;
+ }
+
+ public static void DrawHorizontalLine(float alpha = 0.45f)
+ {
+ var r = GUILayoutUtility.GetRect(1f, 1f);
+ GUI.DrawTexture(new Rect(r.x, r.y, r.width - 3f, 1f),
+ WhiteTexture, ScaleMode.StretchToFill, true,
+ 1f, new Color(1f, 1f, 1f, alpha), 0,0);
+ }
+
+ public static void DrawHorizontalLine(float alpha, float width)
+ {
+ var r = GUILayoutUtility.GetRect(1f, 1f);
+ GUI.DrawTexture(new Rect(r.x, r.y, width, 1f),
+ WhiteTexture, ScaleMode.StretchToFill, true,
+ 1f, new Color(1f, 1f, 1f, alpha), 0,0);
+ }
+ }
+}
diff --git a/StyledGUI/Grid/CellSpanGrid.cs b/StyledGUI/Grid/CellSpanGrid.cs
new file mode 100644
index 0000000..0e552ab
--- /dev/null
+++ b/StyledGUI/Grid/CellSpanGrid.cs
@@ -0,0 +1,74 @@
+using System;
+using UnityEngine;
+
+namespace StyledGUI
+{
+
+ public interface ICellSpan
+ {
+ GUILayoutOption CellSpan1 { get; set; }
+ GUILayoutOption CellSpan2 { get; set; }
+ GUILayoutOption CellSpan3 { get; set; }
+ GUILayoutOption CellSpan4 { get; set; }
+ GUILayoutOption CellSpan5 { get; set; }
+ GUILayoutOption CellSpan6 { get; set; }
+ GUILayoutOption CellSpan7 { get; set; }
+ GUILayoutOption CellSpan8 { get; set; }
+ GUILayoutOption CellSpan9 { get; set; }
+ GUILayoutOption CellSpan10 { get; set; }
+ float GetCellWidth();
+ float GetCellSpace();
+ float GetCellHeight();
+ }
+
+ public abstract class CellSpanGrid : ICellSpan
+ {
+ public float CellWidth;
+ public float CellSpace;
+ public GUILayoutOption CellSpan1 { get; set; }
+ public GUILayoutOption CellSpan2 { get; set; }
+ public GUILayoutOption CellSpan3 { get; set; }
+ public GUILayoutOption CellSpan4 { get; set; }
+ public GUILayoutOption CellSpan5 { get; set; }
+ public GUILayoutOption CellSpan6 { get; set; }
+ public GUILayoutOption CellSpan7 { get; set; }
+ public GUILayoutOption CellSpan8 { get; set; }
+ public GUILayoutOption CellSpan9 { get; set; }
+ public GUILayoutOption CellSpan10 { get; set; }
+ public GUILayoutOption CellSpan(int numCells) => GUILayout.Width(CellWidth * numCells + CellSpace * (numCells - 1));
+
+ public CellSpanGrid()
+ {
+ Resize(34f, 1f);
+ }
+
+ public CellSpanGrid(float cellWidth, float cellSpace)
+ {
+ Resize(cellWidth, cellSpace);
+ }
+
+ public CellSpanGrid Resize(float cellWidth, float cellSpace)
+ {
+ CellWidth = cellWidth;
+ CellSpace = cellSpace;
+ CellSpan1 = CellSpan(1);
+ CellSpan2 = CellSpan(2);
+ CellSpan3 = CellSpan(3);
+ CellSpan4 = CellSpan(4);
+ CellSpan5 = CellSpan(5);
+ CellSpan6 = CellSpan(6);
+ CellSpan7 = CellSpan(7);
+ CellSpan8 = CellSpan(8);
+ CellSpan9 = CellSpan(9);
+ CellSpan10 = CellSpan(10);
+
+ return this;
+ }
+
+ public float GetCellWidth() => CellWidth;
+ public float GetCellSpace() => CellSpace;
+ public virtual float GetCellHeight() => 22f;
+ }
+
+
+}
diff --git a/StyledGUI/Grid/GridStyles.cs b/StyledGUI/Grid/GridStyles.cs
new file mode 100644
index 0000000..1eee8d2
--- /dev/null
+++ b/StyledGUI/Grid/GridStyles.cs
@@ -0,0 +1,24 @@
+using System;
+using UnityEngine;
+
+namespace StyledGUI
+{
+ public interface IStyledGrid : ICellSpan
+ {
+ Color CellTintColor { get; set; }
+ Color CellTintColorAlt { get; set; }
+ Color IconTintColor { get; set; }
+ Color CellButtonTintColor { get; set; }
+ Color SelectedCellTintColor { get; set; }
+ }
+
+ public abstract class GridStyles : CellSpanGrid, IStyledGrid
+ {
+ public virtual Color CellTintColor { get; set; } = new Color(0.9f, 0.9f, 0.85f, 1f);
+ public virtual Color CellTintColorAlt { get; set; } = new Color(0.6f, 0.6f, 0.6f, 1f);
+ public virtual Color IconTintColor { get; set; } = new Color(1f, 1f, 1f, 0.7f);
+ public virtual Color CellButtonTintColor { get; set; } = new Color32(85, 136, 254, 230);
+ public virtual Color SelectedCellTintColor { get; set; } = new Color32(40, 86, 240, 255);
+
+ }
+}
diff --git a/StyledGUI/Grid/StyledGridEx.cs b/StyledGUI/Grid/StyledGridEx.cs
new file mode 100644
index 0000000..f0358f7
--- /dev/null
+++ b/StyledGUI/Grid/StyledGridEx.cs
@@ -0,0 +1,125 @@
+using UnityEngine;
+
+namespace StyledGUI
+{
+ public static class StyledGridEx
+ {
+ public static IStyledGrid Row(this IStyledGrid self, GUIStyle style, params GUILayoutOption[] options)
+ {
+ GUILayout.BeginHorizontal(style, options);
+
+ return self;
+ }
+
+ public static IStyledGrid Row(this IStyledGrid self, params GUILayoutOption[] options)
+ {
+ GUILayout.BeginHorizontal(Styles.RowStyle, options);
+
+ return self;
+ }
+
+ public static IStyledGrid EndRow(this IStyledGrid self)
+ {
+ GUILayout.EndHorizontal();
+
+ return self;
+ }
+
+ public static IStyledGrid EmptyRow(this IStyledGrid self, params GUILayoutOption[] options)
+ {
+ GUILayout.BeginHorizontal(Styles.StaticRowStyle, options);
+ GUILayout.Label(" ", Styles.RowHeaderStyle);
+ GUILayout.EndHorizontal();
+
+ return self;
+ }
+
+ public static IStyledGrid VerticalStack(this IStyledGrid self, params GUILayoutOption[] options)
+ {
+ GUILayout.BeginVertical(Styles.StaticRowStyle, options);
+
+ return self;
+ }
+
+ public static IStyledGrid EndVerticalStack(this IStyledGrid self, params GUILayoutOption[] options)
+ {
+ GUILayout.EndVertical();
+
+ return self;
+ }
+
+ public static IStyledGrid Cell(this IStyledGrid self, string text, GUIStyle style, params GUILayoutOption[] options)
+ {
+ GUILayout.Label(text, style, options);
+
+ return self;
+ }
+
+ public static IStyledGrid Cell(this IStyledGrid self, string text, params GUILayoutOption[] options)
+ {
+ GUILayout.Label(text, Styles.CellStyle, options);
+
+ return self;
+ }
+
+ public static IStyledGrid Cell(this IStyledGrid self, string text, Color color, params GUILayoutOption[] options)
+ {
+ var prevColor = GUI.backgroundColor;
+ GUI.backgroundColor = color;
+
+ GUILayout.Label("" + text + "", Styles.CellStyle, options);
+
+ GUI.backgroundColor = prevColor;
+
+ return self;
+ }
+
+ public static IStyledGrid Cell(this IStyledGrid self, string text, GUIStyle style, Color color, params GUILayoutOption[] options)
+ {
+ var prevColor = GUI.backgroundColor;
+ GUI.backgroundColor = color;
+
+ GUILayout.Label("" + text + "", style, options);
+
+ GUI.backgroundColor = prevColor;
+
+ return self;
+ }
+
+ public static IStyledGrid RowHeader(this IStyledGrid self, string text, GUIStyle style, params GUILayoutOption[] options)
+ {
+ GUILayout.Label("" + text + "", style, options);
+
+ return self;
+ }
+
+ public static IStyledGrid RowHeader(this IStyledGrid self, string text, params GUILayoutOption[] options)
+ {
+ GUILayout.Label("" + text + "", Styles.RowHeaderStyle, options);
+
+ return self;
+ }
+
+
+ public static IStyledGrid DrawHorizontalLine(this IStyledGrid self, float alpha = 0.3f)
+ {
+ Graphics.DrawHorizontalLine(alpha);
+
+ return self;
+ }
+
+ public static IStyledGrid DrawHorizontalLine(this IStyledGrid self, float alpha, float width)
+ {
+ Graphics.DrawHorizontalLine(alpha, width);
+
+ return self;
+ }
+
+ public static IStyledGrid Space(this IStyledGrid self, float size)
+ {
+ GUILayout.Space(size);
+
+ return self;
+ }
+ }
+}
diff --git a/StyledGUI/Grid/VirtualGrid.cs b/StyledGUI/Grid/VirtualGrid.cs
new file mode 100644
index 0000000..c5ad0ac
--- /dev/null
+++ b/StyledGUI/Grid/VirtualGrid.cs
@@ -0,0 +1,219 @@
+using System.Collections.Generic;
+using System.Linq;
+using System;
+using Modding.Humankind.DevTools;
+using UnityEngine;
+using StyledGUI.VirtualGridElements;
+
+namespace StyledGUI
+{
+ public enum VirtualGridAlternateType
+ {
+ None,
+ Columns,
+ Rows
+ }
+
+ public enum VirtualGridSelectionType
+ {
+ None,
+ SingleCell,
+ OptionalSingleCell
+ }
+
+ public class VirtualGrid
+ {
+ public VirtualGridAlternateType AlternateType { get; set; } = VirtualGridAlternateType.Columns;
+ public Column[] Columns { get; set; }
+ public Section[] Sections { get; set; }
+ public IStyledGrid Grid { get => _grid; set => SetStyledGrid(value); }
+ public bool DrawSectionHeaders { get; set; } = true;
+ public bool DrawRowHeaders { get; set; } = true;
+ public GUILayoutOption RowHeaderCellSpan { get; set; } = null;
+ public GUILayoutOption ColumnCellSpan { get; set; } = null;
+ public float SectionHorizontalLineWidth { get; set; } = -1f;
+ public float ColumnGap { get; set; } = 4f;
+ ///
+ /// Horizontal visibility distribution
+ ///
+ public int[] Distribution { get => _distribution; set => SetDistribution(value, true); }
+ ///
+ /// Visibility of sections
+ ///
+ public int[] VisibleViews { get; set; } = null;
+ public bool ExpandWidthOnSingleColumnGrid { get; set; } = true;
+ public Vector2 TargetCellPosition { get; private set; } = Vector2.zero;
+
+ public bool IsLookingForCell => _isLookingForCell && Event.current.type == EventType.Repaint;
+ public GUILayoutOption DefaultCellSpan { get; private set; }
+
+ public VirtualGridCursor Cursor
+ {
+ get => _cursor;
+ set
+ {
+ _cursor = value;
+ _cursor.Initialize(this);
+ }
+ }
+
+ private static GUILayoutOption LooseCellSpan { get; } = GUILayout.ExpandWidth(true);
+ private int[] _distribution = null;
+ private bool _isExplicitDistribution = false;
+ private IStyledGrid _grid;
+ private bool _isLookingForCell = false;
+ private Action OnTargetCellFound { get; set; }
+ private Action OnTargetCellNotFound { get; set; }
+ private bool _isAnyCellFound = false;
+ private VirtualGridCursor _cursor = new VirtualGridCursor();
+
+ public void FindCellAtPosition(Vector2 position, Action callbackOnSuccess, Action callbackOnFailure = null)
+ {
+ _isLookingForCell = true;
+ TargetCellPosition = position;
+ OnTargetCellFound = callbackOnSuccess;
+ OnTargetCellNotFound = callbackOnFailure;
+ _isAnyCellFound = false;
+ }
+
+ public void Render()
+ {
+ if (_distribution == null || (!_isExplicitDistribution && _distribution.Length != Columns.Length))
+ SetDistribution(Columns.Select((e, i) => i).ToArray());
+
+ if (Columns.Length < 1) return;
+
+ Cursor.Reset();
+ UpdateColumnCellSpan();
+
+ for (var sectionIndex = 0; sectionIndex < Sections.Length; sectionIndex++)
+ {
+ ref var section = ref Sections[sectionIndex];
+
+ if (VisibleViews != null && !VisibleViews.Contains(section.View))
+ {
+ Cursor.RowIndex += section.Rows?.Length ?? 0;
+ Cursor.SectionIndex++;
+ continue;
+ }
+
+
+
+ // START drawing Section header
+ if (section.SpaceBefore != 0)
+ {
+ Grid.Space(section.SpaceBefore);
+ Cursor.SyncXY();
+ Cursor.Y += Cursor.LastHeight;
+ }
+ if (DrawSectionHeaders && section.Title.Length > 0)
+ {
+ if (DrawRowHeaders)
+ {
+ Grid.Row(Styles.StaticRowStyle)
+ .VerticalStack()
+ .RowHeader(section.Title, RowHeaderCellSpan)
+ .DrawHorizontalLine(0.5f, SectionHorizontalLineWidth)
+ .EndVerticalStack()
+ .EndRow();
+ }
+ else
+ {
+ Grid.Row(Styles.StaticRowStyle)
+ .RowHeader(section.Title, RowHeaderCellSpan)
+ .EndRow();
+ }
+ Cursor.SyncXY();
+ Cursor.Y += Cursor.LastHeight;
+ }
+ //
+
+ for (var rowIndex = 0; rowIndex < section.Rows.Length; rowIndex++)
+ {
+ var row = section.Rows[rowIndex];
+
+ Cursor.SectionRowIndex = rowIndex;
+ Cursor.X = 0;
+
+ // START drawing Row
+ Grid.Row(row.Style ?? Styles.RowStyle);
+ if (DrawRowHeaders)
+ {
+ Grid.RowHeader(row.Title, RowHeaderCellSpan);
+ Cursor.SyncXY();
+ Cursor.X += Cursor.LastWidth;
+ }
+
+ Distribution
+ .Select(index => row.Cells.ElementAt(index))
+ .Render(this, true);
+ Grid.EndRow();
+ //
+
+ Cursor.X = 0;
+ Cursor.Y += Cursor.LastHeight;
+ Cursor.RowIndex++;
+ Cursor.VisibleRowIndex++;
+ }
+
+ Cursor.VisibleSectionIndex++;
+ Cursor.SectionIndex++;
+ }
+
+ if (IsLookingForCell)
+ {
+ if (!_isAnyCellFound)
+ OnTargetCellNotFound?.Invoke();
+
+ _isLookingForCell = false;
+ _isAnyCellFound = false;
+ TargetCellPosition = Vector2.zero;
+ OnTargetCellFound = null;
+ OnTargetCellNotFound = null;
+ }
+ }
+
+ public static void TriggerHitOnCell(ICell cell, VirtualGrid grid)
+ {
+ if (!grid.IsLookingForCell)
+ return;
+
+ grid._isAnyCellFound = true;
+ try
+ {
+ grid.OnTargetCellFound?.Invoke(cell);
+ }
+ catch (Exception ex)
+ {
+ Loggr.Log(ex);
+ }
+ }
+
+ private void SetStyledGrid(IStyledGrid grid)
+ {
+ _grid = grid;
+ if (RowHeaderCellSpan == null)
+ RowHeaderCellSpan = _grid.CellSpan6;
+ if (SectionHorizontalLineWidth < 0)
+ SectionHorizontalLineWidth = _grid.GetCellWidth() * 6;
+ }
+
+ private void UpdateColumnCellSpan()
+ {
+ DefaultCellSpan = Columns.Length == 1 && ExpandWidthOnSingleColumnGrid
+ ? ColumnCellSpan ?? LooseCellSpan
+ : ColumnCellSpan ?? _grid.CellSpan4;
+
+ if (Columns.Length == 1 && ExpandWidthOnSingleColumnGrid)
+ RowHeaderCellSpan = LooseCellSpan;
+ }
+
+ private void SetDistribution(int[] distribution, bool isExplicit = false)
+ {
+ if (isExplicit)
+ _isExplicitDistribution = true;
+
+ _distribution = distribution;
+ }
+ }
+}
diff --git a/StyledGUI/Grid/VirtualGridCursor.cs b/StyledGUI/Grid/VirtualGridCursor.cs
new file mode 100644
index 0000000..3333bce
--- /dev/null
+++ b/StyledGUI/Grid/VirtualGridCursor.cs
@@ -0,0 +1,197 @@
+using System;
+using System.Linq;
+using Modding.Humankind.DevTools;
+using StyledGUI.VirtualGridElements;
+using UnityEngine;
+
+namespace StyledGUI
+{
+ public class VirtualGridCell
+ {
+ public int RowIndex { get; set; }
+ public int CellIndex { get; set; }
+ public int ColumnIndex { get; set; }
+ public ICell Cell { get; set; }
+ }
+
+ public class VirtualGridCursor
+ {
+ public event Action OnSelectionChange;
+
+ public VirtualGridSelectionType SelectionType { get; set; } = VirtualGridSelectionType.None;
+
+ public VirtualGridCell DefaultSelectedCell { get; set; } = new VirtualGridCell();
+
+ public VirtualGrid Owner { get; private set; }
+
+ ///
+ /// Index of Section[] currently being drawn or the one in which the action is triggered.
+ ///
+ public int SectionIndex { get; set; }
+
+ ///
+ /// Section[]'s current index, not taking into account those sections filtered out using the VisibleViews property.
+ ///
+ public int VisibleSectionIndex { get; set; }
+
+ ///
+ /// The same as SectionIndex but for Rows instead.
+ ///
+ public int RowIndex { get; set; }
+
+ ///
+ /// The same as VisibleSectionIndex but for Rows instead.
+ ///
+ public int VisibleRowIndex { get; set; }
+
+ public int ColumnIndex { get; set; }
+
+ public int VisibleColumnIndex { get; set; }
+
+ ///
+ /// Index of Cell within the within a CellGroup, or 0 if there's a single Cell within the Column in that row.
+ ///
+ public int CellIndex { get; set; }
+
+ ///
+ /// RowIndex within it's section
+ ///
+ public int SectionRowIndex { get; set; }
+
+ public bool IsSelectionActive { get; private set; } = false;
+
+ public float X { get; set; }
+
+ public float Y { get; set; }
+
+ public float LastWidth { get; set; }
+
+ public float LastHeight { get; set; }
+
+ private VirtualGridCell SelectedGridCell { get; set; }
+ private bool _initialized = false;
+
+ private ICell GetCurrentCell()
+ {
+ ICell currentCell = null;
+ try
+ {
+ currentCell = Owner.Sections[SectionIndex].Rows[SectionRowIndex].Cells.ElementAt(CellIndex);
+
+ if (currentCell is Clickable4xCell cell)
+ {
+ Loggr.Log(cell.Title, ConsoleColor.Green);
+ }
+ }
+ catch (Exception e)
+ {
+ Loggr.Log(e);
+ Loggr.Log(this);
+ Loggr.Log(Owner.Sections[SectionIndex]);
+ Loggr.Log(Owner.Sections[SectionIndex].Rows.Length.ToString());
+ }
+
+ return currentCell;
+ }
+
+ public void Reset()
+ {
+ SectionIndex = 0;
+ ColumnIndex = 0;
+ RowIndex = 0;
+ CellIndex = 0;
+ VisibleSectionIndex = 0;
+ VisibleRowIndex = 0;
+ Y = 0;
+ X = 0;
+ }
+
+ public void Initialize(VirtualGrid owner)
+ {
+ if (_initialized)
+ throw new NotSupportedException("VirtualGridCursor already initialized.");
+
+ Owner = owner;
+
+ if (SelectionType == VirtualGridSelectionType.SingleCell)
+ {
+ SelectedGridCell = DefaultSelectedCell;
+ IsSelectionActive = true;
+ }
+
+ _initialized = true;
+ }
+
+ public void SyncXY()
+ {
+ if (Event.current.type != EventType.Repaint)
+ return;
+
+ var r = GUILayoutUtility.GetLastRect();
+
+ X = r.x;
+ Y = r.y;
+ LastWidth = r.width;
+ LastHeight = r.height;
+ }
+
+ public VirtualGridCell SelectedCell => SelectedGridCell;
+
+ public void AddToSelection()
+ {
+ switch (SelectionType)
+ {
+ case VirtualGridSelectionType.SingleCell:
+ case VirtualGridSelectionType.OptionalSingleCell:
+ IsSelectionActive = true;
+ SelectedGridCell = new VirtualGridCell()
+ {
+ RowIndex = RowIndex,
+ ColumnIndex = ColumnIndex,
+ CellIndex = CellIndex,
+ Cell = GetCurrentCell()
+ };
+ InvokeOnSelectionChange();
+
+ break;
+ case VirtualGridSelectionType.None:
+ IsSelectionActive = false;
+ break;
+ }
+ }
+
+ public void ClearSelection()
+ {
+ switch (SelectionType)
+ {
+ case VirtualGridSelectionType.OptionalSingleCell:
+ IsSelectionActive = false;
+ SelectedGridCell = null;
+ break;
+ case VirtualGridSelectionType.SingleCell:
+ IsSelectionActive = true;
+ SelectedGridCell = DefaultSelectedCell;
+ break;
+ }
+
+ InvokeOnSelectionChange();
+ }
+
+
+ public bool IsCurrentCellSelected =>
+ IsSelectionActive &&
+ SelectedGridCell.RowIndex == RowIndex &&
+ SelectedGridCell.ColumnIndex == ColumnIndex &&
+ SelectedGridCell.CellIndex == CellIndex;
+
+ private void InvokeOnSelectionChange()
+ {
+ OnSelectionChange += Dummy;
+ if (!BepInEx.Utility.TryDo(OnSelectionChange, out Exception ex))
+ Loggr.Log(ex);
+ OnSelectionChange -= Dummy;
+ }
+
+ private static void Dummy() { }
+ }
+}
\ No newline at end of file
diff --git a/StyledGUI/Grid/VirtualGridElements.cs b/StyledGUI/Grid/VirtualGridElements.cs
new file mode 100644
index 0000000..c3c716d
--- /dev/null
+++ b/StyledGUI/Grid/VirtualGridElements.cs
@@ -0,0 +1,116 @@
+using System.Collections.Generic;
+using System.Linq;
+using System;
+using UnityEngine;
+
+namespace StyledGUI.VirtualGridElements
+{
+ public interface ICell
+ {
+
+ }
+
+ public interface IElement
+ {
+
+ }
+
+ public class Column
+ {
+ public string Name { get; set; }
+ }
+
+ public class Section
+ {
+ public static Section Empty = new Section() { Rows = new []{ Row.Empty } };
+
+ public string Title { get; set; } = string.Empty;
+ public Row[] Rows { get; set; }
+ public float SpaceBefore { get; set; } = 16f;
+ public int View { get; set; } = 0;
+ }
+
+ public class Row
+ {
+ public static Row Empty = new Row();
+
+ public string Title { get; set; } = string.Empty;
+ public IEnumerable Cells { get; set; }
+ public GUIStyle Style { get; set; } = null;
+ }
+
+ public class CellGroup : ICell
+ {
+ public ICell[] Cells { get; set; }
+ }
+
+ public class ClickableCell : ICell
+ {
+ public Action Action { get; set; }
+ public string Text { get; set; }
+ public Color Color { get; set; } = Color.white;
+ public int? Index { get; set; } = null;
+ public GUILayoutOption Span { get; set; } = null;
+ public GUIStyle Style { get; set; } = null;
+ public bool Enabled { get; set; } = true;
+ }
+
+ public class KeyboardShortcutCell : ICell
+ {
+ public KeyboardShortcutField Field { get; set; }
+ public Action Action { get; set; }
+ public int? Index { get; set; } = null;
+ public Color Color { get; set; } = Color.white;
+ public GUILayoutOption Span { get; set; } = null;
+ public GUIStyle Style { get; set; } = null;
+ public bool Enabled { get; set; } = true;
+ }
+
+ public class Cell : ICell
+ {
+ public string Text { get; set; }
+ public GUILayoutOption Span { get; set; } = null;
+ public GUIStyle Style { get; set; } = null;
+ }
+
+ public class CompositeCell : ICell
+ {
+ public IElement[] Elements { get; set; }
+ public GUILayoutOption Span { get; set; } = null;
+ public GUIStyle Style { get; set; } = null;
+ }
+
+ public class TintableCell : ICell
+ {
+ public string Text { get; set; }
+ public GUILayoutOption Span { get; set; } = null;
+ public Color BackgroundColor { get; set; } = UnityEngine.Color.clear;
+ public string Color { get; set; } = "#FFFFFFFF";
+ public GUIStyle Style { get; set; } = null;
+ }
+
+ public class Clickable4xCell : ICell
+ {
+ public string Title { get; set; }
+ public string Subtitle { get; set; }
+ public string Tags { get; set; }
+ public string Category { get; set; }
+ public string UniqueName { get; set; }
+ public Texture Image { get; set; }
+ public Action Action { get; set; }
+ public GUILayoutOption Span { get; set; } = null;
+ public GUIStyle Style { get; set; } = null;
+ public bool Enabled { get; set; } = true;
+ }
+
+ public class TextElement : IElement
+ {
+ public string Text { get; set; }
+ }
+
+ public class ImageElement : IElement
+ {
+ public Texture Image { get; set; }
+ public float Size { get; set; } = 14f;
+ }
+}
diff --git a/StyledGUI/Grid/VirtualGridEx.cs b/StyledGUI/Grid/VirtualGridEx.cs
new file mode 100644
index 0000000..37a3975
--- /dev/null
+++ b/StyledGUI/Grid/VirtualGridEx.cs
@@ -0,0 +1,300 @@
+using System;
+using UnityEngine;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using Modding.Humankind.DevTools;
+
+namespace StyledGUI.VirtualGridElements
+{
+ public static class VirtualGridEx
+ {
+ public static IEnumerable Render(this IEnumerable sequence, VirtualGrid grid, bool addColumnGap = false)
+ {
+ bool drawGap = false;
+ int count = sequence.Count();
+
+ grid.Cursor.CellIndex = 0;
+
+ for (var i = 0; i < count; i++)
+ {
+ if (addColumnGap)
+ {
+ grid.Cursor.VisibleColumnIndex = i;
+ grid.Cursor.ColumnIndex = grid.Distribution[i];
+ }
+
+ ICell element = sequence.ElementAt(i);
+
+ if (drawGap && grid.ColumnGap != 0)
+ GUILayout.Space(grid.ColumnGap);
+
+ if (element is Cell cell)
+ {
+ cell.Render(grid);
+ }
+ else if (element is TintableCell tintableCell)
+ {
+ tintableCell.Render(grid);
+ }
+ else if (element is CellGroup cellGroup)
+ {
+ cellGroup.Render(grid);
+ }
+ else if (element is ClickableCell clickableCell)
+ {
+ clickableCell.Render(grid);
+ }
+ else if (element is KeyboardShortcutCell shortcutCell)
+ {
+ shortcutCell.Render(grid);
+ }
+ else if (element is CompositeCell compositeCell)
+ {
+ compositeCell.Render(grid);
+ }
+ else if (element is Clickable4xCell clickable4XCell)
+ {
+ clickable4XCell.Render(grid);
+ }
+
+ drawGap = addColumnGap;
+ grid.Cursor.SyncXY();
+ grid.Cursor.X += grid.Cursor.LastWidth;
+ grid.Cursor.CellIndex++;
+ }
+
+ return sequence;
+ }
+
+
+
+ public static void Render(this Cell self, VirtualGrid grid)
+ {
+ if (grid.IsLookingForCell)
+ DoCellLookup(self, grid, self.Span ?? grid.DefaultCellSpan);
+
+ var prevTint = GUI.backgroundColor;
+ if (grid.Cursor.IsCurrentCellSelected)
+ GUI.backgroundColor = grid.Grid.SelectedCellTintColor;
+ else
+ AlternateBackgroundColor(grid);
+
+ grid.Grid.Cell(self.Text, self.Style ?? Styles.CellStyle, self.Span ?? grid.DefaultCellSpan);
+
+ GUI.backgroundColor = prevTint;
+ }
+
+ public static void Render(this CellGroup self, VirtualGrid grid)
+ {
+ self.Cells.Render(grid, false);
+ }
+
+ public static void Render(this TintableCell self, VirtualGrid grid)
+ {
+ if (grid.IsLookingForCell)
+ DoCellLookup(self, grid, self.Span ?? grid.DefaultCellSpan);
+
+ var prev = GUI.backgroundColor;
+ GUI.backgroundColor = self.BackgroundColor;
+ grid.Grid.Cell(
+ "" + self.Text + "",
+ self.Style ?? Styles.ColorableCellStyle,
+ self.BackgroundColor,
+ self.Span ?? grid.DefaultCellSpan);
+ GUI.backgroundColor = prev;
+ }
+
+ public static void Render(this ClickableCell self, VirtualGrid grid)
+ {
+ if (grid.IsLookingForCell)
+ DoCellLookup(self, grid, self.Span ?? grid.DefaultCellSpan);
+
+ var prev = GUI.backgroundColor;
+ GUI.backgroundColor = self.Color;
+ GUI.enabled = self.Enabled;
+ if (GUILayout.Button(self.Text, self.Style ?? Styles.CellButtonStyle, self.Span))
+ {
+ self.Action.Invoke(self.Index ?? grid.Cursor.ColumnIndex);
+ }
+
+ GUI.enabled = true;
+ GUI.backgroundColor = prev;
+ }
+
+ public static void Render(this KeyboardShortcutCell self, VirtualGrid grid)
+ {
+ if (grid.IsLookingForCell)
+ DoCellLookup(self, grid, self.Span ?? grid.DefaultCellSpan);
+
+ var prev = GUI.backgroundColor;
+ GUI.backgroundColor = self.Color;
+ GUI.enabled = self.Enabled;
+
+ if (self.Style != null && self.Style != self.Field.Style)
+ self.Field.Style = self.Style;
+
+ if (self.Field.Draw(self.Style, self.Span) && self.Action != null)
+ self.Action.Invoke(self.Index ?? grid.Cursor.ColumnIndex);
+
+ GUI.enabled = true;
+ GUI.backgroundColor = prev;
+ }
+
+ public static void Render(this Clickable4xCell self, VirtualGrid grid)
+ {
+ GUI.enabled = self.Enabled;
+
+ if (grid.IsLookingForCell)
+ DoCellLookup(self, grid, self.Span ?? grid.DefaultCellSpan);
+
+ var prevTint = GUI.backgroundColor;
+
+ if (grid.Cursor.IsCurrentCellSelected)
+ GUI.backgroundColor = grid.Grid.SelectedCellTintColor;
+ else
+ AlternateBackgroundColor(grid);
+
+ using (var cellScope = new GUILayout.HorizontalScope(self.Style ?? Styles.ColorableCellStyle, self.Span ?? grid.DefaultCellSpan))
+ {
+ var r = GUILayoutUtility.GetRect(46f, 40f);
+ GUI.DrawTexture(
+ new Rect(r.x + 6, r.y, 40f, 40f),
+ self.Image ?? Texture2D.grayTexture,
+ ScaleMode.ScaleToFit,
+ true,
+ 1f,
+ Color.white,
+ 0,
+ 0
+ );
+ GUILayout.BeginVertical();
+ {
+ GUILayout.BeginHorizontal();
+ {
+ GUILayout.Label(self.Title, Styles.Fixed20pxHeightTextStyle);
+ GUILayout.FlexibleSpace();
+ GUI.contentColor = Color.yellow;// Styles.GoldTextColor;
+ GUILayout.Label(self.Category, Styles.Fixed20pxHeightTextStyle);
+ GUI.contentColor = Color.white;
+ }
+ GUILayout.EndHorizontal();
+ GUILayout.BeginHorizontal();
+ {
+ GUI.contentColor = Color.grey;
+ GUILayout.Label(self.Subtitle, Styles.Fixed20pxHeightTextStyle);
+ GUI.contentColor = Color.white;
+ GUILayout.FlexibleSpace();
+ GUILayout.Label(self.Tags, Styles.Fixed20pxHeightTextStyle);
+ }
+ GUILayout.EndHorizontal();
+ }
+ GUILayout.EndVertical();
+
+
+ }
+
+ GUI.backgroundColor = prevTint;
+ GUI.enabled = true;
+ }
+
+ public static void Render(this CompositeCell self, VirtualGrid grid)
+ {
+ if (grid.IsLookingForCell)
+ DoCellLookup(self, grid, self.Span ?? grid.DefaultCellSpan);
+
+ var prevTint = GUI.backgroundColor;
+ if (grid.Cursor.IsCurrentCellSelected)
+ GUI.backgroundColor = grid.Grid.SelectedCellTintColor;
+ else
+ AlternateBackgroundColor(grid);
+
+ GUILayout.BeginHorizontal(self.Style ?? Styles.CellStyle, self.Span ?? grid.DefaultCellSpan);
+ GUILayout.FlexibleSpace();
+
+ self.Elements.Render(grid);
+
+ GUILayout.FlexibleSpace();
+ GUILayout.EndHorizontal();
+
+ GUI.backgroundColor = prevTint;
+ }
+
+ public static IEnumerable Render(this IEnumerable sequence, VirtualGrid grid)
+ {
+ int count = sequence.Count();
+
+ for (var i = 0; i < count; i++)
+ {
+ IElement element = sequence.ElementAt(i);
+
+ if (element is TextElement textElement)
+ {
+ textElement.Render(grid);
+ }
+ else if (element is ImageElement imageElement)
+ {
+ imageElement.Render(grid);
+ }
+ }
+
+ return sequence;
+ }
+
+ public static void Render(this TextElement self, VirtualGrid grid)
+ {
+ GUILayout.Label(self.Text, Styles.InlineCellContentStyle);
+ }
+
+ public static void Render(this ImageElement self, VirtualGrid grid)
+ {
+ GUI.DrawTexture(GUILayoutUtility.GetRect(self.Size, self.Size),
+ self.Image, ScaleMode.StretchToFill, true,
+ 1f, grid.Grid.IconTintColor, 0, 0);
+ }
+
+ public static readonly FieldInfo GUILayoutOptionValue =
+ typeof(GUILayoutOption).GetField("value", BindingFlags.NonPublic | BindingFlags.Instance);
+
+ private static bool HitTest(Vector2 pos, VirtualGrid grid, GUILayoutOption span)
+ {
+ bool hit = false;
+
+ if (grid.Cursor.Y <= pos.y && grid.Cursor.X <= pos.x && pos.y <= grid.Cursor.Y + grid.Grid.GetCellHeight())
+ {
+ hit = (grid.Columns.Length == 1 && grid.ExpandWidthOnSingleColumnGrid) ||
+ (pos.x <= grid.Cursor.X + (float) ((object) GUILayoutOptionValue.GetValue(span)));
+ }
+
+ return hit;
+ }
+
+ private static void DoCellLookup(ICell self, VirtualGrid grid, GUILayoutOption span)
+ {
+ if (HitTest(grid.TargetCellPosition, grid, span))
+ {
+ VirtualGrid.TriggerHitOnCell(self, grid);
+ }
+ }
+
+ private static void AlternateBackgroundColor(VirtualGrid grid)
+ {
+ switch (grid.AlternateType)
+ {
+ case VirtualGridAlternateType.Columns:
+ GUI.backgroundColor = grid.Cursor.VisibleColumnIndex % 2 != 0
+ ? grid.Grid.CellTintColorAlt
+ : grid.Grid.CellTintColor;
+ break;
+ case VirtualGridAlternateType.Rows:
+ GUI.backgroundColor = grid.Cursor.SectionRowIndex % 2 != 0
+ ? grid.Grid.CellTintColorAlt
+ : grid.Grid.CellTintColor;
+ break;
+ case VirtualGridAlternateType.None:
+ GUI.backgroundColor = Color.white;
+ break;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/StyledGUI/KeyboardShortcutField.cs b/StyledGUI/KeyboardShortcutField.cs
new file mode 100644
index 0000000..c24d475
--- /dev/null
+++ b/StyledGUI/KeyboardShortcutField.cs
@@ -0,0 +1,125 @@
+using System.Linq;
+using BepInEx.Configuration;
+using UnityEngine;
+
+namespace StyledGUI
+{
+ public class KeyboardShortcutField
+ {
+ public KeyboardShortcut Value { get; private set; } = KeyboardShortcut.Empty;
+ public KeyboardShortcut InitialValue { get; private set; }
+ public GUIStyle Style { get; set; } = Styles.ToggleCaptureStyle;
+
+ private bool initialValueProvided;
+
+ public KeyboardShortcutField() : this(KeyboardShortcut.Empty) {}
+
+ public KeyboardShortcutField(KeyboardShortcut initialValue)
+ {
+ Value = initialValue;
+ InitialValue = initialValue;
+
+ initialValueProvided = !initialValue.Equals(KeyboardShortcut.Empty);
+ }
+
+ public bool IsCapturing { get; private set; } = false;
+
+ public string DefaultText { get; set; } = "";
+
+ private CaptureKeyCombo keyComboCapturer;
+
+ public string DisplayTextPrefix { get; set; } = "";
+ public string DisplayTextPostfix { get; set; } = "";
+ public string DisplayText => DisplayTextPrefix + (Value.Equals(KeyboardShortcut.Empty) ? (initialValueProvided && !IsCapturing ? InitialValue.Serialize() : DefaultText) : Value.Serialize()) + DisplayTextPostfix;
+
+ ///
+ ///
+ ///
+ ///
+ /// true, only one time, just after capturing is done.
+ public bool Draw(GUIStyle style, params GUILayoutOption[] options)
+ {
+ GUI.color = Color.white;
+ var shouldCapture = GUILayout.Toggle(IsCapturing, DisplayText.ToUpper(), style ?? Style, options);
+ if (shouldCapture && !IsCapturing)
+ {
+ // Start capturing
+ keyComboCapturer = new CaptureKeyCombo();
+ IsCapturing = true;
+ }
+
+ if (IsCapturing)
+ {
+ bool isDoneCapturing = keyComboCapturer.Capture();
+
+ Value = keyComboCapturer.KeyCombo;
+ if (isDoneCapturing)
+ {
+ if (Value.Equals(KeyboardShortcut.Empty))
+ Value = InitialValue;
+
+ IsCapturing = false;
+
+ return true;
+ }
+ }
+
+ return false;
+ }
+ }
+
+ public class CaptureKeyCombo
+ {
+ public KeyCode[] stack = new KeyCode[0] {};
+ public KeyCode lastKeyAddedToStack = KeyCode.None;
+
+ public KeyCode[] CapturedKeys = new KeyCode[0] {};
+ public KeyCode CapturedMainKey = KeyCode.None;
+
+ public KeyboardShortcut KeyCombo = KeyboardShortcut.Empty;
+
+ public bool Capture()
+ {
+ KeyCode[] currentStack = KeyboardShortcut.AllKeyCodes.Where(key => Input.GetKey(key)).ToArray();
+
+ if (currentStack.Length == 0)
+ {
+ if (lastKeyAddedToStack == KeyCode.None)
+ return false;
+
+ // KeyCombo captured
+ UpdateKeyCombo();
+ stack = new KeyCode[0] {};
+ lastKeyAddedToStack = KeyCode.None;
+
+ return true;
+ }
+
+ if (currentStack.Length > stack.Length) {
+ // adding KeyCodes to the combo
+ lastKeyAddedToStack = currentStack.Where(k => !stack.Contains(k)).First();
+ stack = currentStack;
+
+ CapturedKeys = stack.Select(k => k).ToArray();
+ CapturedMainKey = lastKeyAddedToStack;
+
+ UpdateKeyCombo();
+ }
+ else
+ {
+ if (currentStack.Length < stack.Length)
+ {
+ stack = currentStack;
+ }
+ }
+
+ return false;
+ }
+
+ private void UpdateKeyCombo()
+ {
+ KeyCombo = new KeyboardShortcut(CapturedMainKey, CapturedKeys.Where(k => k != CapturedMainKey).ToArray());
+ }
+ }
+
+}
diff --git a/StyledGUI/StyledGUIUtility.cs b/StyledGUI/StyledGUIUtility.cs
new file mode 100644
index 0000000..fe8f1f4
--- /dev/null
+++ b/StyledGUI/StyledGUIUtility.cs
@@ -0,0 +1,10 @@
+using System;
+using UnityEngine;
+
+namespace StyledGUI
+{
+ public static class StyledGUIUtility
+ {
+ public static GUISkin DefaultSkin { get; set; }
+ }
+}
diff --git a/StyledGUI/Styles.cs b/StyledGUI/Styles.cs
new file mode 100644
index 0000000..d146b0f
--- /dev/null
+++ b/StyledGUI/Styles.cs
@@ -0,0 +1,224 @@
+using UnityEngine;
+
+namespace StyledGUI
+{
+ public static class Styles
+ {
+ public static Texture2D Alpha65WhitePixel { get; set; } =
+ Graphics.CreateSinglePixelTexture2D(new Color(1f, 1f, 1f, 0.65f));
+ public static Texture2D Alpha35WhitePixel { get; set; } =
+ Graphics.CreateSinglePixelTexture2D(new Color(1f, 1f, 1f, 0.35f));
+ public static Texture2D WhitePixel { get; set; } =
+ Graphics.CreateSinglePixelTexture2D(new Color(1f, 1f, 1f, 1f));
+ public static Texture2D ButtonNormalPixel { get; set; } =
+ Graphics.CreateSinglePixelTexture2D(new Color32(85, 136, 254, 150));
+ public static Texture2D ButtonHoverPixel { get; set; } =
+ Graphics.CreateSinglePixelTexture2D(new Color32(85, 136, 254, 230));
+ public static Texture2D ButtonActivePixel { get; set; } =
+ Graphics.CreateSinglePixelTexture2D(new Color(1f, 1f, 1f, 0.35f));
+ public static Texture2D RowHoverPixel { get; set; } =
+ Graphics.CreateSinglePixelTexture2D(new Color32(85, 136, 254, 70));
+
+ public static Color GreenTextColor { get; set; } = (Color) new Color32(80, 230, 80, 220);
+ public static Color WhiteTextColor { get; set; } = (Color) new Color32(250, 250, 250, 255);
+ public static Color WhitePearlTextColor { get; set; } = (Color) new Color32(200, 200, 200, 255);
+ public static Color BlueTextColor { get; set; } = (Color) new Color32(40, 86, 240, 255);
+ public static Color GoldTextColor { get; set; } = new Color(0.85f, 0.75f, 0f, 0.85f);
+
+ public static GUIStyle RowStyle { get; set; } =
+ new GUIStyle(StyledGUIUtility.DefaultSkin.FindStyle("PopupWindow.Row"))
+ {
+ alignment = TextAnchor.LowerRight,
+ padding = new RectOffset(0, 0, 0, 0),
+ margin = new RectOffset(0, 0, 0, 0),
+ hover = new GUIStyleState()
+ {
+ background = RowHoverPixel,
+ textColor = Color.white
+ }
+ };
+
+ public static GUIStyle StaticRowStyle { get; set; } =
+ new GUIStyle(StyledGUIUtility.DefaultSkin.FindStyle("PopupWindow.Row"))
+ {
+ alignment = TextAnchor.LowerRight,
+ padding = new RectOffset(0, 0, 0, 0),
+ margin = new RectOffset(0, 0, 0, 0),
+ normal = new GUIStyleState()
+ {
+ background = null,
+ textColor = Color.white
+ },
+ hover = new GUIStyleState()
+ {
+ background = null,
+ textColor = Color.white
+ }
+ };
+
+ public static GUIStyle CenteredStaticRowStyle { get; set; } =
+ new GUIStyle(StyledGUIUtility.DefaultSkin.FindStyle("PopupWindow.Row"))
+ {
+ alignment = TextAnchor.LowerCenter,
+ padding = new RectOffset(0, 0, 0, 0),
+ margin = new RectOffset(0, 0, 0, 0),
+ normal = new GUIStyleState()
+ {
+ background = null,
+ textColor = Color.white
+ },
+ hover = new GUIStyleState()
+ {
+ background = null,
+ textColor = Color.white
+ }
+ };
+
+ public static GUIStyle CellStyle { get; set; } =
+ new GUIStyle(StyledGUIUtility.DefaultSkin.FindStyle("PopupWindow.Grid"))
+ {
+ fontSize = 12,
+ normal = new GUIStyleState()
+ {
+ background = Alpha35WhitePixel,
+ textColor = Color.white
+ },
+ hover = new GUIStyleState()
+ {
+ background = null,
+ textColor = Color.white
+ },
+ };
+
+
+ public static GUIStyle ColorableCellStyle { get; set; } =
+ new GUIStyle(StyledGUIUtility.DefaultSkin.FindStyle("PopupWindow.Grid"))
+ {
+ fontSize = 12,
+ normal = new GUIStyleState()
+ {
+ background = Alpha65WhitePixel,
+ textColor = Color.white
+ },
+ hover = new GUIStyleState()
+ {
+ background = WhitePixel,
+ textColor = Color.white
+ }
+ };
+
+ public static readonly RectOffset RectOffsetZero = new RectOffset(0, 0, 0, 0);
+
+ public static GUIStyle InlineCellContentStyle { get; set; } =
+ new GUIStyle(StyledGUIUtility.DefaultSkin.FindStyle("PopupWindow.Grid"))
+ {
+ fontSize = 12,
+ border = RectOffsetZero,
+ padding = RectOffsetZero,
+ margin = RectOffsetZero,
+ overflow = RectOffsetZero,
+ normal = new GUIStyleState()
+ {
+ background = null,
+ textColor = Color.white,
+ },
+ hover = new GUIStyleState()
+ {
+ background = null,
+ textColor = Color.white,
+ },
+ stretchWidth = false
+ };
+
+ public static GUIStyle RowHeaderStyle { get; set; } =
+ new GUIStyle(StyledGUIUtility.DefaultSkin.FindStyle("PopupWindow.Grid"))
+ {
+ fontSize = 12,
+ alignment = TextAnchor.LowerRight,
+ padding = new RectOffset(0, 8, 4, 4),
+ normal = new GUIStyleState()
+ {
+ background = null,
+ textColor = Color.white
+ }
+ };
+
+ public static GUIStyle CellButtonStyle { get; set; } = new GUIStyle(StyledGUIUtility.DefaultSkin.button)
+ {
+ fontSize = 12,
+ margin = StyledGUIUtility.DefaultSkin.FindStyle("PopupWindow.Grid").margin,
+ padding = StyledGUIUtility.DefaultSkin.FindStyle("PopupWindow.Grid").padding,
+ normal = new GUIStyleState()
+ {
+ background = ButtonNormalPixel,
+ textColor = Color.white
+ },
+ hover = new GUIStyleState()
+ {
+ background = ButtonHoverPixel,
+ textColor = Color.white
+ },
+ active = new GUIStyleState()
+ {
+ background = ButtonActivePixel,
+ textColor = BlueTextColor
+ }
+ };
+
+ public static GUIStyle ToggleCaptureStyle { get; set; } = new GUIStyle(StyledGUIUtility.DefaultSkin.toggle) {
+ fontSize = 12,
+ margin = StyledGUIUtility.DefaultSkin.FindStyle("PopupWindow.Grid").margin,
+ padding = StyledGUIUtility.DefaultSkin.FindStyle("PopupWindow.Grid").padding,
+ normal = new GUIStyleState()
+ {
+ background = Alpha35WhitePixel,
+ textColor = GreenTextColor
+ },
+ hover = new GUIStyleState() {
+ background = StyledGUIUtility.DefaultSkin.toggle.hover.background,
+ textColor = WhitePearlTextColor
+ },
+ active = new GUIStyleState() {
+ background = StyledGUIUtility.DefaultSkin.textField.onNormal.background,
+ textColor = WhiteTextColor
+ },
+ onNormal = new GUIStyleState() {
+ background = StyledGUIUtility.DefaultSkin.textField.onNormal.background,
+ textColor = WhiteTextColor
+ },
+ onHover = new GUIStyleState() {
+ background = StyledGUIUtility.DefaultSkin.textField.onNormal.background,
+ textColor = WhiteTextColor
+ },
+ onActive = new GUIStyleState() {
+ background = StyledGUIUtility.DefaultSkin.textField.onNormal.background,
+ textColor = WhiteTextColor
+ },
+ };
+
+ public static GUIStyle Fixed20pxHeightTextStyle { get; set; } =
+ new GUIStyle(StyledGUIUtility.DefaultSkin.FindStyle("PopupWindow.Grid"))
+ {
+ fontSize = 12,
+ border = RectOffsetZero,
+ padding = new RectOffset(6, 6, 0, 0),
+ margin = RectOffsetZero,
+ overflow = RectOffsetZero,
+ fixedHeight = 20f,
+ alignment = TextAnchor.MiddleLeft,
+ richText = true,
+ wordWrap = false,
+ normal = new GUIStyleState()
+ {
+ background = null,
+ textColor = Color.white,
+ },
+ hover = new GUIStyleState()
+ {
+ background = null,
+ textColor = Color.white,
+ },
+ stretchWidth = false
+ };
+ }
+}
diff --git a/TROUBLESHOOTING.md b/TROUBLESHOOTING.md
new file mode 100644
index 0000000..e69de29
diff --git a/UI/BackScreen/BackScreenWindow.cs b/UI/BackScreen/BackScreenWindow.cs
new file mode 100644
index 0000000..e10da50
--- /dev/null
+++ b/UI/BackScreen/BackScreenWindow.cs
@@ -0,0 +1,183 @@
+using System;
+using Amplitude.Framework.Overlay;
+using Amplitude.Framework.Runtime;
+using Amplitude.Mercury.Overlay;
+using Amplitude.UI;
+using BepInEx.Configuration;
+using Modding.Humankind.DevTools;
+using UnityEngine;
+using Modding.Humankind.DevTools.DeveloperTools.UI;
+using StyledGUI;
+
+namespace DevTools.Humankind.GUITools.UI
+{
+ public class BackScreenWindow : BackScreenWindowBase
+ {
+ public override bool ShouldBeVisible => true;
+ public override bool ShouldRestoreLastWindowPosition => false;
+ public override string UniqueName => "BackScreenWindow";
+ public Rect MinWindowRect { get; set; } = new Rect (0, 0, Screen.width, 24f);
+ public Rect MaxWindowRect { get; set; } = new Rect (0, 0, Screen.width, Screen.height);
+
+ protected bool IsToolboxVisible = false;
+
+ public bool IsInGame { get; private set; } = false;
+
+ public bool IsInLoadingScreen => Amplitude.Mercury.LoadingScreen.Visible;
+
+ protected bool Initialized = false;
+ protected bool InitializedInGame = false;
+ private bool _wasLiveEditorEnabled;
+
+
+ protected virtual void Initialize()
+ {
+ ScreenOverlay.SetInnerRectAsVisible(false);
+ OnCollapse();
+
+ Initialized = true;
+ }
+
+ protected virtual void InitializeInGame()
+ {
+ LiveEditorMode.Initialize();
+ ScreenOverlay.SetInnerRectAsVisible(false);
+ ToolboxController.Initialize(this);
+
+ InitializedInGame = true;
+ }
+
+ public GUIStyle ScreenTag { get; set; } = new GUIStyle(Styles.ColorableCellStyle)
+ {
+ margin = new RectOffset(2, 0, 0, 0),
+ padding = new RectOffset(8, 8, 4, 4),
+ fontSize = 10
+ };
+
+ public override void OnDrawUI(int _)
+ {
+ // TODO: RuntimeGameState.Refresh();
+
+ GUILayout.BeginArea(new Rect(0f, 0f, WindowRect.width, WindowRect.height));
+ GUILayout.BeginHorizontal();
+
+ GUILayout.BeginVertical();
+
+ GUILayout.Space(2f);
+
+ GUILayout.BeginHorizontal();
+ {
+ GUILayout.FlexibleSpace();
+ GUILayout.BeginHorizontal();
+ {
+ GUI.backgroundColor = Color.black;
+
+ if (IsInGame && LiveEditorMode.Enabled)
+ {
+ GUILayout.Label("LIVE EDITOR MODE", ScreenTag);
+ if (LiveEditorMode.BrushType != LiveBrushType.None)
+ GUILayout.Label("BRUSH TYPE: " + LiveEditorMode.BrushType.ToString().ToUpper() + "", ScreenTag);
+ if (PaintBrush.ActionNameOnCreate != string.Empty)
+ GUILayout.Label("ON PAINT: " + PaintBrush.ActionNameOnCreate + "", ScreenTag);
+ if (PaintBrush.ActionNameOnCreate != string.Empty)
+ GUILayout.Label("ON ERASE: " + PaintBrush.ActionNameOnDestroy + "", ScreenTag);
+ }
+
+ GUI.backgroundColor = Color.white;
+ }
+ GUILayout.EndHorizontal();
+ GUILayout.FlexibleSpace();
+ }
+ GUILayout.EndHorizontal();
+
+
+ if (IsInGame)
+ {
+ SyncInGameUI();
+ LiveEditorMode.HexPainter.IsVisible =
+ LiveEditorMode.Enabled && LiveEditorMode.EditorMode == EditorModeType.TilePainter;
+ LiveEditorMode.HexPainter.Draw();
+
+ if (LiveEditorMode.Enabled)
+ {
+ if (Event.current.type == EventType.Repaint)
+ LiveEditorMode.Run();
+
+
+
+ if (IsToolboxVisible != ToolboxController.Draw())
+ {
+ IsToolboxVisible = !IsToolboxVisible;
+
+ ScreenOverlay
+ .SetInnerRect(ToolboxController.ToolboxRect)
+ .SetInnerRectAsVisible(IsToolboxVisible);
+
+ if (IsToolboxVisible)
+ {
+ OnExpand();
+ }
+ else
+ {
+ OnCollapse();
+ }
+ }
+ }
+ }
+
+
+ GUILayout.EndVertical();
+
+ GUILayout.EndHorizontal();
+ GUILayout.EndArea();
+ }
+
+ private void SyncInGameUI()
+ {
+ if (_wasLiveEditorEnabled != LiveEditorMode.Enabled)
+ {
+ if (LiveEditorMode.Enabled)
+ {
+ //ScreenLocker.LockFullScreenMouseEvents = true;
+ }
+ else
+ {
+ IsToolboxVisible = false;
+ ScreenOverlay.SetInnerRectAsVisible(false);
+ ToolboxController.IsSticked = false;
+ ScreenLocker.LockFullScreenMouseEvents = false;
+ OnCollapse();
+ }
+ _wasLiveEditorEnabled = LiveEditorMode.Enabled;
+ }
+ }
+
+ public override void OnZeroGUI()
+ {
+ if (!Initialized)
+ Initialize();
+
+ bool isInGame = Amplitude.Mercury.Presentation.Presentation.IsPresentationRunning;
+
+ if (isInGame != IsInGame)
+ {
+ if (isInGame && !InitializedInGame)
+ InitializeInGame();
+
+ IsInGame = isInGame;
+ }
+ }
+
+ public void OnCollapse()
+ {
+ GUI.BringWindowToBack(WindowID);
+ WindowRect = MinWindowRect;
+ }
+
+ public void OnExpand()
+ {
+ GUI.BringWindowToFront(WindowID);
+ WindowRect = MaxWindowRect;
+ }
+ }
+}
diff --git a/UI/BackScreen/BackScreenWindowBase.cs b/UI/BackScreen/BackScreenWindowBase.cs
new file mode 100644
index 0000000..33e1190
--- /dev/null
+++ b/UI/BackScreen/BackScreenWindowBase.cs
@@ -0,0 +1,84 @@
+using System;
+using Amplitude.Framework.Overlay;
+using Amplitude.Framework.Runtime;
+using Amplitude.Mercury.Overlay;
+using Amplitude.UI;
+using Modding.Humankind.DevTools;
+using UnityEngine;
+using Modding.Humankind.DevTools.DeveloperTools.UI;
+
+namespace DevTools.Humankind.GUITools.UI
+{
+ public abstract class BackScreenWindowBase : PopupToolWindow
+ {
+ public virtual Rect WindowRect { get; set; } = new Rect (0, 0, Screen.width, Screen.height);
+ public virtual string WindowGUIStyle { get; set; } = "PopupWindow.Sidebar";
+ public ScreenUIOverlay ScreenOverlay { get; set; }
+ public abstract string UniqueName { get; }
+ public int WindowID => Math.Abs(GetInstanceID());
+
+ public abstract void OnDrawUI(int _);
+
+ public abstract void OnZeroGUI();
+
+ protected int loop = 0;
+ protected int maxLoop = 40;
+
+ protected override void Awake()
+ {
+ WindowStartupLocation = new Vector2(WindowRect.x, WindowRect.y);
+ Title = string.IsNullOrEmpty(Title) ? "BACK SCREEN WINDOW" : Title;
+ base.Awake();
+ Width = WindowRect.width;
+ }
+
+ void OnGUI () {
+ GUI.skin = UIController.DefaultSkin;
+ GUI.color = Color.white;
+ GUI.backgroundColor = Color.white;
+ GUI.enabled = true;
+
+ if (Event.current.type == EventType.Repaint)
+ {
+ if (loop == 0)
+ {
+ SyncScreenUIOverlay();
+ OnZeroGUI();
+ }
+
+ if (loop++ > maxLoop)
+ loop = 0;
+ }
+ WindowRect = GUI.Window (WindowID, WindowRect, OnDrawUI, string.Empty, WindowGUIStyle);
+ }
+
+ public void SyncScreenUIOverlay()
+ {
+ if (ScreenOverlay == null)
+ {
+ ScreenOverlay = ScreenUIOverlay.Find(UniqueName).FullScreenSync();
+ }
+ else
+ {
+ ScreenOverlay.FullScreenSync();
+ }
+ }
+
+ protected override void OnBecomeVisible() { }
+ protected override void OnBecomeInvisible() { }
+
+ public override Rect GetWindowRect() => WindowRect;
+
+ public override void SetWindowRect(Rect rect)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override void Close(bool saveVisibilityStateBeforeClosing = false)
+ {
+ ToolboxController.Unload();
+ ScreenUIOverlay.Unload();
+ base.Close(false);
+ }
+ }
+}
diff --git a/UI/BackScreen/HexOverlay.cs b/UI/BackScreen/HexOverlay.cs
new file mode 100644
index 0000000..38c37fb
--- /dev/null
+++ b/UI/BackScreen/HexOverlay.cs
@@ -0,0 +1,88 @@
+using Amplitude.Graphics;
+using Amplitude.Mercury.AI;
+using Amplitude.Mercury.Terrain;
+using Amplitude.Mercury.Interop.AI.Data;
+using Amplitude.Mercury.Presentation;
+using System;
+using Amplitude;
+using Amplitude.Mercury;
+using Amplitude.Mercury.Interop.AI;
+using Modding.Humankind.DevTools;
+using UnityEngine;
+
+namespace DevTools.Humankind.GUITools.UI
+{
+ public class HexOverlay : ITileEx
+ {
+ public TerrainDebuggingService HexDrawingService { get; set; }
+ public int DebugLayerID { get; set; }
+
+ public bool IsVisible { get; set; } = true;
+
+ private int PrevTileIndex { get; set; } = 0;
+
+ public Color HexColor { get; set; } = new Color(1f, 1f, 1f, 0.3f);
+
+ public int TileIndex { get; set; } = 0;
+ public Tile Tile { get; set; }
+
+ public Hexagon.OffsetCoords OffsetCoords { get; private set; } = new Hexagon.OffsetCoords(0, 0);
+
+ private Action OnTileChange { get; set; }
+
+ private bool _clear = true;
+
+ public HexOverlay(Action onTileChange)
+ {
+ OnTileChange = onTileChange;
+ }
+
+ public void Draw()
+ {
+ if (HexDrawingService == null)
+ {
+ HexDrawingService = RenderContextAccess.GetInstance(0);
+ DebugLayerID = HexDrawingService.BindDebugLayer(GetType().ToString());
+ }
+
+ if (IsVisible)
+ {
+ var tileIndex = Presentation.PresentationCursorController.CurrentHighlightedPosition.ToTileIndex();
+ ref Tile local1 = ref Snapshots.World.Tiles[tileIndex];
+
+ DebugControl.CursorPosition = local1.WorldPosition;
+
+ if (!DebugControl.CursorPosition.IsWorldPositionValid())
+ return;
+
+ if (PrevTileIndex != tileIndex)
+ {
+ TileIndex = tileIndex;
+ Tile = Snapshots.World.Tiles[tileIndex];
+ HexDrawingService.ClearHexagon(DebugLayerID, OffsetCoords);
+ OffsetCoords = local1.WorldPosition.ToHexagonOffsetCoords();
+ OnTileChange();
+
+ PrevTileIndex = tileIndex;
+
+ HexDrawingService.SetHexagonBorderColor(DebugLayerID, OffsetCoords, Color.green);
+ HexDrawingService.SetHexagonInnerBorderWidth(DebugLayerID, OffsetCoords, 1f);
+ HexDrawingService.SetHexagonColor(
+ DebugLayerID,
+ OffsetCoords,
+ HexColor);
+
+ HexDrawingService.DisplayDebugLayer(DebugLayerID);
+ _clear = false;
+ }
+ return;
+ }
+
+ if (!_clear)
+ {
+ HexDrawingService.ClearHexagons(DebugLayerID);
+ _clear = true;
+ }
+ }
+ }
+}
diff --git a/UI/BackScreen/LiveEditor/AudioPlayer.cs b/UI/BackScreen/LiveEditor/AudioPlayer.cs
new file mode 100644
index 0000000..5f5651f
--- /dev/null
+++ b/UI/BackScreen/LiveEditor/AudioPlayer.cs
@@ -0,0 +1,31 @@
+using Amplitude;
+using Amplitude.Framework;
+using Amplitude.Wwise.Audio;
+
+namespace DevTools.Humankind.GUITools.UI
+{
+ public static class AudioPlayer
+ {
+ public static StaticString DistrictPlacement { get; set; } =
+ new StaticString("DistrictPlacementCursorClick");
+ public static StaticString MoveArmy { get; set; } =
+ new StaticString("MoveArmyCursorClick");
+ public static StaticString CutForest { get; set; } =
+ new StaticString("CutForestCursorClick");
+ public static StaticString AttackArmy { get; set; } =
+ new StaticString("AttackArmyCursorClick");
+ public static StaticString Ransack { get; set; } =
+ new StaticString("RansackCursorClick");
+
+ public static IAudioModulesService AudioModulesService { get; set; }
+
+
+ public static void Play(StaticString audioName)
+ {
+ if (AudioModulesService == null)
+ AudioModulesService = Services.GetService();
+
+ AudioModulesService.SendAudioEvent(audioName);
+ }
+ }
+}
diff --git a/UI/BackScreen/LiveEditor/ITileEx.cs b/UI/BackScreen/LiveEditor/ITileEx.cs
new file mode 100644
index 0000000..9370663
--- /dev/null
+++ b/UI/BackScreen/LiveEditor/ITileEx.cs
@@ -0,0 +1,78 @@
+using System;
+using System.Linq;
+using Amplitude.Mercury.Interop.AI.Data;
+using Amplitude.Mercury.Interop;
+using Amplitude.Mercury.Sandbox;
+using Modding.Humankind.DevTools;
+using Snapshots = Amplitude.Mercury.Interop.AI.Snapshots;
+using Amplitude.Mercury.Interop.AI.Entities;
+using Newtonsoft.Json.Utilities;
+
+namespace DevTools.Humankind.GUITools.UI
+{
+ public interface ITileEx
+ {
+ int TileIndex { get; set; }
+ Tile Tile { get; set; }
+ }
+
+ [Flags]
+ public enum HexTileType
+ {
+ None = 0,
+ Settlement = 1,
+ CityCenter = 2,
+ District = 4,
+ Army = 8
+ }
+
+ /*public static class ITileExtensions
+ {
+
+ public static bool TryGetSettlement(
+ this ITileEx self,
+ out Settlement owner)
+ {
+ owner = null;
+
+ if (ActionController.TryGetDistrictInfoAt(self.Tile.WorldPosition, out DistrictInfo district))
+ {
+ var empire = HumankindGame.GetEmpireEntityAt(district.EmpireIndex);
+
+ if (empire is MajorEmpire majorEmpire)
+ {
+ foreach (var settlement in majorEmpire.Settlements)
+ {
+ if (settlement.Territories.Any(t => t.TileIndexes.Contains(self.TileIndex)))
+ {
+ owner = settlement;
+ return true;
+ }
+ }
+ }
+ else if (empire is MinorEmpire minorEmpire)
+ {
+ if (minorEmpire.Settlement.Territories.Any(t => t.TileIndexes.Contains(self.TileIndex)))
+ {
+ Loggr.Log("Settlement found within MINOR EMPIRE");
+ owner = minorEmpire.Settlement;
+
+ return true;
+ }
+ }
+ else if (empire is LesserEmpire lesserEmpire)
+ {
+ Loggr.Log(lesserEmpire);
+ Loggr.Log("LesserEmpires does not OWN any settlement/city/territory.", ConsoleColor.Red);
+ }
+ }
+
+ // Snapshots.World.Territories
+
+ // Snapshots.GameSnapshot.PresentationData.LocalEmpireInfo.DistrictInfo
+
+ return false;
+ // return Sandbox.World.TileInfo.Data[settlementTileIndex];
+ }
+ }*/
+}
diff --git a/UI/BackScreen/LiveEditor/LiveEditorMode.cs b/UI/BackScreen/LiveEditor/LiveEditorMode.cs
new file mode 100644
index 0000000..52241f6
--- /dev/null
+++ b/UI/BackScreen/LiveEditor/LiveEditorMode.cs
@@ -0,0 +1,139 @@
+using System;
+using System.Linq;
+using Amplitude;
+using Amplitude.Mercury.Data.Simulation;
+using BepInEx.Configuration;
+using Modding.Humankind.DevTools;
+using Modding.Humankind.DevTools.DeveloperTools.UI;
+using StyledGUI.VirtualGridElements;
+using UnityEngine;
+
+namespace DevTools.Humankind.GUITools.UI
+{
+ [Flags]
+ public enum LiveBrushType
+ {
+ None = 0,
+ Unit = 1,
+ District = 2,
+ NavalUnit = 4,
+ AirUnit = 8,
+ LandUnit = 16,
+ MissileUnit = 32,
+ }
+
+ public enum EditorModeType
+ {
+ TilePainter,
+ Settlement
+ }
+
+ public static class LiveEditorMode
+ {
+ public static readonly string ToolboxPreviewActionName = "ShowToolboxWhileHoldingKey";
+ public static readonly string StickedToolboxActionName = "ToggleStickyToolbox";
+ public static readonly string CreateUnderCursorActionName = "CreateConstructibleUnderCursor";
+ public static readonly string DestroyUnderCursorActionName = "DestroyAnythingUnderCursor";
+ public static readonly string DebugUnderCursorActionName = "DebugTileUnderCursor";
+ public static bool Enabled { get; set; } = false;
+ public static EditorModeType EditorMode { get; set; } = EditorModeType.TilePainter;
+ public static HexOverlay HexPainter { get; set; }
+ public static ConstructibleDefinition ActivePaintBrush { get; private set; } = null;
+ public static LiveBrushType BrushType { get; private set; } = LiveBrushType.None;
+
+ private static KeyboardShortcut CreateKey { get; set; }
+ private static KeyboardShortcut DestroyKey { get; set; }
+ private static KeyboardShortcut DebugKey { get; set; }
+
+ private static PaintBrush BrushPainter { get; set; }
+
+ public static void Initialize()
+ {
+ HexPainter = new HexOverlay(HandleOnTileChange);
+ BrushPainter = new PaintBrush();
+ UpdateKeyMappings();
+ }
+
+ private static void HandleOnTileChange()
+ {
+ BrushPainter.UpdateTile();
+ }
+
+ public static void UpdateKeyMappings()
+ {
+ ToolboxController.ToolboxPreviewKey =
+ KeyMappings.Keys.First(map => map.ActionName == ToolboxPreviewActionName).Key;
+ ToolboxController.StickedToolboxKey =
+ KeyMappings.Keys.First(map => map.ActionName == StickedToolboxActionName).Key;
+
+ CreateKey = KeyMappings.Keys.First(map => map.ActionName == CreateUnderCursorActionName).Key;
+ DestroyKey = KeyMappings.Keys.First(map => map.ActionName == DestroyUnderCursorActionName).Key;
+ DebugKey = KeyMappings.Keys.First(map => map.ActionName == DebugUnderCursorActionName).Key;
+
+ var str = "\nCreateKey = " + CreateKey.Serialize() +
+ "\nDestroyKey = " + DestroyKey.Serialize() + "\n";
+
+ Loggr.Log("\t>>> LiveEditorMode.UpdateKeyMappings()" + str, ConsoleColor.Magenta);
+ }
+
+ public static void UpdatePaintBrush()
+ {
+ var gridCell = ToolboxController.Toolbox.ConstructiblesGrid.VirtualGrid.Cursor.SelectedCell;
+
+ if (gridCell != null && gridCell.Cell is Clickable4xCell cell)
+ {
+ ActivePaintBrush = UIController.GameUtils.GetConstructibleDefinition(new StaticString(cell.UniqueName));
+ }
+ else
+ {
+ ActivePaintBrush = null;
+ }
+ UpdateBrushType();
+ }
+
+ public static void Run()
+ {
+ if (!Enabled)
+ return;
+
+ if (EditorMode == EditorModeType.TilePainter)
+ {
+ if (DebugKey.IsPressed()) BrushPainter.Debug();
+ if (CreateKey.IsPressed()) BrushPainter.Paint();
+ if (DestroyKey.IsPressed()) BrushPainter.Erase();
+ }
+ }
+
+ private static void UpdateBrushType()
+ {
+ BrushType = LiveBrushType.None;
+
+ if (ActivePaintBrush == null)
+ return;
+
+ if (ActivePaintBrush is UnitDefinition)
+ {
+ BrushType = LiveBrushType.Unit;
+
+ if (ActivePaintBrush is AirUnitDefinition) BrushType |= LiveBrushType.AirUnit;
+ if (ActivePaintBrush is MissileUnitDefinition) BrushType |= LiveBrushType.MissileUnit;
+ if (ActivePaintBrush is LandUnitDefinition) BrushType |= LiveBrushType.LandUnit;
+ if (ActivePaintBrush is SettlerUnitDefinition) BrushType |= LiveBrushType.LandUnit;
+ if (ActivePaintBrush is NavalUnitDefinition) BrushType |= LiveBrushType.NavalUnit;
+ if (ActivePaintBrush is NavalTransportDefinition) BrushType |= LiveBrushType.NavalUnit;
+ if (ActivePaintBrush is MissileUnitDefinition) BrushType |= LiveBrushType.MissileUnit;
+ if (ActivePaintBrush is MissileUnitDefinition) BrushType |= LiveBrushType.MissileUnit;
+ if (ActivePaintBrush is MissileUnitDefinition) BrushType |= LiveBrushType.MissileUnit;
+ if (ActivePaintBrush is MissileUnitDefinition) BrushType |= LiveBrushType.MissileUnit;
+ }
+
+ if (ActivePaintBrush is DistrictDefinition)
+ {
+ BrushType = LiveBrushType.District;
+
+ // ...
+ }
+
+ }
+ }
+}
diff --git a/UI/BackScreen/LiveEditor/PaintBrush.cs b/UI/BackScreen/LiveEditor/PaintBrush.cs
new file mode 100644
index 0000000..2f748ea
--- /dev/null
+++ b/UI/BackScreen/LiveEditor/PaintBrush.cs
@@ -0,0 +1,149 @@
+using System;
+using Amplitude;
+using Amplitude.Mercury;
+using Amplitude.Mercury.Interop;
+using Amplitude.Mercury.Interop.AI.Data;
+using Amplitude.Mercury.Presentation;
+using Amplitude.Mercury.Sandbox;
+using Modding.Humankind.DevTools;
+using Snapshots = Amplitude.Mercury.Interop.AI.Snapshots;
+
+namespace DevTools.Humankind.GUITools.UI
+{
+ public partial class PaintBrush : ITileEx
+ {
+ public Tile Tile { get; set; }
+ public int TileIndex { get; set; }
+ private WorldPosition WorldPosition { get; set; }
+ private DistrictInfo District { get; set; }
+
+ public HexTileType HexTile { get; private set; } = HexTileType.None;
+
+ private HexTileType LastHexTile { get; set; } = HexTileType.None;
+ private int LastTileIndex { get; set; }
+
+ public void Paint()
+ {
+ OnCreate?.Invoke();
+ OnCreate = null;
+ ActionNameOnCreate = string.Empty;
+ UpdateTile();
+ }
+
+ public void Erase()
+ {
+ OnDestroy?.Invoke();
+ OnDestroy = null;
+ ActionNameOnDestroy = string.Empty;
+ UpdateTile();
+ }
+
+ private void PrePaint()
+ {
+ var brush = LiveEditorMode.ActivePaintBrush; // ConstructibleDefinition
+ var brushType = LiveEditorMode.BrushType; // LiveBrushType
+
+ if ((brushType | LiveBrushType.Unit) != brushType)
+ {
+ if ((HexTile | HexTileType.Settlement) == HexTile)
+ {
+ if ((HexTile | HexTileType.CityCenter) != HexTile)
+ {
+ // Settlement is an Outpost, then upgrade Outpost to city
+ Create(() => EvolveOutpostToCityAt(TileIndex), EvolveOutpostAction);
+ }
+ }
+ else
+ {
+ // It wasn't a Settlement, paint district or repaint a different one instead
+ if ((brushType | LiveBrushType.District) == brushType)
+ {
+ Create(() => CreateDistrictAt(TileIndex, brush.Name), CreateDistrictAction);
+ }
+ }
+ }
+ else
+ {
+ // brushType is Unit
+ if (Tile.Army == null)
+ {
+ Create(() => CreateArmyAt(TileIndex, brush.Name), CreateArmyAction);
+ }
+ else
+ {
+ Create(() => AddUnitToArmy(TileIndex, brush.Name), AddUnitToArmyAction);
+ }
+ }
+ }
+
+ private void PreErase()
+ {
+ if (HexTile != HexTileType.None)
+ {
+ if ((HexTile | HexTileType.Army) == HexTile)
+ {
+ Destroy(() => RemoveUnitFromArmyAt(TileIndex), RemoveUnitAction, true);
+ }
+ else
+ {
+ if ((HexTile | HexTileType.Settlement) == HexTile)
+ {
+ Destroy(() => DestroySettlementAt(TileIndex), DestroySettlementAction);
+ }
+ else if ((HexTile | HexTileType.District) == HexTile)
+ {
+ Destroy(() => DestroyDistrictAt(TileIndex), DestroyDistrictAction);
+ }
+ }
+ }
+ }
+
+ public void Debug()
+ {
+ Loggr.Log(Tile);
+ Loggr.Log(District);
+ Loggr.Log(HexTile.ToString());
+ if (Tile.Army != null)
+ {
+ Loggr.Log(Tile.Army);
+ PresentationArmy armyAtPosition = Presentation
+ .PresentationEntityFactoryController
+ .GetArmyAtPosition(Presentation.PresentationCursorController.CurrentHighlightedPosition) as PresentationArmy;
+
+ Loggr.Log(armyAtPosition);
+ }
+ }
+
+ public void UpdateTile()
+ {
+ TileIndex = LiveEditorMode.HexPainter.TileIndex;
+ Tile = Snapshots.World.Tiles[TileIndex];
+ WorldPosition = Tile.WorldPosition;
+ HexTile = HexTileType.None;
+
+ if (LastTileIndex != TileIndex)
+ LastTileIndex = 0;
+
+ if (ActionController.TryGetDistrictInfoAt(WorldPosition, out DistrictInfo district))
+ {
+ District = district;
+
+ if (district.DistrictDefinitionName == PresentationDistrict.CampDistrictDefinition ||
+ district.DistrictDefinitionName == PresentationDistrict.BeforeCampDistrictDefinition)
+ HexTile |= HexTileType.Settlement;
+
+ else if (district.DistrictDefinitionName == PresentationDistrict.CityCenterDistrictDefinition)
+ HexTile |= HexTileType.Settlement | HexTileType.CityCenter;
+ else
+ HexTile |= HexTileType.District;
+ }
+
+ if (Tile.Army != null)
+ HexTile |= HexTileType.Army;
+
+ PrePaint();
+ PreErase();
+ }
+
+ }
+}
diff --git a/UI/BackScreen/LiveEditor/PaintBrushActions.cs b/UI/BackScreen/LiveEditor/PaintBrushActions.cs
new file mode 100644
index 0000000..87a54ac
--- /dev/null
+++ b/UI/BackScreen/LiveEditor/PaintBrushActions.cs
@@ -0,0 +1,119 @@
+using Amplitude;
+using Amplitude.Mercury;
+using Amplitude.Mercury.Interop;
+using Amplitude.Mercury.Interop.AI.Data;
+using Amplitude.Mercury.Presentation;
+using Amplitude.Mercury.Sandbox;
+using Amplitude.Mercury.Simulation;
+using Modding.Humankind.DevTools;
+using Action = System.Action;
+using Snapshots = Amplitude.Mercury.Interop.AI.Snapshots;
+
+namespace DevTools.Humankind.GUITools.UI
+{
+ public partial class PaintBrush
+ {
+ // STORED ACTIONS
+ private Action OnCreate { get; set; }
+ private Action OnDestroy { get; set; }
+
+ public static string ActionNameOnCreate { get; private set; } = string.Empty;
+ public static string ActionNameOnDestroy { get; private set; } = string.Empty;
+
+ // ACTION NAME IDENTIFIERS
+ public static readonly string RemoveUnitAction = "REMOVE UNIT FROM ARMY";
+ public static readonly string DestroySettlementAction = "DESTROY SETTLEMENT";
+ public static readonly string DestroyDistrictAction = "DESTROY DISTRICT";
+ public static readonly string EvolveOutpostAction = "EVOLVE OUTPOST";
+ public static readonly string CreateDistrictAction = "CREATE DISTRICT";
+ public static readonly string DetachTerritoryAction = "DETACH TERRITORY";
+ public static readonly string RemoveMinorEmpireAction = "REMOVE MINOR EMPIRE";
+ public static readonly string CreateArmyAction = "REMOVE MINOR EMPIRE";
+ public static readonly string AddUnitToArmyAction = "REMOVE MINOR EMPIRE";
+
+ // DESTROY ACTIONS
+ public static void DestroySettlementAt(int tileIndex) => SandboxManager
+ .PostOrder(new EditorOrderDestroySettlement {SettlementTileIndex = tileIndex});
+
+ public static void DestroyDistrictAt(int tileIndex) => SandboxManager
+ .PostOrder(new EditorOrderRemoveDistrictAt {TileIndex = tileIndex});
+
+ public static void RemoveUnitFromArmyAt(int tileIndex) => SandboxManager
+ .PostOrder(new EditorOrderRemoveUnitFromArmy { ArmyTileIndex = tileIndex, UnitIndex = 0 });
+
+ // CREATE ACTIONS
+ public static void CreateDistrictAt(int tileIndex, StaticString districtDefinitionName) => SandboxManager
+ .PostOrder(new EditorOrderCreateExtensionDistrictAt
+ {
+ TileIndex = tileIndex,
+ DistrictDefinitionName = districtDefinitionName
+ });
+
+ public static void CreateArmyAt(int tileIndex, StaticString unitDefinitionName) => SandboxManager
+ .PostOrder(new OrderSpawnArmy
+ {
+ WorldPosition = Snapshots.World.Tiles[tileIndex].WorldPosition,
+ UnitDefinitions = new []{ unitDefinitionName }
+ });
+
+ public static void AddUnitToArmy(int tileIndex, StaticString unitDefinitionName) => SandboxManager
+ .PostOrder(new OrderAddUnitToArmy()
+ {
+ ArmyGUID = (SimulationEntityGUID) Snapshots.World.Tiles[tileIndex].Army.EntityGUID,
+ UnitDefinition = unitDefinitionName
+ });
+
+
+
+
+
+ // TRANSFORM ACTIONS
+ public static void EvolveOutpostToCityAt(int tileIndex) => SandboxManager
+ .PostOrder(new EditorOrderEvolveCampToCity {CampTileIndex = tileIndex});
+
+ // OTHER ACTIONS
+ public static void RemoveMinorEmpire(int minorEmpireIndex) => SandboxManager
+ .PostOrder(new EditorOrderRemoveMinorEmpire { MinorEmpireIndex = minorEmpireIndex });
+
+ public static void DetachTerritoryFromCity(int cityTileIndex, int administrativeCenterTileIndex) =>
+ SandboxManager.PostOrder(new EditorOrderDetachTerritoryFromCity
+ {
+ CityTileIndex = cityTileIndex,
+ AdiministrativeCenterToDetachTileIndex = administrativeCenterTileIndex
+ });
+
+
+ private void Destroy(Action action, string actionName, bool isRepeatingSameActionAllowed = false)
+ {
+
+ ActionNameOnDestroy = actionName;
+
+ OnDestroy = () =>
+ {
+ if (LastTileIndex == TileIndex && LastHexTile == HexTile && !isRepeatingSameActionAllowed)
+ return;
+
+ LastTileIndex = TileIndex;
+ LastHexTile = HexTile;
+ AudioPlayer.Play(AudioPlayer.CutForest);
+ action.Invoke();
+ };
+ }
+
+ private void Create(Action action, string actionName, bool isRepeatingSameActionAllowed = false)
+ {
+ ActionNameOnCreate = actionName;
+
+ OnCreate = () =>
+ {
+ if (LastTileIndex == TileIndex && LastHexTile == HexTile && !isRepeatingSameActionAllowed)
+ return;
+
+ LastTileIndex = TileIndex;
+ LastHexTile = HexTile;
+ AudioPlayer.Play(AudioPlayer.DistrictPlacement);
+ action.Invoke();
+ };
+ }
+ }
+}
diff --git a/UI/BackScreen/LiveEditor/ScreenLocker.cs b/UI/BackScreen/LiveEditor/ScreenLocker.cs
new file mode 100644
index 0000000..c254bfc
--- /dev/null
+++ b/UI/BackScreen/LiveEditor/ScreenLocker.cs
@@ -0,0 +1,63 @@
+using Amplitude.Framework;
+using Amplitude.Mercury.Data;
+using Amplitude.Mercury.Input;
+
+namespace DevTools.Humankind.GUITools.UI
+{
+ public static class ScreenLocker
+ {
+ private static IInputFilterService InputFilterService { get; set; }
+ private static int InputFilterHandle { get; set; } = -1;
+ private static bool _isFilterOnInputDevicesEnabled = false;
+
+ public static void Unlock()
+ {
+ LockFullScreenMouseEvents = false;
+ EnableFilterOnInputDevices = false;
+ }
+
+ public static bool LockFullScreenMouseEvents
+ {
+ get => MainTools.BackScreen.ScreenOverlay.LockFullScreenMouseEvents;
+ set => MainTools.BackScreen.ScreenOverlay.LockFullScreenMouseEvents = value;
+ }
+
+ public static bool EnableFilterOnInputDevices
+ {
+ get => _isFilterOnInputDevicesEnabled;
+ set
+ {
+ if (InputFilterService == null)
+ CreateInputFilter();
+
+ if (_isFilterOnInputDevicesEnabled == value || InputFilterService == null)
+ return;
+
+ _isFilterOnInputDevicesEnabled = value;
+
+ InputFilterService.SetFilterActive(InputFilterHandle, _isFilterOnInputDevicesEnabled);
+ }
+ }
+
+ private static void CreateInputFilter()
+ {
+ if (InputFilterService == null)
+ InputFilterService = Services.GetService();
+
+ InputFilterHandle = InputFilterService.CreateFilter(
+ InputFilterDeviceMask.Keyboard
+ | InputFilterDeviceMask.Gamepad
+ | InputFilterDeviceMask.Mouse
+ | InputFilterDeviceMask.Touch,
+ InputLayer.InputFilter.PauseMenuModalWindow.Group,
+ InputLayer.InputFilter.PauseMenuModalWindow.Priority,
+ false);
+ }
+
+ public static void Unload()
+ {
+ Unlock();
+ InputFilterHandle = InputFilterService.DestroyFilter(InputFilterHandle);
+ }
+ }
+}
\ No newline at end of file
diff --git a/UI/BackScreen/RuntimeGameState.cs b/UI/BackScreen/RuntimeGameState.cs
new file mode 100644
index 0000000..0f4729a
--- /dev/null
+++ b/UI/BackScreen/RuntimeGameState.cs
@@ -0,0 +1,88 @@
+using System;
+using Amplitude.Framework;
+using Amplitude.Framework.Presentation;
+using Modding.Humankind.DevTools;
+
+namespace DevTools.Humankind.GUITools.UI
+{
+ public static class RuntimeGameState
+ {
+ private static string _currentState = "UNKNOWN STATE";
+ private static string _currentView = "UNKNOWN VIEW";
+ private static bool _registeredToViewChanges = false;
+
+ public static string CurrentState
+ {
+ get => _currentState;
+ private set
+ {
+ if (_currentState == value)
+ return;
+
+ _currentState = value;
+ Log();
+ }
+ }
+
+ public static string CurrentView
+ {
+ get => _currentView;
+ private set
+ {
+ if (_currentView == value)
+ return;
+
+ _currentView = value;
+ Log();
+ }
+ }
+
+ public static Amplitude.Framework.Runtime.IRuntimeService RuntimeService { get; private set; }
+ public static Amplitude.Framework.Presentation.IViewService ViewService { get; private set; }
+
+ public static void Log() => Loggr.Log("VIEW = " + _currentView + ", STATE = " + _currentState, ConsoleColor.Magenta);
+
+ public static void Refresh()
+ {
+ if (RuntimeService != null)
+ {
+ if (RuntimeService.Runtime?.HasBeenLoaded ?? false)
+ {
+ CurrentState = RuntimeService.Runtime.FiniteStateMachine?.CurrentState?.GetType().Name ??
+ "FiniteStateMachine is NULL";
+ }
+ else
+ CurrentState = "!Runtime.HasBeenLoaded";
+ }
+ else
+ {
+ CurrentState = "Requesting RuntimeService";
+ if (UnityEngine.Event.current.type == UnityEngine.EventType.Repaint)
+ RuntimeService = Services.GetService();
+ }
+
+ if (ViewService == null)
+ {
+ ViewService = Services.GetService();
+ }
+ else
+ {
+ if (!_registeredToViewChanges)
+ RegisterToViewChangeEvents();
+
+ CurrentView = ViewService.View?.Name ?? "NULL";
+ }
+ }
+
+ private static void RegisterToViewChangeEvents()
+ {
+ ViewService.ViewChange += OnViewChanged;
+ _registeredToViewChanges = true;
+ }
+
+ public static void OnViewChanged(object sender, ViewChangedEventArgs eventArgs)
+ {
+ Loggr.Log("OnViewChanged => " + eventArgs.View.Name, ConsoleColor.Yellow);
+ }
+ }
+}
diff --git a/UI/BackScreen/ScreenUIOverlay.cs b/UI/BackScreen/ScreenUIOverlay.cs
new file mode 100644
index 0000000..cf42a4f
--- /dev/null
+++ b/UI/BackScreen/ScreenUIOverlay.cs
@@ -0,0 +1,190 @@
+using Amplitude.Framework.Overlay;
+using Amplitude.Mercury.UI;
+using Amplitude.UI;
+using Amplitude.UI.Interactables;
+using Modding.Humankind.DevTools;
+using UnityEngine;
+using Modding.Humankind.DevTools.DeveloperTools.UI;
+
+namespace DevTools.Humankind.GUITools.UI
+{
+ [RequireComponent(typeof(UITransform))]
+ [RequireComponent(typeof(UIButton))]
+ public class ScreenUIOverlay : MonoBehaviour
+ {
+ public UIButton Control { get; protected set; }
+ public UIButton InnerControl { get; protected set; }
+ public Color BackgroundColor { get; set; } = new Color(0, 0, 0, 0.7f);
+ public UITransform UITransform { get; protected set; }
+ public UITransform InnerUITransform { get; protected set; }
+ public SquircleBackgroundWidget InnerCanvas { get; protected set; }
+ public SquircleBackgroundWidget Canvas { get; protected set; }
+ public bool IsVisibleSelf { get; private set; } = true;
+ private static GameObject _container = null;
+ public static GameObject Container
+ {
+ get
+ {
+ if (_container == null)
+ {
+ var parentContainer = GameObject.Find("/WindowsRoot/SystemOverlays");
+ var count = parentContainer.transform.childCount;
+
+ for (int i = count - 1; i >= 0; i--)
+ {
+ var child = parentContainer.transform.GetChild(i);
+
+ if (child.name == "ScreenUIOverlayContainer") {
+ Destroy(child.gameObject);
+ }
+ }
+
+ _container = new GameObject("ScreenUIOverlayContainer");
+ _container.transform.parent = parentContainer != null ? parentContainer.transform : null;
+ _container.AddComponent();
+ }
+
+ return _container;
+ }
+ }
+
+ public bool LockFullScreenMouseEvents
+ {
+ get => Control?.enabled ?? false;
+ set => SetLockFullScreenMouseEvents(value);
+ }
+
+ public bool EnableFullScreenBackgroundColor
+ {
+ get => Canvas?.enabled ?? false;
+ set => SetEnableFullScreenBackgroundColor(value);
+ }
+
+
+ public static ScreenUIOverlay Find(string uuid)
+ {
+ var t = Container.transform.Find(uuid);
+
+ return (t == null) ? Create(uuid) : t.GetComponent();
+ }
+
+ public Rect ApplyRelativeResolution(Rect rect)
+ {
+ Rect uiRect = UITransform.Parent.Parent.GlobalRect;
+
+ //Loggr.Log(rect);
+ //Loggr.Log(uiRect);
+ // Loggr.Log("Screen: " + Screen.width + " , " + Screen.height);
+ //Loggr.Log(UITransform.Parent.Parent);
+
+ return new Rect(
+ (uiRect.width * rect.x) / Screen.width,
+ (uiRect.height * rect.y) / Screen.height,
+ (uiRect.width * rect.width) / Screen.width,
+ (uiRect.height * rect.height) / Screen.height
+ );
+ }
+ // 0 0 2400 1500 = uiRect
+ // 300 300 300 300 = rect
+ // 1440 900 = Screen
+
+ // 500 500
+
+
+ public ScreenUIOverlay FullScreenSync()
+ {
+ var rect = ApplyRelativeResolution(new Rect(0, 0, Screen.width, Screen.height));
+
+ UITransform.X = rect.x;
+ UITransform.Y = rect.y;
+ UITransform.Width = rect.width;
+ UITransform.Height = rect.height;
+ UITransform.VisibleSelf = true;
+ IsVisibleSelf = true;
+
+ return this;
+ }
+
+ protected static ScreenUIOverlay Create(string uuid)
+ {
+ var go = new GameObject(uuid);
+ go.transform.parent = Container.transform;
+ var overlay = go.AddComponent();
+ overlay.Setup();
+
+ return overlay;
+ }
+
+ public void Setup()
+ {
+ UITransform = GetComponent();
+ Control = GetComponent();
+ Control.LoadIfNecessary();
+ Control.enabled = false;
+
+ if (gameObject.GetComponent() == null)
+ {
+ Canvas = gameObject.AddComponent();
+ Canvas.BackgroundColor = BackgroundColor;
+ Canvas.OuterBorderColor = Color.green;
+ Canvas.BorderColor = Color.clear;
+ Canvas.CornerRadius = 0f;
+ Canvas.enabled = false;
+ }
+
+ var go = new GameObject("InnerOverlayRect");
+ go.transform.parent = gameObject.transform;
+ InnerUITransform = go.AddComponent();
+ InnerControl = go.AddComponent();
+ InnerControl.LoadIfNecessary();
+
+ InnerCanvas = go.AddComponent();
+ InnerCanvas.BackgroundColor = BackgroundColor;
+ InnerCanvas.OuterBorderColor = Color.clear;
+ InnerCanvas.BorderColor = Color.clear;
+ InnerCanvas.CornerRadius = 7f;
+ }
+
+ public ScreenUIOverlay SetInnerRect(Rect innerRect)
+ {
+ if (InnerUITransform == null)
+ return this;
+
+ var rect = ApplyRelativeResolution(innerRect);
+
+ InnerUITransform.X = rect.x;
+ InnerUITransform.Y = rect.y;
+ InnerUITransform.Width = rect.width;
+ InnerUITransform.Height = rect.height;
+
+ return this;
+ }
+
+ public ScreenUIOverlay SetInnerRectAsVisible(bool shouldBeVisible)
+ {
+ if (InnerUITransform == null)
+ return this;
+
+ InnerUITransform.VisibleSelf = shouldBeVisible;
+
+ return this;
+ }
+
+ public bool SetLockFullScreenMouseEvents(bool shouldBeLocked = true) =>
+ Control != null && (Control.enabled = shouldBeLocked);
+
+ public bool SetEnableFullScreenBackgroundColor(bool shouldBeEnabled = true) =>
+ Canvas != null && (Canvas.enabled = shouldBeEnabled);
+
+ public static void Unload()
+ {
+ var c = GameObject.Find("/WindowsRoot/SystemOverlays/ScreenUIOverlayContainer");
+
+ if (c != null)
+ {
+ c.transform.parent = null;
+ Destroy(c);
+ }
+ }
+ }
+}
diff --git a/UI/BackScreen/Toolbox/BackScreenToolbox.cs b/UI/BackScreen/Toolbox/BackScreenToolbox.cs
new file mode 100644
index 0000000..7bc2c74
--- /dev/null
+++ b/UI/BackScreen/Toolbox/BackScreenToolbox.cs
@@ -0,0 +1,101 @@
+using System;
+using System.Collections.Generic;
+using Modding.Humankind.DevTools;
+using Modding.Humankind.DevTools.DeveloperTools.UI;
+using StyledGUI.VirtualGridElements;
+using UnityEngine;
+
+namespace DevTools.Humankind.GUITools.UI
+{
+ public class BackScreenToolbox
+ {
+ public BackScreenWindow Window { get; set; }
+ public ConstructiblesGrid ConstructiblesGrid { get; set; }
+ public Vector2 ScrollViewPosition { get; set; } = Vector2.zero;
+
+ public int ActiveTab { get; set; } = 0;
+
+ private string[] tabNames =
+ {
+ " UNITS ",
+ " DISTRICTS "
+ };
+
+ private List _storedScrollViewPositions = new List() {Vector2.zero, Vector2.zero};
+
+ public void Draw(Rect targetRect)
+ {
+ GUILayout.BeginArea(targetRect);
+ {
+ Draw();
+ }
+ GUILayout.EndArea();
+ }
+
+ public void Draw()
+ {
+ GUILayout.BeginHorizontal();
+ GUILayout.BeginVertical();
+ //GUILayout.Space(1f);
+
+ DrawTabs();
+
+ ScrollViewPosition = GUILayout.BeginScrollView(
+ ScrollViewPosition,
+ false,
+ false,
+ "horizontalscrollbar",
+ "verticalscrollbar",
+ "scrollview",
+ new GUILayoutOption[]
+ {
+ // GUILayout.Height(300f)
+ });
+ {
+ GUILayout.BeginVertical();
+ {
+ if (Event.current.type == EventType.MouseDown)
+ ConstructiblesGrid.VirtualGrid.FindCellAtPosition(Event.current.mousePosition, OnClickHandler);
+
+ ConstructiblesGrid.Render();
+
+ GUILayout.Space(8f);
+ GUILayout.Label("FOCUSED CONTROL: " + GUI.GetNameOfFocusedControl());
+ if (GUILayout.Button("TESTME"))
+ {
+ Loggr.Log("EVENT TYPE = " + Event.current.type.ToString());
+ }
+ }
+ GUILayout.EndVertical();
+ }
+ GUILayout.EndScrollView();
+ GUILayout.Space(1f);
+ GUILayout.EndVertical();
+ GUILayout.EndHorizontal();
+ }
+
+ private void DrawTabs()
+ {
+ GUILayout.Space(6f);
+ GUILayout.BeginHorizontal();
+ GUILayout.Space(12f);
+
+ var activeTab = GUILayout.Toolbar(ActiveTab, tabNames, "TabButton", GUI.ToolbarButtonSize.FitToContents);
+
+ if (activeTab != ActiveTab)
+ {
+ _storedScrollViewPositions[ActiveTab] = ScrollViewPosition;
+ ScrollViewPosition = _storedScrollViewPositions[activeTab];
+ ActiveTab = activeTab;
+ ConstructiblesGrid.VirtualGrid.VisibleViews = new[] { ActiveTab };
+ }
+ GUILayout.EndHorizontal();
+ Utils.DrawHorizontalLine();
+ }
+
+ public void OnClickHandler(ICell cell)
+ {
+ ConstructiblesGrid.VirtualGrid.Cursor.AddToSelection();
+ }
+ }
+}
\ No newline at end of file
diff --git a/UI/BackScreen/Toolbox/ConstructibleStore.cs b/UI/BackScreen/Toolbox/ConstructibleStore.cs
new file mode 100644
index 0000000..3f5c173
--- /dev/null
+++ b/UI/BackScreen/Toolbox/ConstructibleStore.cs
@@ -0,0 +1,396 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Amplitude;
+using Amplitude.Extensions;
+using Amplitude.Framework;
+using Amplitude.Mercury.Data.Simulation;
+using Amplitude.UI;
+using Modding.Humankind.DevTools;
+using Modding.Humankind.DevTools.Core;
+using Modding.Humankind.DevTools.DeveloperTools.UI;
+using UnityEngine;
+using String = System.String;
+
+namespace DevTools.Humankind.GUITools.UI
+{
+ public class DefinitionsGroup
+ {
+ public string Title { get; set; }
+ public Constructible[] Values { get; set; }
+ }
+
+ public class Constructible
+ {
+ public StaticString DefinitionName { get; set; }
+ public string Name { get; set; }
+ public string Title { get; set; }
+ public string Category { get; set; }
+ public int Era { get; set; }
+ public Texture Image { get; set; }
+ }
+
+ public static class ConstructibleStore
+ {
+ public static DefinitionsGroup[] Districts { get; set; }
+ public static DefinitionsGroup[] Units { get; set; }
+
+ private static string LastName(string name) => name.Substring(name.LastIndexOf('_') + 1);
+ private static int EraLevel(string name) => int.TryParse(name.Substring(name.LastIndexOf('_') - 1, 1), out int level) ? level : 0;
+ private static string UnitLastName(string name) => name.Substring(name.LastIndexOf('_', name.LastIndexOf('_') - 1) + 1);
+ private static int UnitEraLevel(string name) => int.TryParse(name.Substring(name.LastIndexOf('_', name.LastIndexOf('_') - 1) - 1, 1), out int level) ? level : 0;
+
+ public static Constructible CreateDistrictConstructible(DistrictDefinition definition)
+ {
+ var name = LastName(definition.name);
+
+ return new Constructible()
+ {
+ DefinitionName = definition.Name,
+ Title = UIController.GetLocalizedTitle(definition.Name, name),
+ Name = name,
+ Category = definition.Category.ToString(),
+ Era = EraLevel(definition.name),
+ Image = Utils.LoadTexture(definition.name)
+ };
+ }
+
+ public static Constructible CreateUnitConstructible(UnitDefinition definition)
+ {
+ var name = UnitLastName(definition.name);
+
+ return new Constructible()
+ {
+ DefinitionName = definition.Name,
+ Title = UIController.GetLocalizedTitle(definition.Name, name),
+ Name = name,
+ Category = UIController.GetLocalizedTitle(definition.UnitClassName),
+ Era = UnitEraLevel(definition.name),
+ Image = Utils.LoadTexture(definition.name)
+ };
+ }
+
+ public static void Rebuild()
+ {
+ var constructibles = Databases
+ .GetDatabase(false);
+
+ var districts = constructibles
+ .OfType()
+ .ToArray();
+
+ var units = constructibles
+ .OfType()
+ .ToArray();
+
+ Districts = new DefinitionsGroup[]
+ {
+ new DefinitionsGroup()
+ {
+ Title = "Common Districts",
+ Values = districts
+ .Where(d => d.Prototype == "Extension_Prototype_BaseEconomy")
+ .Select(CreateDistrictConstructible)
+ .ToArray()
+ },
+ new DefinitionsGroup()
+ {
+ Title = "Extractors & Manufactories",
+ Values = districts
+ .Where(d => d.Prototype == "Extension_Base_Extractor" || d.Prototype == "Extension_Base_WondrousExtractor")
+ .Select(CreateDistrictConstructible)
+ .ToArray()
+ },
+ new DefinitionsGroup()
+ {
+ Title = "Emblematic Districts",
+ Values = districts
+ .Where(d => d.Prototype == "Extension_Prototype_Emblematic")
+ .Select(CreateDistrictConstructible)
+ .ToArray()
+ }
+ };
+
+ Units = new DefinitionsGroup[]
+ {
+
+ new DefinitionsGroup()
+ {
+ Title = "Maritime Units",
+ Values = units
+ .Where(u => u.SpawnType == UnitSpawnType.Maritime)
+ .Select(CreateUnitConstructible)
+ .ToArray()
+ },
+ new DefinitionsGroup()
+ {
+ Title = "Land Units",
+ Values = units
+ .Where(u => u.SpawnType == UnitSpawnType.Land)
+ .Select(CreateUnitConstructible)
+ .ToArray()
+ },
+ new DefinitionsGroup()
+ {
+ Title = "Air & Missile Units",
+ Values = units
+ .Where(u => u.SpawnType == UnitSpawnType.Air || u.SpawnType == UnitSpawnType.Missile)
+ .Select(CreateUnitConstructible)
+ .ToArray()
+ }
+ };
+ }
+
+ public static void PrintBatchProcess()
+ {
+ var constructibles = Databases
+ .GetDatabase(false);
+
+ var key = new StaticString("Small");
+ var key2 = new StaticString("Default_Small");
+ List remaining = new List();
+ List result = new List();
+ int failCount = 0;
+ int count = 0;
+ string assetPath = "";
+ foreach (var definition in constructibles.GetValues())
+ {
+ count++;
+ try
+ {
+ var uiTexture = UIController.DataUtils.GetImage(definition.Name, key);
+ assetPath = "" + uiTexture.AssetPath;
+ if (assetPath.Length == 0)
+ {
+ assetPath = "" + UIController.DataUtils.GetImage(definition.Name, key2).AssetPath;
+ }
+ if (assetPath.Length == 0)
+ {
+ remaining.Add(definition);
+ failCount++;
+ continue;
+ }
+
+ var filename = assetPath.Substring(assetPath.LastIndexOf('/') + 1);
+ result.Add("cp -u " + filename + " ../Small/" + definition.name + ".png");
+ }
+ catch (Exception)
+ {
+ failCount++;
+ }
+ }
+ Loggr.Log(failCount.ToString() + " FAILED OUT OF " + count + ", REMAINING = " + remaining.Count, ConsoleColor.Green);
+
+ foreach (var constructibleDefinition in remaining)
+ {
+ Loggr.Log("" + constructibleDefinition.name.ToString(), ConsoleColor.DarkCyan);
+ }
+
+ Loggr.Log("\n\n");
+
+ foreach (var s in result)
+ {
+ Loggr.Log(s, ConsoleColor.Green);
+ }
+
+ Loggr.Log("\n\n");
+ }
+ }
+}
+
+/*
+using System.Collections.Generic;
+using System.Linq;
+using Amplitude.Framework;
+using Amplitude.Mercury.Data.Simulation;
+
+namespace Modding.Humankind.DevTools.Core
+{
+ public static class QuickAccess
+ {
+ private static UnitDefinition[] _unitDefinitions = null;
+
+ public static UnitDefinition[] UnitDefinitions =>
+ _unitDefinitions ?? (_unitDefinitions = Databases
+ .GetDatabase(false)
+ .OfType()
+ .ToArray());
+
+ // UITooltipClassDefinition
+ }
+}
+
+
+ "Extension_ArtificialWonder_Era1_HangingGardensOfBabylon"
+"Extension_ArtificialWonder_Era1_PyramidOfGiza"
+"Extension_ArtificialWonder_Era1_Stonehenge"
+"Extension_ArtificialWonder_Era1_TempleOfArtemis"
+"Extension_ArtificialWonder_Era2_ColossusOfRhodes"
+"Extension_ArtificialWonder_Era2_LighthouseOfAlexandria"
+"Extension_ArtificialWonder_Era2_MausoleumAtHalicarnassus"
+"Extension_ArtificialWonder_Era2_StatueOfZeus"
+"Extension_ArtificialWonder_Era3_AngkorWat"
+"Extension_ArtificialWonder_Era3_ForbiddenCity"
+"Extension_ArtificialWonder_Era3_NotreDameDeParis"
+"Extension_ArtificialWonder_Era3_TodaiJi"
+"Extension_ArtificialWonder_Era4_MachuPicchu"
+"Extension_ArtificialWonder_Era4_SaintBasilsCathedral"
+"Extension_ArtificialWonder_Era4_TajMahal"
+"Extension_ArtificialWonder_Era4_TopkapiPalace"
+"Extension_ArtificialWonder_Era5_BigBen"
+"Extension_ArtificialWonder_Era5_EiffelTower"
+"Extension_ArtificialWonder_Era5_StatueOfLiberty"
+"Extension_ArtificialWonder_Era6_ChristTheRedeemer"
+"Extension_ArtificialWonder_Era6_EmpireStateBuilding"
+"Extension_ArtificialWonder_Era6_SydneyOperaHouse"
+"Extension_Base_AdministrativeCenter"
+"Extension_Base_Airfield"
+"Extension_Base_Airport"
+"Extension_Base_CityCenter"
+"Extension_Base_Extractor"
+"Extension_Base_Food"
+"Extension_Base_Harbour"
+"Extension_Base_Industry"
+"Extension_Base_Luxury"
+"Extension_Base_Military"
+"Extension_Base_MissileSilo"
+"Extension_Base_Money"
+"Extension_Base_NaturalReserve"
+"Extension_Base_PublicOrder"
+"Extension_Base_Science"
+"Extension_Base_Strategic01"
+"Extension_Base_Strategic02"
+"Extension_Base_Strategic03"
+"Extension_Base_Strategic04"
+"Extension_Base_Strategic05"
+"Extension_Base_Strategic06"
+"Extension_Base_Strategic07"
+"Extension_Base_Strategic08"
+"Extension_Base_TrainStation"
+"Extension_Base_VillageCenter"
+"Extension_Base_WondrousExtractor"
+"Extension_Camp_BeforeCamp"
+"Extension_Camp_CampCenter"
+"Extension_Prototype_Base"
+"Extension_Prototype_BaseEconomy"
+"Extension_Prototype_BaseMilitary"
+"Extension_Prototype_Emblematic"
+"Extension_Wondrous_Resource11"
+"Extension_Wondrous_Resource12"
+"Extension_Wondrous_Resource13"
+"Extension_Wondrous_Resource14"
+"Extension_Wondrous_Resource15"
+"Extension_Wondrous_Resource16"
+"Extension_Wondrous_Resource17"
+"Extension_Wondrous_Resource18"
+"Extension_Wondrous_Resource19"
+"Extension_Wondrous_Resource20"
+"Extension_Wondrous_Resource21"
+"Extension_Wondrous_Resource22"
+"Extension_Wondrous_Resource23"
+"Extension_Wondrous_Resource24"
+"Extension_Wondrous_Resource25"
+"Extension_Wondrous_Resource26"
+"Extension_Wondrous_Resource27"
+"Extension_Wondrous_Resource28"
+"Extension_Wondrous_Resource29"
+"Extension_Wondrous_Resource30"
+"Extension_Wondrous_Resource31"
+"Extension_Wondrous_Template"
+"Extension_Era1_Assyria"
+"Extension_Era1_Babylon"
+"Extension_Era1_EgyptianKingdom"
+"Extension_Era1_HarappanCivilization"
+"Extension_Era1_HittiteEmpire"
+"Extension_Era1_MycenaeanCivilization"
+"Extension_Era1_Nubia"
+"Extension_Era1_OlmecCivilization"
+"Extension_Era1_Phoenicia"
+"Extension_Era1_ZhouChina"
+"Extension_Era2_AksumiteEmpire"
+"Extension_Era2_AncientGreece"
+"Extension_Era2_Carthage"
+"Extension_Era2_CelticCivilization"
+"Extension_Era2_Goths"
+"Extension_Era2_Huns"
+"Extension_Era2_MauryaEmpire"
+"Extension_Era2_MayaCivilization"
+"Extension_Era2_Persia"
+"Extension_Era2_RomanEmpire"
+"Extension_Era3_AztecEmpire"
+"Extension_Era3_Byzantium"
+"Extension_Era3_FrankishKingdom"
+"Extension_Era3_GhanaEmpire"
+"Extension_Era3_HolyRomanEmpire"
+"Extension_Era3_KhmerEmpire"
+"Extension_Era3_MedievalEngland"
+"Extension_Era3_MongolEmpire"
+"Extension_Era3_UmayyadCaliphate"
+"Extension_Era3_Vikings"
+"Extension_Era4_Holland"
+"Extension_Era4_IroquoisConfederacy"
+"Extension_Era4_JoseonKorea"
+"Extension_Era4_MingChina"
+"Extension_Era4_MughalEmpire"
+"Extension_Era4_OttomanEmpire"
+"Extension_Era4_PolishKingdom"
+"Extension_Era4_Spain"
+"Extension_Era4_TokugawaShogunate"
+"Extension_Era4_VenetianRepublic"
+"Extension_Era5_AfsharidPersia"
+"Extension_Era5_AustriaHungary"
+"Extension_Era5_BritishEmpire"
+"Extension_Era5_FrenchRepublic"
+"Extension_Era5_Germany"
+"Extension_Era5_Italy"
+"Extension_Era5_Mexico"
+"Extension_Era5_RussianEmpire"
+"Extension_Era5_Siam"
+"Extension_Era5_ZuluKingdom"
+"Extension_Era6_Australia"
+"Extension_Era6_Brazil"
+"Extension_Era6_China"
+"Extension_Era6_Egypt"
+"Extension_Era6_India"
+"Extension_Era6_Japan"
+"Extension_Era6_Sweden"
+"Extension_Era6_Turkey"
+"Extension_Era6_USA"
+"Extension_Era6_USSR"
+"Extension_HolySite_Buddhism"
+"Extension_HolySite_Christianism"
+"Extension_HolySite_Hinduism"
+"Extension_HolySite_Islam"
+"Extension_HolySite_Judaism"
+"Extension_HolySite_Polytheism"
+"Extension_HolySite_Shamanism"
+"Extension_HolySite_Shintoism"
+"Extension_HolySite_Taoism"
+"Extension_HolySite_Zoroastrism"
+"Extension_NationalProject_NuclearTest_Level1"
+"Extension_NationalProject_NuclearTest_Level2"
+"Extension_NationalProject_NuclearTest_Level3"
+"Extension_NationalProject_SatelliteLaunch_Level1"
+"Extension_NationalProject_SatelliteLaunch_Level2"
+"Extension_NationalProject_SatelliteLaunch_Level3"
+"Extension_NationalProject_SpaceRace_Level1"
+"Extension_NationalProject_SpaceRace_Level2"
+"Extension_NationalProject_SpaceRace_Level3"
+"Extension_ArtificialWonder_Era2_LadyMaryOfZion"
+"Extension_ArtificialWonder_Era3_GreatMosqueOfDjenne"
+"Extension_ArtificialWonder_Era3_GreatZimbabwe"
+"Extension_Era1_Bantu"
+"Extension_Era2_Garamantes"
+"Extension_Era3_Swahili"
+"Extension_Era4_Maasai"
+"Extension_Era5_Ethiopia"
+"Extension_Era6_Nigeria"
+
+
+UI_Extension_ArtificialWonder_Era3_GreatZimbabwe_Small.png
+Extension_ArtificialWonder_Era3_GreatZimbabwe
+
+UI_ConstructibleInfrastructure_Repeatable_Era3_GreatMosqueOfDjenne_Small.png
+UI_ConstructibleExtension_Era5_Siam_Small.png
+ */
+
\ No newline at end of file
diff --git a/UI/BackScreen/Toolbox/ConstructibleStoreSnapshot.cs b/UI/BackScreen/Toolbox/ConstructibleStoreSnapshot.cs
new file mode 100644
index 0000000..953a358
--- /dev/null
+++ b/UI/BackScreen/Toolbox/ConstructibleStoreSnapshot.cs
@@ -0,0 +1,9 @@
+namespace DevTools.Humankind.GUITools.UI
+{
+ public class ConstructibleStoreSnapshot
+ {
+ public DefinitionsGroup[] Districts { get; set; }
+ public DefinitionsGroup[] Units { get; set; }
+
+ }
+}
diff --git a/UI/BackScreen/Toolbox/ConstructiblesGrid.cs b/UI/BackScreen/Toolbox/ConstructiblesGrid.cs
new file mode 100644
index 0000000..eb41871
--- /dev/null
+++ b/UI/BackScreen/Toolbox/ConstructiblesGrid.cs
@@ -0,0 +1,98 @@
+using System.Linq;
+using StyledGUI;
+using StyledGUI.VirtualGridElements;
+using UnityEngine;
+
+namespace DevTools.Humankind.GUITools.UI
+{
+ public class ConstructiblesStyledGrid : GridStyles
+ {
+ public override Color CellTintColor { get; set; } = new Color(0, 0, 0, 0.6f);
+ public override Color CellTintColorAlt { get; set; } = new Color(0, 0, 0, 0.2f);
+ public override Color IconTintColor { get; set; } = new Color(1f, 1f, 1f, 0.7f);
+ public override float GetCellHeight() => 48f;
+ }
+
+ public class ConstructiblesGrid
+ {
+ public VirtualGrid VirtualGrid { get; set; }
+ public ConstructibleStoreSnapshot Snapshot { get; set; }
+ public bool IsDirty { get; set; } = true;
+
+ protected IStyledGrid Grid;
+
+ public ConstructiblesGrid()
+ {
+ }
+
+ public void Render()
+ {
+ if (IsDirty)
+ Update();
+
+ VirtualGrid.Render();
+ }
+
+ public void Update()
+ {
+ Grid = VirtualGrid.Grid;
+ ComputeVirtualGrid();
+
+ IsDirty = false;
+ }
+
+ private void ComputeVirtualGrid()
+ {
+ VirtualGrid.Columns = new Column[]
+ {
+ new Column() {Name = "Constructibles"}
+ };
+
+ VirtualGrid.Sections = Snapshot.Units
+ .Select(group => new Section()
+ {
+ Title = "" + group.Title.ToUpper() + "",
+ View = 0,
+ Rows = group.Values.Select(c => new Row()
+ {
+ Cells = new[]
+ {
+ new Clickable4xCell()
+ {
+ Title = "" + c.Title.ToUpper() + "",
+ Subtitle = c.Name,
+ UniqueName = c.DefinitionName.ToString(),
+ Category = c.Category == "None" ? "" : "" + c.Category.ToUpper() + "",
+ Tags = c.Era > 0 ? "ERA " + c.Era + "" : "",
+ Image = c.Image
+ // Span = Grid.CellSpan8
+ }
+ }
+ }).ToArray()
+ })
+ .Concat(
+ Snapshot.Districts.Select(group => new Section()
+ {
+ Title = "" + group.Title.ToUpper() + "",
+ View = 1,
+ Rows = group.Values.Select(c => new Row()
+ {
+ Cells = new[]
+ {
+ new Clickable4xCell()
+ {
+ Title = "" + c.Title.ToUpper() + "",
+ Subtitle = c.Name,
+ UniqueName = c.DefinitionName.ToString(),
+ Category = c.Category == "None" ? "" : "" + c.Category.ToUpper() + "",
+ Tags = c.Era > 0 ? "ERA " + c.Era + "" : "",
+ Image = c.Image
+ // Span = Grid.CellSpan8
+ }
+ }
+ }).ToArray()
+ }))
+ .ToArray();
+ }
+ }
+}
diff --git a/UI/BackScreen/Toolbox/ToolboxController.cs b/UI/BackScreen/Toolbox/ToolboxController.cs
new file mode 100644
index 0000000..cbd6312
--- /dev/null
+++ b/UI/BackScreen/Toolbox/ToolboxController.cs
@@ -0,0 +1,159 @@
+using System;
+using System.Linq;
+using Amplitude.Framework;
+using Amplitude.Mercury.Data;
+using Amplitude.Mercury.Input;
+using BepInEx.Configuration;
+using Modding.Humankind.DevTools;
+using StyledGUI;
+using UnityEngine;
+
+namespace DevTools.Humankind.GUITools.UI
+{
+ public static class ToolboxController
+ {
+ public static Rect ToolboxRect { get; private set; } = Rect.zero;
+ public static Rect InputFilterRect { get; private set; } = Rect.zero;
+ public static BackScreenToolbox Toolbox { get; set; }
+ public static KeyboardShortcut ToolboxPreviewKey { get; set; } = new KeyboardShortcut(KeyCode.LeftControl);
+ public static KeyboardShortcut StickedToolboxKey { get; set; } = new KeyboardShortcut(KeyCode.Space, KeyCode.LeftControl);
+ public static bool IsVisible { get; private set; } = false;
+ public static bool IsSticked { get; set; } = false;
+ public static string InputFilter { get; set; } = string.Empty;
+
+ // IInputService
+
+ // private static IInputFilterService inputFilterService;
+ // private static int inputFilterHandle = -1;
+
+ public static void Initialize(BackScreenWindow window)
+ {
+ if (ToolboxRect.Equals(Rect.zero))
+ SetToolboxRect(new Rect(
+ 300f, 220f, 360f,
+ Mathf.Min(640f, Mathf.Ceil(Screen.height * 0.66f))));
+
+ ConstructibleStore.Rebuild();
+
+ Toolbox = new BackScreenToolbox()
+ {
+ Window = window,
+ ConstructiblesGrid = new ConstructiblesGrid()
+ {
+ Snapshot = new ConstructibleStoreSnapshot()
+ {
+ Districts = ConstructibleStore.Districts,
+ Units = ConstructibleStore.Units
+ },
+ VirtualGrid = new VirtualGrid()
+ {
+ Grid = new ConstructiblesStyledGrid(),
+ DrawRowHeaders = false,
+ DrawSectionHeaders = true,
+ VisibleViews = new[] { 0 },
+ AlternateType = VirtualGridAlternateType.Rows,
+ Cursor = new VirtualGridCursor()
+ {
+ SelectionType = VirtualGridSelectionType.OptionalSingleCell,
+ }
+ }
+ }
+ };
+
+ Toolbox.ConstructiblesGrid.VirtualGrid.Cursor.OnSelectionChange += LiveEditorMode.UpdatePaintBrush;
+
+ //CreateInputFilter();
+ }
+
+ public static void SetToolboxRect(Rect newRect)
+ {
+ ToolboxRect = newRect;
+ InputFilterRect = new Rect(newRect.x + 12f, newRect.y - 24f, newRect.width, 24f);
+ }
+
+ public static bool Draw()
+ {
+ if (Event.current.type == EventType.Repaint)
+ {
+ if (StickedToolboxKey.IsDown())
+ {
+ IsSticked = !IsSticked;
+ }
+ }
+
+ if (IsSticked || AreKeysHeldDown(ToolboxPreviewKey))
+ {
+ if (!IsVisible)
+ OnShow();
+
+ if (InputFilter.Length > 0)
+ DrawInputFilter();
+
+ Toolbox.Draw(ToolboxRect);
+
+ if (Event.current.type == EventType.Repaint && Input.inputString.Length > 0)
+ InputFilter = (InputFilter + Input.inputString).TrimStart(' ');
+
+ return true;
+ }
+
+ InputFilter = string.Empty;
+ if (IsVisible)
+ OnHide();
+
+ return false;
+ }
+
+ private static void DrawInputFilter()
+ {
+ GUILayout.BeginArea(InputFilterRect);
+ {
+ GUILayout.BeginHorizontal();
+ {
+ GUILayout.Label("FILTER: ");
+ GUILayout.Label("" + InputFilter.ToUpper() + "");
+ GUILayout.FlexibleSpace();
+ }
+ GUILayout.EndHorizontal();
+ }
+ GUILayout.EndArea();
+ }
+
+ private static bool AreKeysHeldDown(KeyboardShortcut shortcut) =>
+ Input.GetKey(shortcut.MainKey) && shortcut.Modifiers.Count(key => !Input.GetKey(key)) == 0;
+
+ /*private static void CreateInputFilter()
+ {
+ if (inputFilterService == null)
+ inputFilterService = Services.GetService();
+
+ inputFilterHandle = inputFilterService.CreateFilter(
+ InputFilterDeviceMask.Keyboard
+ | InputFilterDeviceMask.Gamepad
+ | InputFilterDeviceMask.Mouse
+ | InputFilterDeviceMask.Touch,
+ InputLayer.InputFilter.PauseMenuModalWindow.Group,
+ InputLayer.InputFilter.PauseMenuModalWindow.Priority,
+ false);
+ }*/
+
+ private static void OnShow()
+ {
+ IsVisible = true;
+ //inputFilterService.SetFilterActive(inputFilterHandle, true);
+ }
+
+ private static void OnHide()
+ {
+ IsVisible = false;
+ //inputFilterHandle = inputFilterService.DestroyFilter(inputFilterHandle);
+ //CreateInputFilter();
+ }
+
+ public static void Unload()
+ {
+ //inputFilterHandle = inputFilterService.DestroyFilter(inputFilterHandle);
+ Toolbox.ConstructiblesGrid.VirtualGrid.Cursor.OnSelectionChange -= LiveEditorMode.UpdatePaintBrush;
+ }
+ }
+}
diff --git a/UI/BasicToolWindow.cs b/UI/BasicToolWindow.cs
index 134ed7f..7e011c6 100644
--- a/UI/BasicToolWindow.cs
+++ b/UI/BasicToolWindow.cs
@@ -1,10 +1,27 @@
using System;
using System.Reflection;
+using Amplitude;
+using Amplitude.Framework;
+using Amplitude.Graphics;
+using Amplitude.Mercury;
+using Amplitude.Mercury.AI;
+using Amplitude.Mercury.Audio;
using UnityEngine;
using Modding.Humankind.DevTools;
using Modding.Humankind.DevTools.Core;
using Modding.Humankind.DevTools.DeveloperTools.UI;
using Amplitude.Mercury.Interop;
+using Amplitude.Mercury.Presentation;
+using Amplitude.Mercury.Terrain;
+using Amplitude.Mercury.UI;
+using Amplitude.UI;
+using Amplitude.Framework;
+using Amplitude.Framework.Overlay;
+using Amplitude.Mercury.Audio;
+using Amplitude.Wwise.Audio;
+using System.Reflection;
+using Amplitude.Mercury.Input;
+using UnityEngine;
namespace DevTools.Humankind.GUITools.UI
{
@@ -13,71 +30,267 @@ public class BasicToolWindow : FloatingToolWindow
public override bool ShouldBeVisible => true;
public override bool ShouldRestoreLastWindowPosition => true;
public override string WindowTitle { get; set; } = "BASIC TOOL WINDOW";
- public override Rect WindowRect { get; set; } = new Rect (300, 300, 900, 600);
+ public override Rect WindowRect { get; set; } = new Rect(300, 300, 900, 900);
- public static FieldInfo EmpireEndGameStatusField = R.GetField("EmpireEndGameStatus", R.NonPublicInstance);
+ public static FieldInfo EmpireEndGameStatusField =
+ R.GetField("EmpireEndGameStatus", R.NonPublicInstance);
private int loop = 0;
+
+ private GUIStyle bgStyle = new GUIStyle(UIController.DefaultSkin.FindStyle("PopupWindow.Sidebar.Highlight"))
+ {
+ normal = new GUIStyleState()
+ {
+ background = Utils.CreateSinglePixelTexture2D(new Color(0, 0, 0, 0.8f)),
+ textColor = Color.white
+ },
+ hover = new GUIStyleState()
+ {
+ background = null,
+ textColor = Color.white
+ }
+ };
+
+ public Texture EmpireIconTexture { get; set; }
+
public override void OnDrawUI()
{
var asMajorEmpire = HumankindGame.Empires[0].Simulation;
- EmpireEndGameStatus endGameStatus = (EmpireEndGameStatus)EmpireEndGameStatusField.GetValue(asMajorEmpire);
+ EmpireEndGameStatus endGameStatus = (EmpireEndGameStatus) EmpireEndGameStatusField.GetValue(asMajorEmpire);
if (loop < 20)
{
+ if (loop > 18)
+ {
+ // EmpireIcon = UIController.GameUtils.GetEmpireIcon(1);
+ EmpireIcon = UIController.GameUtils.GetEmpireBannerOrnament(0);
+ // EmpireIcon.GetAsset();
+ EmpireIcon.RequestAsset();
+ EmpireIconTexture = EmpireIcon.GetAsset();
+ Loggr.Log(EmpireIconTexture);
+ Loggr.LogAll(EmpireIcon);
+ EmpireIcon.RequestAsset();
+ Loggr.LogAll(EmpireIcon.GetAsset());
+ }
+
if (loop == 16 && endGameStatus == EmpireEndGameStatus.Resigned)
{
- Loggr.Log("SETTING EmpireEndGameStatusField TO InGame");
EmpireEndGameStatusField.SetValue(asMajorEmpire, EmpireEndGameStatus.InGame);
}
+
loop++;
}
- GUILayout.BeginVertical();
- DrawValue("Name", Amplitude.Framework.Application.Name);
- DrawValue("User Name", Amplitude.Framework.Application.UserName);
- DrawValue("User Identifier", Amplitude.Framework.Application.UserIdentifier.ToString());
- DrawValue("User Directory", Amplitude.Framework.Application.UserDirectory);
- DrawValue("Game Directory", Amplitude.Framework.Application.GameDirectory);
- DrawValue("Game Save Directory", Amplitude.Framework.Application.GameSaveDirectory);
- DrawValue("Current Game Language", Amplitude.Framework.Application.CurrentGameLanguage);
- DrawValue("EmpireEndGameStatus", endGameStatus.ToString());
+ GUILayout.BeginVertical(bgStyle);
+ {
+ DrawUITexture();
+
+ StaticString staticString = StaticString.Empty;
+ if (GUILayout.Button(AudioEvents.CitySirenPlayed.ToString(), Array.Empty()))
+ {
+ staticString = AudioEvents.CitySirenPlayed;
+ }
+
+ if (GUILayout.Button(AudioEvents.CitySirenStopped.ToString(), Array.Empty()))
+ {
+ staticString = AudioEvents.CitySirenStopped;
+ }
+
+ if (!StaticString.IsNullOrEmpty(staticString))
+ {
+ /*Services.GetService().SendAudioEvent(staticString, new object[]
+ {
+ city.SimulationEntityGUID
+ });*/
+ }
+
+ DrawValue("rotationX", ActionController.FreeCamera.FreeCam?.rotationX.ToString());
+ DrawValue("rotationY", ActionController.FreeCamera.FreeCam?.rotationY.ToString());
+ DrawValue("Position", ActionController.FreeCamera.FreeCam?.GetTransform().position.ToString());
+ DrawValue("localRotation",
+ ActionController.FreeCamera.FreeCam?.GetTransform().localRotation.ToString());
+ DrawValue("FreeCam rotation", ActionController.FreeCamera.FreeCam?.GetTransform().rotation.ToString());
+ DrawValue("nearClipPlane", ActionController.Camera?.nearClipPlane.ToString());
+ DrawValue("farClipPlane", ActionController.Camera?.farClipPlane.ToString());
+ DrawValue("fieldOfView", ActionController.Camera?.fieldOfView.ToString());
+ DrawValue("Camera rotation", ActionController.Camera?.transform.rotation.ToString());
+ DrawValue("WorldPosition Highlighted",
+ Presentation.PresentationCursorController.CurrentHighlightedPosition.ToString());
+
+ // UpdateDebugger();
+ // OnDrawTerrainDebugger();
Utils.DrawHorizontalLine(0.6f);
GUILayout.BeginHorizontal();
+ {
GUI.enabled = HumankindGame.IsGameLoaded;
- GUILayout.Label("FOG OF WAR");
+ GUILayout.Label("CAMERA, LEFTCTRL + ...");
GUILayout.FlexibleSpace();
- if (GUILayout.Button("ENABLE"))
- EnableFogOfWar(true);
- if (GUILayout.Button("DISABLE"))
- EnableFogOfWar(false);
+ if (GUILayout.Button("1: Loggr => CameraController"))
+ Loggr.Log(ActionController.FreeCamera);
+ if (GUILayout.Button("2: Loggr => FreeCamera"))
+ Loggr.Log(ActionController.FreeCamera?.FreeCam);
+
+ if (GUILayout.Button("3: Loggr => PresentationCameraMover"))
+ Loggr.Log(ActionController.FreeCamera?.presCamMover);
+
+ if (GUILayout.Button("4: Loggr => Camera"))
+ Loggr.Log(ActionController.FreeCamera?.cameraCam);
GUI.enabled = true;
+ }
GUILayout.EndHorizontal();
-
+ OnDrawWindowClientArea(0);
+ }
GUILayout.EndVertical();
}
private void DrawValue(string title, string value)
{
GUILayout.BeginHorizontal();
- GUILayout.Label("" + title.ToUpper() + "");
- GUILayout.FlexibleSpace();
- GUILayout.Label(value, "RightAlignedLabel");
+ GUILayout.Label("" + title.ToUpper() + "");
+ GUILayout.FlexibleSpace();
+ GUILayout.Label(value, "RightAlignedLabel");
GUILayout.EndHorizontal();
}
- public static void EnableFogOfWar(bool enable)
+ public Texture2D HeaderImage { get; set; } =
+ Modding.Humankind.DevTools.DevTools.Assets.Load("GameplayOrientation_Warmonger");
+
+ public UITexture EmpireIcon { get; set; } = UIController.GameUtils.GetEmpireIcon(0);
+
+ public void DrawUITexture()
{
- if (!HumankindGame.IsGameLoaded)
+ GUILayout.BeginHorizontal();
+ GUILayout.BeginVertical(GUILayout.ExpandWidth(false), GUILayout.Width(78f), GUILayout.ExpandHeight(false),
+ GUILayout.Height(78f));
+ GUILayoutUtility.GetRect(64f, 64f);
+ GUI.DrawTexture(
+ new Rect(18f, 10f, 64f, 64f),
+ HeaderImage,
+ ScaleMode.ScaleToFit,
+ true,
+ 1f,
+ new Color32(255, 255, 255, 240),
+ 0,
+ 0
+ );
+ GUILayout.EndVertical();
+ GUILayout.BeginVertical(GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(false), GUILayout.Height(82f),
+ GUILayout.MaxHeight(82f));
+ GUILayout.Label(
+ ("\n Showcasing a fully featured demo of an " +
+ "in-game\n\n Tool made with Humankind Modding DevTools" +
+ "\n").ToUpper(), "Text");
+ GUILayout.FlexibleSpace();
+ GUI.color = new Color(1f, 1f, 1f, 0.5f);
+ GUILayout.Label(R.Text.Size(R.Text.Bold("GUITooltip.ToUpper()"), 9), "Tooltip");
+ GUI.color = Color.white;
+ GUILayout.EndVertical();
+ GUILayout.EndHorizontal();
+ }
+ /*
+ private static StaticString[] reflectedEventNames;
+ private Vector2 scrollPosition = Vector2.zero;
+
+ private IAudioModulesService AudioModulesService { get; set; }
+
+ protected override void OnDrawWindowClientArea(int instanceId)
+ {
+ GUI.color = Color.white;
+ GUI.backgroundColor = Color.white;
+ GUILayout.BeginVertical((GUIStyle) "Widget.ClientArea", GUILayout.ExpandWidth(true), GUILayout.Height(400f));
+ if (this.AudioModulesService != null)
{
- Loggr.Log("UNABLE TO CHANGE FOG OF WAR VALUE WHEN NO GAME IS RUNNING.", ConsoleColor.DarkRed);
+ if (BasicToolWindow.reflectedEventNames == null)
+ BasicToolWindow.GenerateReflectedEventNames();
+ this.scrollPosition = GUILayout.BeginScrollView(this.scrollPosition);
+ for (int index = 0; index < BasicToolWindow.reflectedEventNames.Length; ++index)
+ {
+ StaticString reflectedEventName = BasicToolWindow.reflectedEventNames[index];
+ if (GUILayout.Button(reflectedEventName.ToString()))
+ this.AudioModulesService.SendAudioEvent(reflectedEventName);
+ }
+ GUILayout.EndScrollView();
+ }
+ else
+ {
+ GUILayout.Label("Waiting for the audio module service...");
+ if (Event.current.type == EventType.Repaint)
+ this.AudioModulesService = Services.GetService();
+ }
+ GUILayout.EndVertical();
+ }
+
+ private static void GenerateReflectedEventNames()
+ {
+ FieldInfo[] fields = typeof (AudioEvents).GetFields(BindingFlags.Static | BindingFlags.Public);
+ BasicToolWindow.reflectedEventNames = new StaticString[fields.Length];
+ for (int index = 0; index < fields.Length; ++index)
+ BasicToolWindow.reflectedEventNames[index] = (StaticString) fields[index].GetValue((object) null);
+ }
+ */
+
+ [SerializeField] private ushort inputFilterGroup = 13;
+ [SerializeField] private ushort inputFilterPrority = 1;
+ private IInputFilterService inputFilterService;
+ private InputFilterDeviceMask devicesToFilter;
+ private int inputFilterHandle = -1;
+
+ protected override void OnDrawWindowClientArea(int instanceId)
+ {
+ if (!this.IsVisible)
return;
+ GUI.color = Color.white;
+ GUI.backgroundColor = Color.white;
+ GUILayout.BeginVertical((GUIStyle) "Widget.ClientArea", GUILayout.ExpandWidth(true));
+ if (this.inputFilterService == null)
+ this.DrawWindow_NoService();
+ else
+ this.DrawClientArea();
+ base.OnDrawWindowClientArea(instanceId);
+ }
+
+ private void DrawWindow_NoService()
+ {
+ GUILayout.Label("Waiting for the input filter service...");
+ if (Event.current.type != EventType.Repaint)
+ return;
+ this.inputFilterService = Services.GetService();
+ }
+
+ private void DrawClientArea()
+ {
+ bool flag1 = (uint) (this.devicesToFilter & InputFilterDeviceMask.Keyboard) > 0U;
+ bool flag2 = (uint) (this.devicesToFilter & InputFilterDeviceMask.Mouse) > 0U;
+ bool flag3 = (uint) (this.devicesToFilter & InputFilterDeviceMask.Gamepad) > 0U;
+ bool flag4 = (uint) (this.devicesToFilter & InputFilterDeviceMask.Touch) > 0U;
+ GUILayout.BeginVertical();
+ GUILayout.Label("Select input device to block:");
+ bool flag5 = GUILayout.Toggle(flag1, "Keyboard");
+ bool flag6 = GUILayout.Toggle(flag2, "Mouse");
+ bool flag7 = GUILayout.Toggle(flag3, "Gamepad");
+ bool flag8 = GUILayout.Toggle(flag4, "Touch");
+ if (GUI.changed)
+ {
+ InputFilterDeviceMask filterMask =
+ (InputFilterDeviceMask) (0 | (flag5 ? 1 : 0) | (flag6 ? 2 : 0) | (flag7 ? 4 : 0) | (flag8 ? 8 : 0));
+ if (filterMask != this.devicesToFilter)
+ this.SetDeviceToFilter(filterMask);
}
- HumankindGame.Empires[0].EnableFogOfWar(enable);
- HumankindGame.Update();
+ GUILayout.EndVertical();
+ }
+
+ private void SetDeviceToFilter(InputFilterDeviceMask filterMask)
+ {
+ if (this.inputFilterHandle != -1)
+ this.inputFilterHandle = this.inputFilterService.DestroyFilter(this.inputFilterHandle);
+ this.devicesToFilter = filterMask;
+ if (this.devicesToFilter == InputFilterDeviceMask.None)
+ return;
+ this.inputFilterHandle = this.inputFilterService.CreateFilter(this.devicesToFilter, this.inputFilterGroup,
+ this.inputFilterPrority, true);
}
}
}
diff --git a/UI/Common/ActionController.cs b/UI/Common/ActionController.cs
new file mode 100644
index 0000000..6b4b1c1
--- /dev/null
+++ b/UI/Common/ActionController.cs
@@ -0,0 +1,69 @@
+using Amplitude.Mercury.Interop;
+using Amplitude.Mercury.Presentation;
+using Amplitude.Mercury.Sandbox;
+using Modding.Humankind.DevTools.DeveloperTools.UI;
+using UnityEngine;
+using Amplitude;
+using Amplitude.Framework;
+using Amplitude.Mercury;
+using Amplitude.Mercury.Simulation;
+
+namespace DevTools.Humankind.GUITools.UI
+{
+ public static partial class ActionController
+ {
+ public static bool IsPresentationFogOfWarEnabled =>
+ Snapshots.GameSnapshot?.PresentationData?.IsPresentationFogOfWarEnabled ?? false;
+
+ public static void TogglePresentationFogOfWar() =>
+ Snapshots.GameSnapshot?.SetFogOfWarEnabled(!IsPresentationFogOfWarEnabled);
+
+ public static void ToggleFreeCameraMode() => FreeCamera.ToggleFreeCameraMode();
+
+ public static FreeCameraController FreeCamera { get; set; } = new FreeCameraController();
+
+ public static PresentationCameraMover CameraMover => _cameraMover ? _cameraMover
+ : (_cameraMover = GameObject.Find("Camera")?.GetComponent());
+
+ public static Camera Camera => _camera ? _camera
+ : (_camera = GameObject.Find("Camera")?.GetComponent());
+
+ public static void SwitchCameraFieldOfView()
+ {
+ var camera = Camera;
+
+ if (camera != null)
+ camera.fieldOfView = camera.fieldOfView < 40f ? (camera.fieldOfView < 30f ? 65f : 15f) : 35f;
+ }
+
+ public static void ToggleTooltipsVisibility() =>
+ UIController.AreTooltipsVisible = !UIController.AreTooltipsVisible;
+
+ public static void ToggleAmplitudeUIVisibility() =>
+ UIController.IsAmplitudeUIVisible = !UIController.IsAmplitudeUIVisible;
+
+ public static void ToggleFrontiersVisibility() => Presentation.PresentationFrontiersController?
+ .DisplayAllFrontiers(!Presentation.PresentationFrontiersController?.FrontiersDisplayed ?? false);
+
+ public static void ToggleGodMode() => UIController.GodMode = !UIController.GodMode;
+ public static void ToggleLiveEditorMode() => LiveEditorMode.Enabled = !LiveEditorMode.Enabled;
+
+ public static bool TryGetDistrictInfoAt(WorldPosition position, out DistrictInfo districtInfo)
+ {
+ DistrictInfo[] array = Snapshots.GameSnapshot.PresentationData.LocalEmpireInfo.DistrictInfo;
+ for (int i = 0; i < array.Length; i++)
+ {
+ if (new WorldPosition(array[i].TileIndex) == position)
+ {
+ districtInfo = array[i];
+ return true;
+ }
+ }
+ districtInfo = default(DistrictInfo);
+ return false;
+ }
+
+ private static Camera _camera = null;
+ private static PresentationCameraMover _cameraMover = null;
+ }
+}
\ No newline at end of file
diff --git a/UI/Common/CursorActionController.cs b/UI/Common/CursorActionController.cs
new file mode 100644
index 0000000..aa1a15e
--- /dev/null
+++ b/UI/Common/CursorActionController.cs
@@ -0,0 +1,77 @@
+using Amplitude.Mercury.Interop;
+using Amplitude.Mercury.Presentation;
+using Amplitude.Mercury.Sandbox;
+using Modding.Humankind.DevTools.DeveloperTools.UI;
+using UnityEngine;
+using Amplitude;
+using Amplitude.Framework;
+using Amplitude.Mercury;
+using Amplitude.Mercury.Simulation;
+
+namespace DevTools.Humankind.GUITools.UI
+{
+ public static partial class ActionController
+ {
+ public static void GiveVisionAtCursorPosition()
+ {
+ SandboxManager.PostOrder(new OrderGiveVisionAtPosition
+ {
+ WorldPosition = Presentation.PresentationCursorController.CurrentHighlightedPosition,
+ VisionRange = 6,
+ DetectionRange = 6,
+ VisionHeight = 10,
+ Duration = 1
+ });
+ }
+
+ public static void CreateCityAtCursorPosition()
+ {
+ SandboxManager.PostOrder(new EditorOrderCreateCityAt
+ {
+ EmpireIndex = (int)Snapshots.GameSnapshot.PresentationData.LocalEmpireInfo.EmpireIndex,
+ CityTileIndex = Presentation.PresentationCursorController.CurrentHighlightedPosition.ToTileIndex()
+ });
+ }
+
+ public static void CreateExtensionDistrictIndustryUnderCursor()
+ {
+ DistrictInfo districtInfo2;
+ if (TryGetDistrictInfoAt(Presentation.PresentationCursorController.CurrentHighlightedPosition, out districtInfo2))
+ {
+ SandboxManager.PostOrder(new EditorOrderCreateExtensionDistrictAt
+ {
+ DistrictDefinitionName = new StaticString("Extension_Base_Industry"),
+ TileIndex = Presentation.PresentationCursorController.CurrentHighlightedPosition.ToTileIndex()
+ });
+ }
+ }
+
+ public static void DestroyDistrictOrSettlementUnderCursor()
+ {
+ DistrictInfo districtInfo3;
+ WorldPosition worldPosition = Presentation.PresentationCursorController.CurrentHighlightedPosition;
+
+ if (TryGetDistrictInfoAt(worldPosition, out districtInfo3))
+ {
+ EditorOrder order2;
+ if (districtInfo3.DistrictDefinitionName == PresentationDistrict.CityCenterDistrictDefinition
+ || districtInfo3.DistrictDefinitionName == PresentationDistrict.CampDistrictDefinition
+ || districtInfo3.DistrictDefinitionName == PresentationDistrict.BeforeCampDistrictDefinition)
+ {
+ order2 = new EditorOrderDestroySettlement
+ {
+ SettlementTileIndex = worldPosition.ToTileIndex()
+ };
+ }
+ else
+ {
+ order2 = new EditorOrderRemoveDistrictAt
+ {
+ TileIndex = worldPosition.ToTileIndex()
+ };
+ }
+ SandboxManager.PostOrder(order2);
+ }
+ }
+ }
+}
diff --git a/UI/Common/KeyMappings.cs b/UI/Common/KeyMappings.cs
new file mode 100644
index 0000000..92b44b2
--- /dev/null
+++ b/UI/Common/KeyMappings.cs
@@ -0,0 +1,250 @@
+using System;
+using BepInEx.Configuration;
+using Modding.Humankind.DevTools;
+using Modding.Humankind.DevTools.DeveloperTools.UI;
+using UnityEngine;
+
+namespace DevTools.Humankind.GUITools.UI
+{
+ public static class KeyMappings
+ {
+ public static string GlobalKeysGroup = "GLOBAL KEYS";
+ public static string OtherKeysGroup = "OTHER KEYS";
+ public static string CameraKeysGroup = "CAMERA / SCREEN PRESENTATION";
+ public static string InteractionKeysGroup = "GAME INTERACTION";
+ public static string UserInterfacesKeysGroup = "GAME UI / GUI TOOLS";
+ public static string LiveEditorKeysGroup = "LIVE EDITOR MODE";
+
+ public static KeyMap[] Keys { get; set; } = new KeyMap[]
+ {
+ new KeyMap("ToggleGameOverviewWindow")
+ {
+ DisplayName = "GAME OVERVIEW FULLSCREEN OVERLAY",
+ Action = MainTools.ToggleGameOverviewWindow,
+ Key = new KeyboardShortcut(KeyCode.Tab),
+ GroupName = GlobalKeysGroup,
+ IsEditable = false,
+ IsRemovable = false
+ },
+ new KeyMap("ToggleHideToolbarWindow")
+ {
+ DisplayName = "HIDE TOOLBAR WINDOW",
+ Action = MainTools.ToggleHideToolbarWindow,
+ Key = new KeyboardShortcut(KeyCode.Home),
+ GroupName = GlobalKeysGroup
+ },
+ new KeyMap("TogglePresentationFogOfWar")
+ {
+ DisplayName = "PRESENTATION FOG OF WAR",
+ Action = ActionController.TogglePresentationFogOfWar,
+ Key = KeyboardShortcut.Empty,
+ GroupName = CameraKeysGroup
+ },
+ new KeyMap("ToggleFreeCameraMode")
+ {
+ DisplayName = "FREE CAMERA MODE",
+ Action = ActionController.ToggleFreeCameraMode,
+ Key = KeyboardShortcut.Empty,
+ GroupName = CameraKeysGroup
+ },
+ new KeyMap("SwitchCameraFieldOfView")
+ {
+ DisplayName = "SWITCH MAIN CAMERA FIELD OF VIEW (15, 35, 65)",
+ Action = ActionController.SwitchCameraFieldOfView,
+ Key = KeyboardShortcut.Empty,
+ GroupName = CameraKeysGroup
+ },
+ new KeyMap("ToggleLiveEditor")
+ {
+ DisplayName = "TOGGLE LIVE EDITOR MODE ON/OFF",
+ Action = ActionController.ToggleLiveEditorMode,
+ Key = new KeyboardShortcut(KeyCode.F4),
+ GroupName = LiveEditorKeysGroup
+ },
+ new KeyMap(LiveEditorMode.ToolboxPreviewActionName, LiveEditorMode.UpdateKeyMappings)
+ {
+ DisplayName = "HOLD FOR QUICK USE OF TOOLBOX",
+ Action = null,
+ Key = new KeyboardShortcut(KeyCode.LeftControl),
+ GroupName = LiveEditorKeysGroup,
+ IsGlobalShortcut = false,
+ IsRemovable = false,
+ },
+ new KeyMap(LiveEditorMode.StickedToolboxActionName, LiveEditorMode.UpdateKeyMappings)
+ {
+ DisplayName = "TOGGLE STICKY TOOLBOX",
+ Action = null,
+ Key = new KeyboardShortcut(KeyCode.Space, KeyCode.LeftControl),
+ GroupName = LiveEditorKeysGroup,
+ IsGlobalShortcut = false,
+ IsRemovable = false,
+ },
+ new KeyMap(LiveEditorMode.CreateUnderCursorActionName, LiveEditorMode.UpdateKeyMappings)
+ {
+ DisplayName = "PAINT/CREATE SELECTED CONSTRUCTIBLE",
+ Action = null,
+ Key = new KeyboardShortcut(KeyCode.Mouse0),
+ GroupName = LiveEditorKeysGroup,
+ IsGlobalShortcut = false,
+ IsRemovable = false,
+ },
+ new KeyMap(LiveEditorMode.DestroyUnderCursorActionName, LiveEditorMode.UpdateKeyMappings)
+ {
+ DisplayName = "DESTROY ARMY/DISTRICT/SETTLEMENT/ETC",
+ Action = null,
+ Key = new KeyboardShortcut(KeyCode.Mouse1),
+ GroupName = LiveEditorKeysGroup,
+ IsGlobalShortcut = false,
+ IsRemovable = false,
+ },
+ new KeyMap(LiveEditorMode.DebugUnderCursorActionName, LiveEditorMode.UpdateKeyMappings)
+ {
+ DisplayName = "PRINT TILE DEBUG INFO TO CONSOLE",
+ Action = null,
+ Key = new KeyboardShortcut(KeyCode.Mouse0, KeyCode.LeftAlt),
+ GroupName = LiveEditorKeysGroup,
+ IsGlobalShortcut = false,
+ },
+ new KeyMap("ToggleGodMode")
+ {
+ DisplayName = "TOGGLE GOD MODE CURSOR",
+ Action = ActionController.ToggleGodMode,
+ Key = KeyboardShortcut.Empty,
+ GroupName = InteractionKeysGroup
+ },
+ new KeyMap("GiveVisionAtCursorPosition")
+ {
+ DisplayName = "GIVE VISION UNDER CURSOR",
+ Action = ActionController.GiveVisionAtCursorPosition,
+ Key = KeyboardShortcut.Empty,
+ GroupName = InteractionKeysGroup
+ },
+ new KeyMap("CreateCityAtCursorPosition")
+ {
+ DisplayName = "CREATE CITY UNDER CURSOR",
+ Action = ActionController.CreateCityAtCursorPosition,
+ Key = KeyboardShortcut.Empty,
+ GroupName = InteractionKeysGroup
+ },
+ new KeyMap("CreateExtensionDistrictIndustryUnderCursor")
+ {
+ DisplayName = "CREATE INDUSTRIAL DISTRICT UNDER CURSOR",
+ Action = ActionController.CreateExtensionDistrictIndustryUnderCursor,
+ Key = KeyboardShortcut.Empty,
+ GroupName = InteractionKeysGroup
+ },
+ new KeyMap("DestroyDistrictOrSettlementUnderCursor")
+ {
+ DisplayName = "DESTROY DISTRICT OR SETTLEMENT UNDER CURSOR",
+ Action = ActionController.DestroyDistrictOrSettlementUnderCursor,
+ Key = KeyboardShortcut.Empty,
+ GroupName = InteractionKeysGroup
+ },
+
+ new KeyMap("ToggleTooltipsVisibility")
+ {
+ DisplayName = "TOGGLE TOOLTIPS VISIBILITY",
+ Action = ActionController.ToggleTooltipsVisibility,
+ Key = KeyboardShortcut.Empty,
+ GroupName = UserInterfacesKeysGroup
+ },
+ new KeyMap("ToggleFrontiersVisibility")
+ {
+ DisplayName = "TOGGLE FRONTIERS VISIBILITY",
+ Action = ActionController.ToggleFrontiersVisibility,
+ Key = KeyboardShortcut.Empty,
+ GroupName = UserInterfacesKeysGroup
+ },
+ new KeyMap("ToggleAmplitudeUIVisibility")
+ {
+ DisplayName = "ENABLE/DISABLE VISIBILITY OF GAME UI",
+ Action = ActionController.ToggleAmplitudeUIVisibility,
+ Key = KeyboardShortcut.Empty,
+ GroupName = UserInterfacesKeysGroup
+ },
+ new KeyMap("ToggleHideAllGUITools")
+ {
+ DisplayName = "VISIBILITY OVERRIDE FOR ALL GUI TOOLS",
+ Action = MainTools.ToggleHideAllUIWindows,
+ Key = KeyboardShortcut.Empty, // new KeyboardShortcut(KeyCode.Insert),
+ GroupName = UserInterfacesKeysGroup,
+ IsEditable = false,
+ SaveAndRestore = false,
+ },
+
+ };
+
+ public static void Apply()
+ {
+ // Loggr.Log("IN KeyMappings.Apply()", ConsoleColor.Green);
+
+ foreach (var key in Keys)
+ {
+ if (key.IsGlobalShortcut)
+ HumankindDevTools.RegisterAction(key.Key, key.ActionName, key.Action);
+ }
+ }
+
+ public static void WritePlayerPreferences(FloatingToolWindow Window)
+ {
+ // Loggr.Log("IN KeyMappings.WritePlayerPreferences()", ConsoleColor.Green);
+
+ foreach (var key in Keys)
+ {
+ if (key.SaveAndRestore)
+ PlayerPrefs.SetString(Window.GetPlayerPrefKey(key.ActionName), key.Key.Serialize());
+ }
+ }
+
+ public static void ReadPlayerPreferences(FloatingToolWindow Window)
+ {
+ // Loggr.Log("IN KeyMappings.ReadPlayerPreferences()", ConsoleColor.Green);
+
+ foreach (var key in Keys)
+ {
+ if (key.SaveAndRestore)
+ key.Key = KeyboardShortcut.Deserialize(
+ PlayerPrefs.GetString(Window.GetPlayerPrefKey(key.ActionName), key.Key.Serialize()));
+ }
+ }
+ }
+
+ public class KeyMap
+ {
+ public KeyboardShortcut Key { get => _key; set => ChangeKey(value); }
+ public string ActionName { get; private set; }
+ public string DisplayName { get; set; }
+ public Action Action { get; set; }
+ public string GroupName { get; set; }
+ public bool IsGlobalShortcut { get; set; } = true;
+ public bool IsRemovable { get; set; } = true;
+ public bool IsEditable { get; set; } = true;
+ public bool SaveAndRestore { get; set; } = true;
+
+ private Action OnKeyChange { get; set; }
+ private KeyboardShortcut _key = KeyboardShortcut.Empty;
+
+ public KeyMap(string actionName, Action onKeyChange = null)
+ {
+ ActionName = actionName.Replace(" ", "_");
+ OnKeyChange = onKeyChange;
+ }
+
+ private void ChangeKey(KeyboardShortcut newKey)
+ {
+ if (!_key.Equals(newKey))
+ {
+ _key = newKey;
+
+ try
+ {
+ OnKeyChange?.Invoke();
+ }
+ catch (Exception)
+ {
+ // ignored
+ }
+ }
+ }
+ }
+}
diff --git a/UI/Common/Settings.cs b/UI/Common/Settings.cs
index aae5e94..5590282 100644
--- a/UI/Common/Settings.cs
+++ b/UI/Common/Settings.cs
@@ -78,7 +78,7 @@ private void DrawContent()
public static class GlobalSettings
{
- public static bool ShouldHideTools => GameStatsWindow.IsVisibleFullscreen || PauseMenu.InGameMenuController.IsEndGameWindowVisible || (HideToolsInGameMenu.Value && PauseMenu.InGameMenuController.IsVisible);
+ public static bool ShouldHideTools => false; // TODO: // GameStatsWindow.IsVisibleFullscreen || PauseMenu.InGameMenuController.IsEndGameWindowVisible || (HideToolsInGameMenu.Value && PauseMenu.InGameMenuController.IsVisible);
public static CheckboxSetting WindowTransparency = new CheckboxSetting(
"Toggles the background transparency of all tool windows.",
@@ -95,7 +95,8 @@ public static class GlobalSettings
"Hide the Toolbar window. \nKEYBOARD SHORTCUT: [ HOME ]", "", false
);
public static CheckboxSetting HideToolsInGameMenu = new CheckboxSetting(
- "Hide all Tool Windows in the Game Menu screen, including the Toolbar window."
+ "Hide all Tool Windows in the Game Menu screen, including the Toolbar window.",
+ "", false
);
public static CheckboxSetting CheatingTools = new CheckboxSetting(R.Text.Bold("Cheating Tools section".ToUpper()));
@@ -118,7 +119,7 @@ public static class GlobalSettings
public static CheckboxSetting CivicsTool = new CheckboxSetting("Civics Tool.");
public static CheckboxSetting CollectiblesTool = new CheckboxSetting("Collectibles Tool.", "", null, false);
public static CheckboxSetting DiplomacyTool = new CheckboxSetting("Diplomacy Tool.", "", null, false);
- public static CheckboxSetting TerrainPickingTool = new CheckboxSetting("Terrain Picking Tool.", "", null, false);
+ public static CheckboxSetting TerrainPickingTool = new CheckboxSetting("Terrain Picking Tool.", "", null, true);
public static CheckboxSetting GameInfoTool = new CheckboxSetting("Game Info Tool.", "", null, false);
public static CheckboxSetting DistrictPainterTool = new CheckboxSetting("District Painter Tool.", "", null, false);
public static CheckboxSetting SettlementTools = new CheckboxSetting("Settlement Tools.", "", null, false);
@@ -166,10 +167,10 @@ public static void WritePlayerPreferences(FloatingToolWindow Window)
public static void ReadPlayerPreferences(FloatingToolWindow Window)
{
- CheatingTools.Value = PlayerPrefs.GetInt(Window.GetPlayerPrefKey("CheatingTools"), CheatingTools.Value ? 1 : 0) != 0;
- ProfilingTools.Value = PlayerPrefs.GetInt(Window.GetPlayerPrefKey("ProfilingTools"), ProfilingTools.Value ? 1 : 0) != 0;
- DeveloperTools.Value = PlayerPrefs.GetInt(Window.GetPlayerPrefKey("DeveloperTools"), DeveloperTools.Value ? 1 : 0) != 0;
- ExperimentalTools.Value = PlayerPrefs.GetInt(Window.GetPlayerPrefKey("ExperimentalTools"), ExperimentalTools.Value ? 1 : 0) != 0;
+ CheatingTools.Value = true; // PlayerPrefs.GetInt(Window.GetPlayerPrefKey("CheatingTools"), CheatingTools.Value ? 1 : 0) != 0;
+ ProfilingTools.Value = false; // PlayerPrefs.GetInt(Window.GetPlayerPrefKey("ProfilingTools"), ProfilingTools.Value ? 1 : 0) != 0;
+ DeveloperTools.Value = true; // PlayerPrefs.GetInt(Window.GetPlayerPrefKey("DeveloperTools"), DeveloperTools.Value ? 1 : 0) != 0;
+ ExperimentalTools.Value = true; // PlayerPrefs.GetInt(Window.GetPlayerPrefKey("ExperimentalTools"), ExperimentalTools.Value ? 1 : 0) != 0;
MilitaryTool.Value = PlayerPrefs.GetInt(Window.GetPlayerPrefKey("MilitaryTool"), MilitaryTool.Value ? 1 : 0) != 0;
ArmyTool.Value = PlayerPrefs.GetInt(Window.GetPlayerPrefKey("ArmyTool"), ArmyTool.Value ? 1 : 0) != 0;
TechnologyTool.Value = PlayerPrefs.GetInt(Window.GetPlayerPrefKey("TechnologyTool"), TechnologyTool.Value ? 1 : 0) != 0;
@@ -193,10 +194,10 @@ public static void ReadPlayerPreferences(FloatingToolWindow Window)
StatisticsAndAchievementsTool.Value = PlayerPrefs.GetInt(Window.GetPlayerPrefKey("StatisticsAndAchievementsTool"), StatisticsAndAchievementsTool.Value ? 1 : 0) != 0;
FameTool.Value = PlayerPrefs.GetInt(Window.GetPlayerPrefKey("FameTool"), FameTool.Value ? 1 : 0) != 0;
EndGameTool.Value = PlayerPrefs.GetInt(Window.GetPlayerPrefKey("EndGameTool"), EndGameTool.Value ? 1 : 0) != 0;
-
+
WindowTransparency.Value = PlayerPrefs.GetInt(Window.GetPlayerPrefKey("WindowTransparency"), WindowTransparency.Value ? 1 : 0) != 0;
WindowTitleBar.Value = PlayerPrefs.GetInt(Window.GetPlayerPrefKey("WindowTitleBar"), WindowTitleBar.Value ? 1 : 0) != 0;
- HideToolbarWindow.Value = PlayerPrefs.GetInt(Window.GetPlayerPrefKey("HideToolbarWindow"), HideToolbarWindow.Value ? 1 : 0) != 0;
+ HideToolbarWindow.Value = false; // PlayerPrefs.GetInt(Window.GetPlayerPrefKey("HideToolbarWindow"), HideToolbarWindow.Value ? 1 : 0) != 0;
HideToolsInGameMenu.Value = PlayerPrefs.GetInt(Window.GetPlayerPrefKey("HideToolsInGameMenu"), HideToolsInGameMenu.Value ? 1 : 0) != 0;
}
}
diff --git a/UI/Common/Utils.cs b/UI/Common/Utils.cs
index 9edf29e..17b18d0 100644
--- a/UI/Common/Utils.cs
+++ b/UI/Common/Utils.cs
@@ -57,7 +57,8 @@ public static void DrawText(string text)
// UNIT UTILL
public static Sprite LoadUnitSprite(Amplitude.StaticString unitName) => LoadUnitSprite(unitName.ToString());
- public static Sprite LoadUnitSprite(string unitName) => SharedAssets.SharedAssets.Load(NormalizeUnitName(unitName));
+ public static Sprite LoadUnitSprite(string unitName) => SharedAssets.SharedAssets.Load(unitName);
+ public static Texture2D LoadTexture(string name) => SharedAssets.SharedAssets.Load(name);
public static string NormalizeUnitName(string unitName) => unitName.Substring(unitName.IndexOf('_') + 1);
// FIDS GAINS AS IMAGE
diff --git a/UI/Drawables.cs b/UI/Drawables.cs
index 2cc2e30..8e6e9af 100644
--- a/UI/Drawables.cs
+++ b/UI/Drawables.cs
@@ -78,299 +78,4 @@ public int Draw() where T : GUIContent
}
}
- public abstract class DrawableGridBase
- {
- public float CellWidth;
- public float CellSpace;
- public GUILayoutOption CellSpan1;
- public GUILayoutOption CellSpan2;
- public GUILayoutOption CellSpan3;
- public GUILayoutOption CellSpan4;
- public GUILayoutOption CellSpan5;
- public GUILayoutOption CellSpan6;
- public GUILayoutOption CellSpan7;
- public GUILayoutOption CellSpan8;
- public GUILayoutOption CellSpan9;
- public GUILayoutOption CellSpan10;
- public GUILayoutOption CellSpan(int numCells) => GUILayout.Width(CellWidth * numCells + CellSpace * (numCells - 1));
-
- public DrawableGridBase()
- {
- Resize(34f, 1f);
- }
-
- public DrawableGridBase(float cellWidth, float cellSpace)
- {
- Resize(cellWidth, cellSpace);
- }
-
- public DrawableGridBase Resize(float cellWidth, float cellSpace)
- {
- CellWidth = cellWidth;
- CellSpace = cellSpace;
- CellSpan1 = CellSpan(1);
- CellSpan2 = CellSpan(2);
- CellSpan3 = CellSpan(3);
- CellSpan4 = CellSpan(4);
- CellSpan5 = CellSpan(5);
- CellSpan6 = CellSpan(6);
- CellSpan7 = CellSpan(7);
- CellSpan8 = CellSpan(8);
- CellSpan9 = CellSpan(9);
- CellSpan10 = CellSpan(10);
-
- return this;
- }
- }
-
- public class DrawableGrid : DrawableGridBase where T : class
- {
-
- public GUIStyle RowStyle { get; set; } = new GUIStyle(UIController.DefaultSkin.FindStyle("PopupWindow.Row"))
- {
- alignment = TextAnchor.LowerRight,
- padding = new RectOffset(0, 0, 0, 0),
- margin = new RectOffset(0, 0, 0, 0),
- hover = new GUIStyleState()
- {
- background = Utils.CreateSinglePixelTexture2D(new Color32(85, 136, 254, 70)),
- textColor = Color.white
- }
- };
-
- public GUIStyle StaticRowStyle { get; set; } = new GUIStyle(UIController.DefaultSkin.FindStyle("PopupWindow.Row"))
- {
- alignment = TextAnchor.LowerRight,
- padding = new RectOffset(0, 0, 0, 0),
- margin = new RectOffset(0, 0, 0, 0),
- normal = new GUIStyleState()
- {
- background = null,
- textColor = Color.white
- },
- hover = new GUIStyleState()
- {
- background = null,
- textColor = Color.white
- }
- };
-
- public GUIStyle CenteredStaticRowStyle { get; set; } = new GUIStyle(UIController.DefaultSkin.FindStyle("PopupWindow.Row"))
- {
- alignment = TextAnchor.LowerCenter,
- padding = new RectOffset(0, 0, 0, 0),
- margin = new RectOffset(0, 0, 0, 0),
- normal = new GUIStyleState()
- {
- background = null,
- textColor = Color.white
- },
- hover = new GUIStyleState()
- {
- background = null,
- textColor = Color.white
- }
- };
-
- public GUIStyle CellStyle { get; set; } = new GUIStyle(UIController.DefaultSkin.FindStyle("PopupWindow.Grid"))
- {
- fontSize = 12,
- normal = new GUIStyleState() {
- background = Utils.CreateSinglePixelTexture2D(new Color(1f, 1f, 1f, 0.35f)),
- textColor = Color.white
- },
- hover = new GUIStyleState() {
- background = null,
- textColor = Color.white
- },
- };
-
- public GUIStyle ColorableCellStyle { get; set; } = new GUIStyle(UIController.DefaultSkin.FindStyle("PopupWindow.Grid"))
- {
- fontSize = 12,
- normal = new GUIStyleState() {
- background = Utils.CreateSinglePixelTexture2D(new Color(1f, 1f, 1f, 0.65f)),
- textColor = Color.white
- },
- hover = new GUIStyleState() {
- background = Utils.CreateSinglePixelTexture2D(new Color(1f, 1f, 1f, 1f)),
- textColor = Color.white
- }
- };
-
- public static readonly RectOffset RectOffsetZero = new RectOffset(0, 0, 0, 0);
-
- public GUIStyle InlineCellContentStyle { get; set; } = new GUIStyle(UIController.DefaultSkin.FindStyle("PopupWindow.Grid"))
- {
- fontSize = 12,
- border = RectOffsetZero,
- padding = RectOffsetZero,
- margin = RectOffsetZero,
- overflow = RectOffsetZero,
- normal = new GUIStyleState() {
- background = null,
- textColor = Color.white,
- },
- hover = new GUIStyleState() {
- background = null,
- textColor = Color.white,
- },
- stretchWidth = false
- };
-
- public GUIStyle RowHeaderStyle { get; set; } = new GUIStyle(UIController.DefaultSkin.FindStyle("PopupWindow.Grid"))
- {
- fontSize = 12,
- alignment = TextAnchor.LowerRight,
- padding = new RectOffset(0, 8, 4, 4),
- normal = new GUIStyleState()
- {
- background = null,
- textColor = Color.white
- }
- };
-
- public GUIStyle CellButtonStyle { get; set; } = new GUIStyle(UIController.DefaultSkin.button) {
- fontSize = 12,
- margin = UIController.DefaultSkin.FindStyle("PopupWindow.Grid").margin,
- padding = UIController.DefaultSkin.FindStyle("PopupWindow.Grid").padding,
- normal = new GUIStyleState() {
- background = Utils.CreateSinglePixelTexture2D(new Color32(85, 136, 254, 150)),
- textColor = Color.white
- },
- hover = new GUIStyleState() {
- background = Utils.CreateSinglePixelTexture2D(new Color32(85, 136, 254, 230)),
- textColor = Color.white
- },
- active = new GUIStyleState() {
- background = Utils.CreateSinglePixelTexture2D(new Color(1f, 1f, 1f, 0.35f)),
- textColor = new Color32(40, 86, 240, 255)
- }
- };
-
- public DrawableGrid Row(GUIStyle style, params GUILayoutOption[] options)
- {
- GUILayout.BeginHorizontal(style, options);
-
- return this;
- }
-
- public DrawableGrid Row(params GUILayoutOption[] options)
- {
- GUILayout.BeginHorizontal(RowStyle, options);
-
- return this;
- }
-
- public DrawableGrid EndRow()
- {
- GUILayout.EndHorizontal();
-
- return this;
- }
-
- public DrawableGrid EmptyRow(params GUILayoutOption[] options)
- {
- GUILayout.BeginHorizontal(StaticRowStyle, options);
- GUILayout.Label(" ", RowHeaderStyle);
- GUILayout.EndHorizontal();
-
- return this;
- }
-
- public DrawableGrid VerticalStack(params GUILayoutOption[] options)
- {
- GUILayout.BeginVertical(StaticRowStyle, options);
-
- return this;
- }
-
- public DrawableGrid EndVerticalStack(params GUILayoutOption[] options)
- {
- GUILayout.EndVertical();
-
- return this;
- }
-
- public DrawableGrid Cell(string text, GUIStyle style, params GUILayoutOption[] options)
- {
- GUILayout.Label(text, style, options);
-
- return this;
- }
-
- public DrawableGrid Cell(string text, params GUILayoutOption[] options)
- {
- GUILayout.Label(text, CellStyle, options);
-
- return this;
- }
-
- public DrawableGrid Cell(string text, Color color, params GUILayoutOption[] options)
- {
- var prevColor = GUI.backgroundColor;
- GUI.backgroundColor = color;
-
- GUILayout.Label("" + text + "", CellStyle, options);
-
- GUI.backgroundColor = prevColor;
-
- return this;
- }
-
- public DrawableGrid Cell(string text, GUIStyle style, Color color, params GUILayoutOption[] options)
- {
- var prevColor = GUI.backgroundColor;
- GUI.backgroundColor = color;
-
- GUILayout.Label("" + text + "", style, options);
-
- GUI.backgroundColor = prevColor;
-
- return this;
- }
-
- public DrawableGrid RowHeader(string text, GUIStyle style, params GUILayoutOption[] options)
- {
- GUILayout.Label("" + text + "", style, options);
-
- return this;
- }
-
- public DrawableGrid RowHeader(string text, params GUILayoutOption[] options)
- {
- GUILayout.Label("" + text + "", RowHeaderStyle, options);
-
- return this;
- }
-
- public virtual DrawableGrid Iterate(Action action) => this;
- public virtual DrawableGrid Iterate(Action action) => this;
- public virtual DrawableGrid Iterate(Action action) => this;
-
- public virtual DrawableGrid CellButton(string text, Action action, params GUILayoutOption[] options) => this;
- public virtual DrawableGrid CellButton(string text, Action action, params GUILayoutOption[] options) => this;
- public virtual DrawableGrid CellButton(string text, Action action, params GUILayoutOption[] options) => this;
-
- public DrawableGrid DrawHorizontalLine(float alpha = 0.3f)
- {
- Utils.DrawHorizontalLine(alpha);
-
- return this;
- }
-
- public DrawableGrid DrawHorizontalLine(float alpha, float width)
- {
- Utils.DrawHorizontalLine(alpha, width);
-
- return this;
- }
-
- public DrawableGrid Space(float size)
- {
- GUILayout.Space(size);
-
- return this;
- }
- }
}
diff --git a/UI/InGameMenu/InGameMenuWindow.cs b/UI/InGameMenu/InGameMenuWindow.cs
index fbfe213..9e26705 100644
--- a/UI/InGameMenu/InGameMenuWindow.cs
+++ b/UI/InGameMenu/InGameMenuWindow.cs
@@ -307,6 +307,7 @@ public override void OnWritePlayerPreferences()
base.OnWritePlayerPreferences();
GlobalSettings.WritePlayerPreferences(this);
+ KeyMappings.WritePlayerPreferences(this);
}
public override void OnReadPlayerPreferences()
@@ -314,6 +315,8 @@ public override void OnReadPlayerPreferences()
base.OnReadPlayerPreferences();
GlobalSettings.ReadPlayerPreferences(this);
+ KeyMappings.ReadPlayerPreferences(this);
+ KeyMappings.Apply();
}
private static string GreenText(string text) => "" + text + "";
diff --git a/UI/MainToolbar.cs b/UI/MainToolbar.cs
index 4aa4019..8b8768e 100644
--- a/UI/MainToolbar.cs
+++ b/UI/MainToolbar.cs
@@ -8,8 +8,7 @@ namespace DevTools.Humankind.GUITools.UI
{
public class MainToolbar : FloatingToolWindow
{
- public override bool ShouldBeVisible => !GlobalSettings.ShouldHideTools &&
- HumankindGame.IsGameLoaded && !GlobalSettings.HideToolbarWindow.Value;
+ public override bool ShouldBeVisible => !GlobalSettings.ShouldHideTools /* TODO: && HumankindGame.IsGameLoaded */ && !GlobalSettings.HideToolbarWindow.Value;
public override bool ShouldRestoreLastWindowPosition => true;
public override string WindowTitle { get; set; } = "TOOLBAR";
public override Rect WindowRect { get; set; } = new Rect (30, 290, 170, 600);
@@ -107,9 +106,8 @@ public override void OnDrawUI()
GUILayout.BeginHorizontal(TintableBackgroundStyle);
GUI.backgroundColor = Color.black;
- GUILayout.BeginVertical(BackgroundContainerStyle);
-
-
+ GUILayout.BeginVertical(BackgroundContainerStyle);
+
OnDrawCheatingTools();
GUI.backgroundColor = Color.black;
OnDrawDeveloperTools();
diff --git a/UI/Presentation/FreeCamera.cs b/UI/Presentation/FreeCamera.cs
new file mode 100644
index 0000000..72f98dc
--- /dev/null
+++ b/UI/Presentation/FreeCamera.cs
@@ -0,0 +1,68 @@
+using Amplitude.Mercury.Presentation;
+using UnityEngine;
+
+namespace DevTools.Humankind.GUITools.UI
+{
+ public class FreeCamera : MonoBehaviour
+ {
+ public float cameraSensitivity = 15;
+ public float climbSpeed = 8;
+ public float normalMoveSpeed = 12;
+
+ public float slowMoveFactor;
+ public float fastMoveFactor;
+
+ public float rotationX = 5f;
+ public float rotationY = -26f;
+
+ public Camera LinkedCamera { get; set; } = null;
+ public PresentationCameraMover CameraMover { get; set; } = null;
+
+ public Transform GetTransform() => transform;
+ void Update()
+ {
+ rotationX += Input.GetAxis("Mouse X") * cameraSensitivity * Time.deltaTime;
+ rotationY += Input.GetAxis("Mouse Y") * cameraSensitivity * Time.deltaTime;
+
+
+ rotationY = Mathf.Clamp(rotationY, -90f, -5f);
+
+ transform.localRotation = Quaternion.AngleAxis(rotationX, Vector3.up);
+ transform.localRotation *= Quaternion.AngleAxis(rotationY, Vector3.left);
+
+ if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))
+ {
+ fastMoveFactor = 3;
+ }
+ else
+ {
+ fastMoveFactor = 1;
+ }
+
+ if (Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl))
+ {
+ slowMoveFactor = 0.25f;
+ }
+ else
+ {
+ slowMoveFactor = 1;
+ }
+
+ transform.position += transform.forward * normalMoveSpeed * slowMoveFactor * fastMoveFactor *
+ Input.GetAxis("Vertical") * Time.deltaTime;
+ transform.position += transform.right * normalMoveSpeed * slowMoveFactor * fastMoveFactor *
+ Input.GetAxis("Horizontal") * Time.deltaTime;
+
+
+ if (Input.GetKey(KeyCode.Q))
+ {
+ transform.position += transform.up * climbSpeed * slowMoveFactor * fastMoveFactor * Time.deltaTime;
+ }
+
+ if (Input.GetKey(KeyCode.E))
+ {
+ transform.position -= transform.up * climbSpeed * slowMoveFactor * fastMoveFactor * Time.deltaTime;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/UI/Presentation/FreeCameraController.cs b/UI/Presentation/FreeCameraController.cs
new file mode 100644
index 0000000..ac6b1b0
--- /dev/null
+++ b/UI/Presentation/FreeCameraController.cs
@@ -0,0 +1,79 @@
+using UnityEngine;
+using Amplitude.Mercury.Presentation;
+using Modding.Humankind.DevTools;
+using Modding.Humankind.DevTools.DeveloperTools.UI;
+
+namespace DevTools.Humankind.GUITools.UI
+{
+ public class FreeCameraController
+ {
+ public bool cameraBool;
+ public float nearClip = 33.93487f; //orig values
+ public float farClip = 113.942f;
+
+ public GameObject cameraGo;
+ public PresentationCameraMover presCamMover;
+ public FreeCamera FreeCam;
+ public Camera cameraCam;
+
+ public void Setup()
+ {
+ cameraBool = false;
+ cameraGo = GameObject.Find("Camera");
+ if (cameraGo == null)
+ {
+ Loggr.Log("NullRef, No Camera GameObject found");
+ }
+
+ //this is the default script the game uses to control the camera
+ presCamMover = cameraGo.GetComponent();
+ if (presCamMover == null)
+ {
+ Loggr.Log("NullRef, No PresentationCameraMover found");
+ }
+
+ cameraCam = cameraGo.GetComponent();
+
+ Quaternion localRotation = cameraGo.transform.localRotation;
+ Vector3 position = cameraGo.transform.position;
+
+ FreeCam = cameraGo.AddComponent();
+
+ nearClip = cameraCam.nearClipPlane; //in case of different camera settings
+ farClip = cameraCam.farClipPlane;
+
+ FreeCam.transform.position = new Vector3(position.x, 25f, position.z);
+ FreeCam.transform.localRotation = localRotation;
+ }
+
+ public void ToggleFreeCameraMode()
+ {
+ if (!cameraGo)
+ {
+ Setup();
+ }
+
+ cameraBool = !cameraBool;
+ presCamMover.enabled = !cameraBool;
+ FreeCam.enabled = cameraBool;
+ //GUI.enabled = !GUI.enabled;
+
+ if (cameraBool == true)
+ {
+ UnityEngine.Cursor.lockState = CursorLockMode.Locked;
+ cameraCam.nearClipPlane = 0.01f;
+ cameraCam.farClipPlane = farClip * 2;
+ if (UIController.AreTooltipsVisible)
+ ActionController.ToggleAmplitudeUIVisibility();
+ }
+ else
+ {
+ UnityEngine.Cursor.lockState = CursorLockMode.None;
+ cameraCam.nearClipPlane = nearClip;
+ cameraCam.farClipPlane = farClip;
+ if (!UIController.AreTooltipsVisible)
+ ActionController.ToggleAmplitudeUIVisibility();
+ }
+ }
+ }
+}
diff --git a/UI/Statistics/GameGrid/CommonHeadersGrid.cs b/UI/Statistics/GameGrid/CommonHeadersGrid.cs
new file mode 100644
index 0000000..c5f8c95
--- /dev/null
+++ b/UI/Statistics/GameGrid/CommonHeadersGrid.cs
@@ -0,0 +1,119 @@
+using System.Linq;
+using StyledGUI;
+using StyledGUI.VirtualGridElements;
+using System;
+using Modding.Humankind.DevTools;
+using Amplitude.Mercury.Interop;
+using Amplitude.Mercury.Sandbox;
+using Amplitude.Framework;
+using Amplitude.Framework.Networking;
+using UnityEngine;
+
+
+namespace DevTools.Humankind.GUITools.UI
+{
+ public class StaticHeaderGrid : GridStyles { }
+
+ public class CommonHeadersGrid
+ {
+ public VirtualGrid VirtualGrid { get; set; }
+ public GameStatsSnapshot Snapshot { get; set; }
+ public bool IsDirty { get; set; } = true;
+ public const string PerTurn = "/ TURN";
+
+ protected IStyledGrid Grid;
+
+ public CommonHeadersGrid() { }
+
+ public void Render()
+ {
+ if (IsDirty)
+ Update();
+
+ VirtualGrid.Render();
+ }
+
+ public void Update()
+ {
+ Grid = VirtualGrid.Grid;
+ ComputeVirtualGrid();
+
+ IsDirty = false;
+ }
+
+ private void ComputeVirtualGrid()
+ {
+ VirtualGrid.Columns = new[]
+ {
+ new Column() { Name = "GLOBAL"}
+ };
+
+ VirtualGrid.Sections = new[]
+ {
+ new Section()
+ {
+ Rows = new []
+ {
+ new Row()
+ {
+ Style = Styles.StaticRowStyle,
+ Cells = new ICell[]
+ {
+ new CellGroup()
+ {
+ Cells = new ICell[]
+ {
+ new Cell() { Text = "TURN", Style = Styles.RowHeaderStyle, Span = Grid.CellSpan2 },
+ new Cell() { Text = "" + Snapshot.Turn + "", Span = Grid.CellSpan1 },
+ new Cell() { Text = "ATMOSPHERE POLLUTION", Style = Styles.RowHeaderStyle, Span = Grid.CellSpan5 },
+ new Cell() { Text = "LEVEL " + Snapshot.AtmospherePollutionLevel + "", Span = Grid.CellSpan2 },
+ new Cell() { Span = Grid.CellSpan4, Text = "" + Snapshot.AtmospherePollutionStock + "" +
+ (Snapshot.AtmospherePollutionNet >= 0 ? " ( +" : " ( ") +
+ Snapshot.AtmospherePollutionNet + " " + PerTurn + " )" },
+ new ClickableCell() { Span = Grid.CellSpan1, Text = "-2K", Action = OnRemove2kPollution },
+ new ClickableCell() { Span = Grid.CellSpan1, Text = "-250", Action = OnRemove250Pollution },
+ new ClickableCell() { Span = Grid.CellSpan1, Text = "+250", Action = OnAdd250Pollution },
+ new ClickableCell() { Span = Grid.CellSpan1, Text = "+2K", Action = OnAdd2kPollution },
+ }
+ }
+ }
+ },
+ },
+ SpaceBefore = 0
+ },
+ };
+ }
+
+ private void Trigger(Action action)
+ {
+ // some actions tracking stuff here
+ action.Invoke();
+ // Trigger update
+ GameStatsWindow.ResetLoop();
+ }
+
+ private void OnRemove2kPollution(int _) =>
+ Trigger(() => SandboxManager.PostOrder((Order)new EditorOrderAddOrRemoveAtmospherePollution()
+ {
+ Delta = -2000
+ }, (int)Snapshots.GameSnapshot.PresentationData.LocalEmpireInfo.EmpireIndex));
+
+ private void OnRemove250Pollution(int _) =>
+ Trigger(() => SandboxManager.PostOrder((Order)new EditorOrderAddOrRemoveAtmospherePollution()
+ {
+ Delta = -250
+ }, (int)Snapshots.GameSnapshot.PresentationData.LocalEmpireInfo.EmpireIndex));
+
+ private void OnAdd250Pollution(int _) =>
+ Trigger(() => SandboxManager.PostOrder((Order)new EditorOrderAddOrRemoveAtmospherePollution()
+ {
+ Delta = 250
+ }, (int)Snapshots.GameSnapshot.PresentationData.LocalEmpireInfo.EmpireIndex));
+
+ private void OnAdd2kPollution(int _) =>
+ Trigger(() => SandboxManager.PostOrder((Order)new EditorOrderAddOrRemoveAtmospherePollution()
+ {
+ Delta = 2000
+ }, (int)Snapshots.GameSnapshot.PresentationData.LocalEmpireInfo.EmpireIndex));
+ }
+}
\ No newline at end of file
diff --git a/UI/Statistics/GameGrid/GameGrid.cs b/UI/Statistics/GameGrid/GameGrid.cs
new file mode 100644
index 0000000..e118a13
--- /dev/null
+++ b/UI/Statistics/GameGrid/GameGrid.cs
@@ -0,0 +1,267 @@
+using System.Linq;
+using StyledGUI;
+using StyledGUI.VirtualGridElements;
+using System;
+using Modding.Humankind.DevTools;
+using Amplitude.Mercury.Interop;
+using Amplitude.Mercury.Sandbox;
+using Amplitude.Framework;
+using Amplitude.Framework.Networking;
+using UnityEngine;
+
+namespace DevTools.Humankind.GUITools.UI
+{
+
+ public class GameOverviewGrid : GridStyles { }
+
+ public class GameGrid
+ {
+ public VirtualGrid VirtualGrid { get; set; }
+ public GameStatsSnapshot Snapshot { get; set; }
+ public bool IsDirty { get; set; } = true;
+ public const string PerTurn = "/ TURN";
+
+ protected IStyledGrid Grid;
+
+ public GameGrid() { }
+
+ public void Render()
+ {
+ if (IsDirty)
+ Update();
+
+ VirtualGrid.Render();
+ }
+
+ public void Update()
+ {
+ Grid = VirtualGrid.Grid;
+ ComputeVirtualGrid();
+
+ IsDirty = false;
+ }
+
+ private void ComputeVirtualGrid()
+ {
+ VirtualGrid.Columns = Snapshot.Empires.Select(empire => new Column()
+ {
+ Name = empire.UserName
+ }).ToArray();
+
+ VirtualGrid.Sections = new[]
+ {
+ new Section()
+ {
+ Rows = new []
+ {
+ new Row() { Cells = Snapshot.Empires.Select(empire => new Cell()
+ {
+ Text = (empire.Index == Snapshot.LocalEmpireIndex) ?
+ "A C T I V E" : " ",
+ Style = Styles.CenteredStaticRowStyle
+ }), Style = Styles.StaticRowStyle },
+ new Row() { Cells = Snapshot.Empires.Select(empire => new TintableCell()
+ {
+ Text = "" + empire.UserName + "",
+ BackgroundColor = empire.Color,
+ Color = empire.SecondaryColor
+ }), Style = Styles.StaticRowStyle }
+ },
+ SpaceBefore = 0
+ },
+ new Section()
+ {
+ SpaceBefore = 4f,
+ Rows = new[]
+ {
+ new Row() { Title = "TERRITORIES, CITIES / MAX",
+ Cells = Snapshot.Empires.Select(e => new CellGroup() { Cells = new ICell[] {
+ new Cell() { Text = e.TerritoryCount, Span = Grid.CellSpan1},
+ new Cell() { Text = e.CityCount + " / " + e.CityCap, Span = Grid.CellSpan3},
+ }})},
+ new Row() { Title = "STABILITY",
+ Cells = Snapshot.Empires.Select(e => new CompositeCell() { Elements = new IElement[] {
+ new TextElement() { Text = e.Stability },
+ new ImageElement() { Image = Utils.StabilityTexture },
+ }})},
+ new Row() { Title = "ERA LEVEL, SUM OF ERA STARS",
+ Cells = Snapshot.Empires.Select(e => new CellGroup() { Cells = new ICell[] {
+ new Cell() { Text = e.EraLevel, Span = Grid.CellSpan1},
+ new Cell() { Text = e.SumOfEraStars, Span = Grid.CellSpan3},
+ }})},
+ new Row() { Title = "CITIZENS, EMPIRE POPULATION",
+ Cells = Snapshot.Empires.Select(e => new CellGroup() { Cells = new ICell[] {
+ new Cell() { Text = e.SettlementsPopulation, Span = Grid.CellSpan2},
+ new Cell() { Text = e.EmpirePopulation, Span = Grid.CellSpan2},
+ }})},
+ new Row() { Title = "POLLUTION",
+ Cells = Snapshot.Empires.Select(e => new CellGroup() { Cells = new ICell[] {
+ new Cell() { Text = e.PollutionStock, Span = Grid.CellSpan2},
+ new Cell() { Text = (int.Parse(e.PollutionNet) >= 0 ? "+" : "") +
+ e.PollutionNet + " " + PerTurn, Span = Grid.CellSpan2},
+ }})}
+ }
+ },
+ new Section()
+ {
+ Title = "MILITARY STATS",
+ Rows = new[]
+ {
+ QuickTextRow("COMBAT STRENGTH", e => e.CombatStrength),
+ new Row() { Title = "ARMIES, TOTAL UNITS",
+ Cells = Snapshot.Empires.Select(e => new CellGroup() { Cells = new ICell[] {
+ new Cell() { Text = e.ArmyCount, Span = Grid.CellSpan2},
+ new Cell() { Text = e.UnitCount, Span = Grid.CellSpan2},
+ }})},
+ new Row() { Title = "MILITARY UPKEEP",
+ Cells = Snapshot.Empires.Select(e => new CompositeCell() { Elements = new IElement[] {
+ new TextElement() { Text = e.MilitaryUpkeep },
+ new ImageElement() { Image = Utils.MoneyTexture },
+ new TextElement() { Text = PerTurn },
+ }})},
+ }
+ },
+ new Section()
+ {
+ Title = "RESEARCH STATS",
+ Rows = new[]
+ {
+ new Row() { Title = "SCIENCE",
+ Cells = Snapshot.Empires.Select(e => new CellGroup() { Cells = new ICell[] {
+ new CompositeCell() { Span = Grid.CellSpan3, Elements = new IElement[] {
+ new TextElement() { Text = "+" + e.ResearchNet },
+ new ImageElement() { Image = Utils.ScienceTexture },
+ new TextElement() { Text = PerTurn }}},
+ new ClickableCell() { Span = Grid.CellSpan1, Text = "+5K", Action = OnAdd5kResearch }
+ }})},
+ new Row() { Title = "AVAILABLE, UNLOCKED",
+ Cells = Snapshot.Empires.Select(e => new CellGroup() { Cells = new ICell[] {
+ new Cell() { Text = e.AvailableTechnologiesCount, Span = Grid.CellSpan2},
+ new Cell() { Text = e.UnlockedTechnologiesCount, Span = Grid.CellSpan2},
+ }})},
+ QuickTextRow("TECHNOLOGICAL ERA OFFSET", e => e.TechnologicalEraOffset),
+ }
+ },
+ new Section()
+ {
+ Title = "ECONOMIC STATS",
+ Rows = new[]
+ {
+ new Row() { Title = "MONEY",
+ Cells = Snapshot.Empires.Select(e => new CompositeCell() { Elements = new IElement[] {
+ new TextElement() { Text = e.MoneyNet },
+ new ImageElement() { Image = Utils.MoneyTexture },
+ new TextElement() { Text = PerTurn },
+ }})},
+ new Row() { Title = "MONEY STOCK",
+ Cells = Snapshot.Empires.Select(e => new CellGroup() { Cells = new ICell[] {
+ new CompositeCell() { Span = Grid.CellSpan2, Elements = new IElement[] {
+ new TextElement() { Text = e.MoneyStock },
+ new ImageElement() { Image = Utils.MoneyTexture }}},
+ new ClickableCell() { Span = Grid.CellSpan1, Text = "-500", Action = OnRemove500Money },
+ new ClickableCell() { Span = Grid.CellSpan1, Text = "+5K", Action = OnAdd5kMoney }
+ }})},
+ new Row() { Title = "INFLUENCE",
+ Cells = Snapshot.Empires.Select(e => new CompositeCell() { Elements = new IElement[] {
+ new TextElement() { Text = "+" + e.InfluenceNet },
+ new ImageElement() { Image = Utils.InfluenceTexture },
+ new TextElement() { Text = PerTurn },
+ }})},
+ new Row() { Title = "INFLUENCE STOCK",
+ Cells = Snapshot.Empires.Select(e => new CellGroup() { Cells = new ICell[] {
+ new CompositeCell() { Span = Grid.CellSpan2, Elements = new IElement[] {
+ new TextElement() { Text = e.InfluenceStock },
+ new ImageElement() { Image = Utils.InfluenceTexture }}},
+ new ClickableCell() { Span = Grid.CellSpan1, Text = "-75", Action = OnRemove75Influence },
+ new ClickableCell() { Span = Grid.CellSpan1, Text = "+250", Action = OnAdd250Influence }
+ }})},
+ QuickTextRow("TOTAL TRADE NODES", e => e.TradeNodesCount),
+ new Row() { Title = "LUXURY, STRATEGIC ACCESS COUNT",
+ Cells = Snapshot.Empires.Select(e => new CellGroup() { Cells = new ICell[] {
+ new Cell() { Text = e.LuxuryResourcesAccessCount, Span = Grid.CellSpan2},
+ new Cell() { Text = e.StrategicResourcesAccessCount, Span = Grid.CellSpan2},
+ }})},
+ }
+ },
+ new Section()
+ {
+ SpaceBefore = 4f,
+ Rows = new[]
+ {
+ new Row() { Cells = Snapshot.Empires.Select(e => new ClickableCell() {
+ Text = "SWITCH EMPIRE",
+ Action = OnSwitchEmpire,
+ Span = Grid.CellSpan4,
+ Enabled = e.Index != Snapshot.LocalEmpireIndex
+ }
+ ), Style = Styles.StaticRowStyle }
+ }
+ }
+ };
+
+
+ }
+
+ private void Trigger(Action action)
+ {
+ // some actions tracking stuff here
+ action.Invoke();
+ // Trigger update
+ GameStatsWindow.ResetLoop();
+ }
+
+ private void OnAdd5kMoney(int empireIndex) =>
+ Trigger(() => HumankindGame.Empires[empireIndex].MoneyStock += 5000);
+
+ private void OnRemove500Money(int empireIndex) =>
+ Trigger(() => HumankindGame.Empires[empireIndex].MoneyStock -= 500);
+
+ private void OnAdd250Influence(int empireIndex) =>
+ Trigger(() => HumankindGame.Empires[empireIndex].InfluenceStock += 250);
+
+ private void OnRemove75Influence(int empireIndex) =>
+ Trigger(() => HumankindGame.Empires[empireIndex].InfluenceStock -= 75);
+
+ private void OnAdd5kResearch(int empireIndex) =>
+ Trigger(() => HumankindGame.Empires[empireIndex].ResearchStock = 5000);
+
+ private void OnSwitchEmpire(int empireIndex)
+ {
+ Trigger(() =>
+ {
+ try
+ {
+ Services.GetService()?.CreateMessageSender().SendLocalMessage(
+ (LocalMessage) new SandboxControlMessage(
+ (ISandboxControlInstruction) new ChangeLocalEmpireInstruction(empireIndex)
+ )
+ );
+ HumankindGame.Empires
+ .Where(emp => emp.EmpireIndex == empireIndex)
+ .Settlements()
+ .IsCapital()
+ .First()
+ .CenterToCamera();
+ }
+ catch (Exception)
+ {
+ HumankindGame.Empires
+ .Where(emp => emp.EmpireIndex == empireIndex)
+ .Armies()
+ .First()
+ .CenterToCamera();
+ }
+ });
+ }
+
+ private Row QuickTextRow(string title, Func builder) =>
+ new Row()
+ {
+ Title = title,
+ Cells = Snapshot.Empires.Select(empire => new Cell()
+ {
+ Text = builder.Invoke(empire)
+ })
+ };
+ }
+}
\ No newline at end of file
diff --git a/UI/Statistics/GameGrid/KeyboardShortcutsGrid.cs b/UI/Statistics/GameGrid/KeyboardShortcutsGrid.cs
new file mode 100644
index 0000000..d7dfcdf
--- /dev/null
+++ b/UI/Statistics/GameGrid/KeyboardShortcutsGrid.cs
@@ -0,0 +1,198 @@
+using System.Linq;
+using StyledGUI;
+using StyledGUI.VirtualGridElements;
+using System;
+using System.Collections.Generic;
+using Modding.Humankind.DevTools;
+using Amplitude.Mercury.Interop;
+using Amplitude.Mercury.Sandbox;
+using Amplitude.Framework;
+using Amplitude.Framework.Networking;
+using BepInEx.Configuration;
+using UnityEngine;
+
+
+namespace DevTools.Humankind.GUITools.UI
+{
+ public class KeyMapEntry
+ {
+ public int Index { get; set; }
+ public KeyMap KeyMap { get; set; }
+ public KeyboardShortcutField Field { get; set; }
+ public bool HasPendingAction { get; set; } = false;
+ public bool HasInvalidValue { get; set; } = false;
+ }
+
+ public class ShortcutsGrid : GridStyles { }
+
+ public class KeyboardShortcutsGrid
+ {
+ public VirtualGrid VirtualGrid { get; set; }
+ public bool IsDirty { get; set; } = true;
+
+ protected IStyledGrid Grid;
+
+ public KeyMapEntry[] Entries { get; private set; }
+
+ private List KeyGroups = new List();
+
+ public KeyboardShortcutsGrid()
+ {
+ ResyncKeyMappings();
+ }
+
+ public void ResyncKeyMappings()
+ {
+ Entries = KeyMappings.Keys.Select((keyMap, i) => new KeyMapEntry() {
+ Index = i,
+ KeyMap = keyMap,
+ Field = CreateShortcutField(keyMap.Key)
+ }).ToArray();
+
+ foreach (var keyMap in KeyMappings.Keys)
+ {
+ if (!KeyGroups.Contains(keyMap.GroupName))
+ KeyGroups.Add(keyMap.GroupName);
+ }
+ }
+
+ public static KeyboardShortcutField CreateShortcutField(KeyboardShortcut initialValue) =>
+ new KeyboardShortcutField(initialValue)
+ {
+ DefaultText = "START PRESSING ANY KEY...",
+ DisplayTextPrefix = "",
+ DisplayTextPostfix = ""
+ };
+
+ public void Render()
+ {
+ if (IsDirty)
+ Update();
+
+ VirtualGrid.Render();
+ }
+
+ public void Update()
+ {
+ Grid = VirtualGrid.Grid;
+ ComputeVirtualGrid();
+
+ IsDirty = false;
+ }
+
+ private void ComputeVirtualGrid()
+ {
+ VirtualGrid.Columns = new[]
+ {
+ new Column() { Name = "Keyboard Shortcuts"}
+ };
+
+ VirtualGrid.Sections = (new Section[]
+ {
+ BuildSection(KeyMappings.GlobalKeysGroup),
+ })
+ .Concat(
+ KeyGroups
+ .Where(groupName => groupName != KeyMappings.GlobalKeysGroup)
+ .Select(group => BuildSection(group)).ToArray()
+ ).ToArray();
+ }
+
+ private Color InvalidColor { get; set; } = new Color32(200, 15, 35, 230);
+
+ private Section BuildSection(string sectionName)
+ {
+ return new Section()
+ {
+ Title = "" + sectionName + "",
+ Rows = Entries.Where(entry => entry.KeyMap.GroupName == sectionName).Select(entry => new Row()
+ {
+ Style = Styles.StaticRowStyle,
+ Title = entry.KeyMap.DisplayName.ToUpper(),
+ Cells = new ICell[]
+ {
+ new CellGroup()
+ {
+ Cells = new ICell[]
+ {
+ new KeyboardShortcutCell()
+ {
+ Span = Grid.CellSpan8,
+ Field = entry.Field,
+ Index = entry.Index,
+ Action = OnDoneCapturing,
+ Color = entry.HasInvalidValue ? InvalidColor : Color.white,
+ Enabled = entry.KeyMap.IsEditable
+ },
+ new ClickableCell()
+ {
+ Span = Grid.CellSpan2,
+ Enabled = entry.KeyMap.IsEditable && entry.HasPendingAction && !entry.HasInvalidValue,
+ Text = "APPLY",
+ Index = entry.Index,
+ Action = OnApply
+ },
+ new ClickableCell()
+ {
+ Span = Grid.CellSpan2,
+ Enabled = entry.HasPendingAction || (!entry.HasPendingAction &&
+ entry.KeyMap.IsRemovable &&
+ !entry.KeyMap.Key.Equals(
+ KeyboardShortcut.Empty)),
+ Text = (entry.HasPendingAction
+ ? "CANCEL"
+ : "REMOVE"),
+ Index = entry.Index,
+ Action = OnHandleAction
+ }
+ }
+ }
+ }
+ }).ToArray()
+ };
+ }
+
+ private void OnDoneCapturing(int index)
+ {
+ Entries[index].HasPendingAction = true;
+
+ KeyboardShortcut capturedKey = Entries[index].Field.Value;
+
+ Entries[index].HasInvalidValue = Entries.Any(entry => entry.Index != index && entry.KeyMap.Key.Equals(capturedKey));
+ IsDirty = true;
+ }
+
+ private void OnApply(int index)
+ {
+ Entries[index].HasPendingAction = false;
+ Entries[index].KeyMap.Key = Entries[index].Field.Value;
+
+ KeyMappings.Apply();
+ IsDirty = true;
+ }
+
+
+ private void OnHandleAction(int index)
+ {
+ if (Entries[index].HasPendingAction)
+ {
+ // Cancel action
+ Entries[index].Field = CreateShortcutField(Entries[index].KeyMap.Key);
+
+ Entries[index].HasInvalidValue = false;
+ }
+ else
+ {
+ // Remove action
+ Entries[index].KeyMap.Key = KeyboardShortcut.Empty;
+ Entries[index].Field = CreateShortcutField(Entries[index].KeyMap.Key);
+
+ KeyMappings.Apply();
+ }
+
+ Entries[index].HasPendingAction = false;
+ IsDirty = true;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/UI/Statistics/GameGrid/SettlementsGrid.cs b/UI/Statistics/GameGrid/SettlementsGrid.cs
new file mode 100644
index 0000000..be28a11
--- /dev/null
+++ b/UI/Statistics/GameGrid/SettlementsGrid.cs
@@ -0,0 +1,131 @@
+using System.Linq;
+using StyledGUI;
+using StyledGUI.VirtualGridElements;
+using System;
+using Modding.Humankind.DevTools;
+using Amplitude.Mercury.Interop;
+using Amplitude.Mercury.Sandbox;
+using Amplitude.Framework;
+using Amplitude.Framework.Networking;
+using UnityEngine;
+
+namespace DevTools.Humankind.GUITools.UI
+{
+
+ public class EmpireSettlementsGrid : GridStyles { }
+
+ public class SettlementsGrid
+ {
+ public VirtualGrid VirtualGrid { get; set; }
+ public GameStatsSnapshot Snapshot { get; set; }
+ public bool IsDirty { get; set; } = true;
+ public const string PerTurn = "/ TURN";
+
+ protected IStyledGrid Grid;
+
+ public SettlementsGrid() { }
+
+ public void Render()
+ {
+ if (IsDirty)
+ Update();
+
+ VirtualGrid.Render();
+ }
+
+ public void Update()
+ {
+ Grid = VirtualGrid.Grid;
+ ComputeVirtualGrid();
+
+ IsDirty = false;
+ }
+
+ private void ComputeVirtualGrid()
+ {
+ VirtualGrid.Columns = Snapshot.Empires.Select(empire => new Column()
+ {
+ Name = empire.UserName
+ }).ToArray();
+
+ VirtualGrid.Sections = new[]
+ {
+ new Section()
+ {
+ Rows = new []
+ {
+ new Row() { Cells = Snapshot.Empires.Select(empire => new Cell()
+ {
+ Text = (empire.Index == Snapshot.LocalEmpireIndex) ?
+ "A C T I V E" : " ",
+ Style = Styles.CenteredStaticRowStyle
+ }), Style = Styles.StaticRowStyle },
+ new Row() { Cells = Snapshot.Empires.Select(empire => new TintableCell()
+ {
+ Text = "" + empire.UserName + "",
+ BackgroundColor = empire.Color,
+ Color = empire.SecondaryColor
+ }), Style = Styles.StaticRowStyle }
+ },
+ SpaceBefore = 0
+ },
+ new Section()
+ {
+ SpaceBefore = 4f,
+ Rows = new[]
+ {
+ new Row() { Title = "TERRITORIES, CITIES / MAX",
+ Cells = Snapshot.Empires.Select(e => new CellGroup() { Cells = new ICell[] {
+ new Cell() { Text = e.TerritoryCount, Span = Grid.CellSpan1},
+ new Cell() { Text = e.CityCount + " / " + e.CityCap, Span = Grid.CellSpan3},
+ }})},
+ new Row() { Title = "STABILITY",
+ Cells = Snapshot.Empires.Select(e => new CompositeCell() { Elements = new IElement[] {
+ new TextElement() { Text = e.Stability },
+ new ImageElement() { Image = Utils.StabilityTexture },
+ }})},
+ new Row() { Title = "ERA LEVEL, SUM OF ERA STARS",
+ Cells = Snapshot.Empires.Select(e => new CellGroup() { Cells = new ICell[] {
+ new Cell() { Text = e.EraLevel, Span = Grid.CellSpan1},
+ new Cell() { Text = e.SumOfEraStars, Span = Grid.CellSpan3},
+ }})},
+ new Row() { Title = "CITIZENS, EMPIRE POPULATION",
+ Cells = Snapshot.Empires.Select(e => new CellGroup() { Cells = new ICell[] {
+ new Cell() { Text = e.SettlementsPopulation, Span = Grid.CellSpan2},
+ new Cell() { Text = e.EmpirePopulation, Span = Grid.CellSpan2},
+ }})},
+ new Row() { Title = "POLLUTION",
+ Cells = Snapshot.Empires.Select(e => new CellGroup() { Cells = new ICell[] {
+ new Cell() { Text = e.PollutionStock, Span = Grid.CellSpan2},
+ new Cell() { Text = (int.Parse(e.PollutionNet) >= 0 ? "+" : "") +
+ e.PollutionNet + " " + PerTurn, Span = Grid.CellSpan2},
+ }})}
+ }
+ }
+ };
+
+
+ }
+
+ private void Trigger(Action action)
+ {
+ // some actions tracking stuff here
+ action.Invoke();
+ // Trigger update
+ GameStatsWindow.ResetLoop();
+ }
+
+ private void OnAdd5kMoney(int empireIndex) =>
+ Trigger(() => HumankindGame.Empires[empireIndex].MoneyStock += 5000);
+
+ private Row QuickTextRow(string title, Func builder) =>
+ new Row()
+ {
+ Title = title,
+ Cells = Snapshot.Empires.Select(empire => new Cell()
+ {
+ Text = builder.Invoke(empire)
+ })
+ };
+ }
+}
\ No newline at end of file
diff --git a/UI/Statistics/GameStatisticsGrid.cs b/UI/Statistics/GameStatisticsGrid.cs
deleted file mode 100644
index 85edf33..0000000
--- a/UI/Statistics/GameStatisticsGrid.cs
+++ /dev/null
@@ -1,343 +0,0 @@
-using System;
-using System.Linq;
-using UnityEngine;
-using Modding.Humankind.DevTools;
-using Modding.Humankind.DevTools.DeveloperTools.UI;
-using Amplitude.Mercury.Interop;
-using Amplitude.Mercury.Sandbox;
-using Amplitude.Framework;
-using Amplitude.Framework.Networking;
-using Amplitude.UI;
-
-namespace DevTools.Humankind.GUITools.UI
-{
- public class GameStatisticsGrid : DrawableGrid
- {
-
- public GameStatsSnapshot CurrentSnapshot;
- public int[] DisplayOrder { get; set; } = null;
-
- public float SpaceEmpireColumsBy = 4f;
-
- public Color CellTintColor = new Color(0.9f, 0.9f, 0.85f, 1f);
- // public Color CellTintColorAlt = new Color(1f, 1f, 1f, 0.35f);
- public Color CellTintColorAlt = new Color(0.6f, 0.6f, 0.6f, 1f);
- public Color IconTintColor = new Color(1f, 1f, 1f, 0.7f);
- public Color CellButtonTintColor = new Color32(85, 136, 254, 230);
-
- // public const string SpiralCharacter = "\u0489";
- // public const string SpiralCharacter = "\u2314";
- // public const string TurnCharacter = "Ⓣ";
- public const string PerTurn = "/ TURN";
- public const string ReturnCharacter = "⏎";
- //public const string SpiralCharacter = "⌀";
-
- private int CurrentIndex;
- private int CurrentEmpireIndex;
-
- public void SetSnapshot(GameStatsSnapshot snapshot)
- {
- CurrentSnapshot = snapshot;
- if (DisplayOrder == null || DisplayOrder.Length != snapshot.Empires.Length)
- DisplayOrder = snapshot.Empires.Select((e, i) => i).ToArray();
- }
-
- public void DrawCommonHeader()
- {
- Row(StaticRowStyle);
- RowHeader(" ", CellSpan6);
-
- RowHeader("TURN", CellSpan1);
- DrawCell(CurrentSnapshot.Turn.ToString(), CellSpan1);
-
- RowHeader("ATMOSPHERE POLLUTION", CellSpan5);
- DrawCell("LEVEL " + CurrentSnapshot.AtmospherePollutionLevel + "", CellSpan2);
- DrawCell("" +
- "" + CurrentSnapshot.AtmospherePollutionStock + "" +
- (CurrentSnapshot.AtmospherePollutionNet >= 0 ? " ( +" : " ( ") +
- CurrentSnapshot.AtmospherePollutionNet + " " + PerTurn + " )",
- CellSpan4);
- CellButton("-2K", () =>
- {
- SandboxManager.PostOrder((Order)new EditorOrderAddOrRemoveAtmospherePollution()
- {
- Delta = -2000
- }, (int)Snapshots.GameSnapshot.PresentationData.LocalEmpireInfo.EmpireIndex);
- }, CellSpan1);
- CellButton("-250", () =>
- {
- SandboxManager.PostOrder((Order)new EditorOrderAddOrRemoveAtmospherePollution()
- {
- Delta = -250
- }, (int)Snapshots.GameSnapshot.PresentationData.LocalEmpireInfo.EmpireIndex);
- }, CellSpan1);
- CellButton("+250", () =>
- {
- SandboxManager.PostOrder((Order)new EditorOrderAddOrRemoveAtmospherePollution()
- {
- Delta = 250
- }, (int)Snapshots.GameSnapshot.PresentationData.LocalEmpireInfo.EmpireIndex);
- }, CellSpan1);
- CellButton("+2K", () =>
- {
- SandboxManager.PostOrder((Order)new EditorOrderAddOrRemoveAtmospherePollution()
- {
- Delta = 2000
- }, (int)Snapshots.GameSnapshot.PresentationData.LocalEmpireInfo.EmpireIndex);
- }, CellSpan1);
-
- EndRow();
- }
-
- public void Draw()
- {
- DrawRow(" ", StaticRowStyle, (empire, index, empireIndex) =>
- {
- var headerText = empireIndex == CurrentSnapshot.LocalEmpireIndex ?
- "A C T I V E" : " ";
- DrawCell(headerText, CenteredStaticRowStyle, Color.white, CellSpan4);
- });
- DrawRow(" ", StaticRowStyle, (empire, index, empireIndex) =>
- {
- GUI.backgroundColor = empire.Color;
- DrawCell("" + empire.UserName + "", ColorableCellStyle, empire.Color, CellSpan4);
- GUI.backgroundColor = Color.white;
- });
-
- Space(4f);
-
- DrawRow("TERRITORIES, CITIES / MAX", empire =>
- DrawCell(empire.TerritoryCount, CellSpan1)
- .DrawCell(empire.CityCount + " / " + empire.CityCap, CellSpan3));
- DrawRow("STABILITY", empire => DrawCompositeCell(empire.Stability + " ", Utils.StabilityTexture, null, CellSpan4));
- DrawRow("ERA LEVEL, SUM OF ERA STARS", empire =>
- DrawCell(empire.EraLevel, CellSpan1)
- .DrawCell(empire.SumOfEraStars, CellSpan3));
- DrawRow("CITIZENS, EMPIRE POPULATION", empire =>
- DrawCell(empire.SettlementsPopulation, CellSpan2)
- .DrawCell(empire.EmpirePopulation, CellSpan2));
- DrawRow("POLLUTION", empire =>
- DrawCell("" + empire.PollutionStock, CellSpan2)
- .DrawCell((int.Parse(empire.PollutionNet) >= 0 ? "+" : "") +
- empire.PollutionNet + " " + PerTurn, CellSpan2));
-
- DrawSection("MILITARY STATS");
- DrawRow("COMBAT STRENGTH", empire => DrawCell(empire.CombatStrength, CellSpan4));
- DrawRow("ARMIES, TOTAL UNITS", empire =>
- DrawCell(empire.ArmyCount, CellSpan2)
- .DrawCell(empire.UnitCount, CellSpan2));
- DrawRow("MILITARY UPKEEP", empire => DrawCompositeCell(empire.MilitaryUpkeep + " ", Utils.MoneyTexture, PerTurn, CellSpan4));
-
- DrawSection("RESEARCH STATS");
- DrawRow("SCIENCE", empire => DrawCompositeCell("+" + empire.ResearchNet + " ", Utils.ScienceTexture, PerTurn, CellSpan3)
- .CellButton("+5K", (e, i, empireIndex) =>
- {
- HumankindGame.Empires[empireIndex].ResearchStock = 5000;
- }, CellSpan1));
- DrawRow("AVAILABLE, UNLOCKED", empire =>
- DrawCell(empire.AvailableTechnologiesCount, CellSpan2)
- .DrawCell(empire.UnlockedTechnologiesCount, CellSpan2));
- DrawRow("TECHNOLOGICAL ERA OFFSET", empire => DrawCell(empire.TechnologicalEraOffset, CellSpan4));
-
- DrawSection("ECONOMIC STATS");
- DrawRow("MONEY", empire => DrawCompositeCell(empire.MoneyNet + " ", Utils.MoneyTexture, PerTurn, CellSpan4));
- DrawRow("MONEY STOCK", empire => DrawCompositeCell(empire.MoneyStock + " ", Utils.MoneyTexture, null, CellSpan2)
- .CellButton("-500", (e, i, empireIndex) =>
- {
- HumankindGame.Empires[empireIndex].MoneyStock -= 500;
- }, CellSpan1)
- .CellButton("+5K", (e, i, empireIndex) =>
- {
- HumankindGame.Empires[empireIndex].MoneyStock += 5000;
- }, CellSpan1));
- DrawRow("INFLUENCE", empire => DrawCompositeCell("+" + empire.InfluenceNet + " ", Utils.InfluenceTexture, PerTurn, CellSpan4));
- DrawRow("INFLUENCE STOCK", empire => DrawCompositeCell(empire.InfluenceStock + " ", Utils.InfluenceTexture, null, CellSpan2)
- .CellButton("-75", (e, i, empireIndex) =>
- {
- HumankindGame.Empires[empireIndex].InfluenceStock -= 75;
- }, CellSpan1)
- .CellButton("+250", (e, i, empireIndex) =>
- {
- HumankindGame.Empires[empireIndex].InfluenceStock += 250;
- }, CellSpan1));
- DrawRow("TOTAL TRADE NODES", empire => DrawCell(empire.TradeNodesCount, CellSpan4));
- DrawRow("LUXURY, STRATEGIC ACCESS COUNT", empire =>
- DrawCell(empire.LuxuryResourcesAccessCount, CellSpan2)
- .DrawCell(empire.StrategicResourcesAccessCount, CellSpan2));
-
- Space(4f);
- DrawRow(" ", StaticRowStyle, (empire, index, empireIndex) =>
- {
- GUI.enabled = (empireIndex != CurrentSnapshot.LocalEmpireIndex);
- CellButton("SWITCH EMPIRE", (e, i, eIndex) =>
- {
- try
- {
- Services.GetService()?.CreateMessageSender().SendLocalMessage(
- (LocalMessage) new SandboxControlMessage(
- (ISandboxControlInstruction) new ChangeLocalEmpireInstruction(eIndex)
- )
- );
- HumankindGame.Empires.Where(emp => emp.EmpireIndex == eIndex).Settlements().IsCapital().First()
- .CenterToCamera();
- }
- catch (Exception)
- {
- HumankindGame.Empires.Where(emp => emp.EmpireIndex == eIndex).Armies().First().CenterToCamera();
- }
- }, CellSpan4);
- GUI.enabled = true;
- });
-
- }
-
- public void CellButton(string text, Action action, params GUILayoutOption[] options)
- {
- var prevBgTint = GUI.backgroundColor;
- // GUI.backgroundColor = CellButtonTintColor;
- GUI.backgroundColor = Color.white;
- if (GUILayout.Button(text, CellButtonStyle, options))
- {
- action.Invoke();
- HumankindGame.Update();
- // CurrentSnapshot.Snapshot();
- GameStatsWindow.ResetLoop();
- }
- GUI.backgroundColor = prevBgTint;
- }
-
- public GameStatisticsGrid DrawSection(string title)
- {
- return (GameStatisticsGrid)this
- .Space(16f)
- .Row(StaticRowStyle)
- .VerticalStack()
- .RowHeader(title, CellSpan6)
- .DrawHorizontalLine(0.5f, CellWidth * 6)
- .EndVerticalStack()
- .EndRow();
- }
-
- public GameStatisticsGrid DrawColumnHeader(string title)
- {
- // TODO:
- return (GameStatisticsGrid)this
- .Space(16f)
- .Row(StaticRowStyle)
- .VerticalStack()
- .RowHeader(title, CellSpan6)
- .DrawHorizontalLine(0.5f, CellWidth * 6)
- .EndVerticalStack()
- .EndRow();
- }
-
- public GameStatisticsGrid DrawRow(string title, GUIStyle style, Action action)
- {
- return (GameStatisticsGrid)this
- .Row(style)
- .RowHeader(title, CellSpan6)
- .Iterate(action)
- .EndRow();
- }
-
- public GameStatisticsGrid DrawRow(string title, Action action)
- {
- return (GameStatisticsGrid)this
- .Row()
- .RowHeader(title, CellSpan6)
- .Iterate(action)
- .EndRow();
- }
-
- public GameStatisticsGrid DrawRow(string title, Action action)
- {
- return (GameStatisticsGrid)this
- .Row()
- .RowHeader(title, CellSpan6)
- .Iterate(action)
- .EndRow();
- }
-
- public GameStatisticsGrid DrawCell(string text, params GUILayoutOption[] options)
- {
- return (GameStatisticsGrid)this
- .Cell("" + text + "", CurrentIndex % 2 != 0 ? CellTintColorAlt : CellTintColor, options);
- }
-
- public GameStatisticsGrid DrawCell(string text, GUIStyle style, Color tintColor, params GUILayoutOption[] options)
- {
- return (GameStatisticsGrid)this
- .Cell("" + text + "", style, tintColor, options);
- }
-
-
- public GameStatisticsGrid DrawCompositeCell(string text, Texture image, string rest = null, params GUILayoutOption[] options)
- {
- var prevTint = GUI.backgroundColor;
- GUI.backgroundColor = CurrentIndex % 2 != 0 ? CellTintColorAlt : CellTintColor;
-
- GUILayout.BeginHorizontal(CellStyle, options);
- GUILayout.FlexibleSpace();
- GUILayout.Label("" + text + "", InlineCellContentStyle);
- GUI.DrawTexture(GUILayoutUtility.GetRect(14f, 14f),
- image, ScaleMode.StretchToFill, true,
- 1f, IconTintColor, 0, 0);
- if (rest != null)
- GUILayout.Label("" + rest + "", InlineCellContentStyle);
- GUILayout.FlexibleSpace();
- GUILayout.EndHorizontal();
-
- GUI.backgroundColor = prevTint;
-
- return this;
- }
-
- public override DrawableGrid Iterate(Action action)
- {
- for (var i = 0; i < DisplayOrder.Length; i++)
- {
- if (SpaceEmpireColumsBy != 0 && i != 0)
- GUILayout.Space(SpaceEmpireColumsBy);
- CurrentIndex = i;
- CurrentEmpireIndex = DisplayOrder[i];
- action.Invoke((EmpireSnapshot)CurrentSnapshot.Empires[DisplayOrder[i]]);
- }
-
- return this;
- }
-
- public override DrawableGrid Iterate(Action action)
- {
- for (var i = 0; i < DisplayOrder.Length; i++)
- {
- if (SpaceEmpireColumsBy != 0 && i != 0)
- GUILayout.Space(SpaceEmpireColumsBy);
- CurrentIndex = i;
- CurrentEmpireIndex = DisplayOrder[i];
- action.Invoke((EmpireSnapshot)CurrentSnapshot.Empires[DisplayOrder[i]], i, CurrentEmpireIndex);
- }
-
- return this;
- }
-
- public override DrawableGrid CellButton(string text, Action action, params GUILayoutOption[] options)
- {
- var empireIndex = CurrentEmpireIndex;
- var index = CurrentIndex;
- var prevBgTint = GUI.backgroundColor;
- // GUI.backgroundColor = CellButtonTintColor;
- GUI.backgroundColor = Color.white;
- if (GUILayout.Button(text, CellButtonStyle, options))
- {
- action.Invoke((EmpireSnapshot)CurrentSnapshot.Empires[empireIndex], index, empireIndex);
- HumankindGame.Update();
- // CurrentSnapshot.Snapshot();
- GameStatsWindow.ResetLoop();
- }
- GUI.backgroundColor = prevBgTint;
-
- return this;
- }
-
- }
-}
diff --git a/UI/Statistics/GameStatsSnapshot.cs b/UI/Statistics/GameStatsSnapshot.cs
index 0cf5716..492d634 100644
--- a/UI/Statistics/GameStatsSnapshot.cs
+++ b/UI/Statistics/GameStatsSnapshot.cs
@@ -1,16 +1,24 @@
-// using System.Drawing;
using System;
using System.Reflection;
using System.Linq;
using Modding.Humankind.DevTools;
using Modding.Humankind.DevTools.Core;
-using Modding.Humankind.DevTools.DeveloperTools.UI;
using UnityEngine;
using Amplitude.Mercury;
using Amplitude.Mercury.Interop;
namespace DevTools.Humankind.GUITools.UI
{
+ public interface IDataType
+ {
+
+ }
+
+ public interface IEmpireSnapshotDataType : IDataType
+ {
+
+ }
+
public class GameStatsSnapshot
{
public int Turn { get; set; }
@@ -62,7 +70,7 @@ public GameStatsSnapshot SetLocalEmpireIndex(int localEmpireIndex)
}
- public class EmpireSnapshot
+ public class EmpireSnapshot : IEmpireSnapshotDataType
{
public string[] Values;
private string primaryColor = "#FFFFFFFF";
@@ -74,6 +82,7 @@ public class EmpireSnapshot
public string SecondaryColor => secondaryColor;
public Color ContrastColor => contrastColor;
public string UserName = string.Empty;
+ public int Index { get; private set; }
public EmpireSnapshot(HumankindEmpire empire)
{
@@ -82,6 +91,7 @@ public EmpireSnapshot(HumankindEmpire empire)
public EmpireSnapshot Snapshot(HumankindEmpire empire)
{
+ Index = empire.EmpireIndex;
Values = EmpireSnapshotUtils.MakeEmpireSnapshotValues(empire);
if (R.Text.NormalizeColor(empire.PrimaryColor) != primaryColor)
diff --git a/UI/Statistics/GameStatsWindow.cs b/UI/Statistics/GameStatsWindow.cs
index 639ddb3..b3f36c9 100644
--- a/UI/Statistics/GameStatsWindow.cs
+++ b/UI/Statistics/GameStatsWindow.cs
@@ -1,16 +1,11 @@
-using System;
-using System.Reflection;
+using System.Linq;
using UnityEngine;
using Modding.Humankind.DevTools;
-using Modding.Humankind.DevTools.Core;
using Modding.Humankind.DevTools.DeveloperTools.UI;
-using UIToolManager = Modding.Humankind.DevTools.DeveloperTools.UI.UIController;
using Amplitude.Mercury.Interop;
-using Amplitude.Mercury.Sandbox;
using Amplitude.Framework;
-using Amplitude.Framework.Networking;
-using Amplitude.UI;
using Amplitude.Mercury.UI;
+using StyledGUI;
namespace DevTools.Humankind.GUITools.UI
{
@@ -30,10 +25,17 @@ public class GameStatsWindow : FloatingToolWindow
private static GameStatsSnapshot Snapshot;
// True when the snapshot current snapshot can be "live" updated or it is a previously saved one.
private static bool isLiveSnapshot;
+
+ private int activeTab = 0;
+ private int previousActiveTab = 0;
- private GameStatisticsGrid grid;
+ private string[] tabNames = {"OVERVIEW", "KEYBOARD SHORTCUTS"};
+
+ public GameGrid GameOverviewGrid { get; set; }
+ public CommonHeadersGrid HeadersGrid { get; set; }
+ public KeyboardShortcutsGrid ShortcutsGrid { get; set; }
- private GUIStyle bgStyle = new GUIStyle(UIToolManager.DefaultSkin.FindStyle("PopupWindow.Sidebar.Highlight")) {
+ private GUIStyle bgStyle = new GUIStyle(UIController.DefaultSkin.FindStyle("PopupWindow.Sidebar.Highlight")) {
normal = new GUIStyleState() {
background = Utils.CreateSinglePixelTexture2D(new Color(0, 0, 0, 0.8f)),
textColor = Color.white
@@ -43,15 +45,21 @@ public class GameStatsWindow : FloatingToolWindow
textColor = Color.white
}
};
+
+ private GUIStyle bgStyleAlt = new GUIStyle(UIController.DefaultSkin.FindStyle("PopupWindow.Sidebar.Highlight")) {
+ normal = new GUIStyleState() {
+ background = Utils.CreateSinglePixelTexture2D(new Color(0.85f, 0.75f, 0f, 0.45f)),
+ textColor = Color.white
+ },
+ hover = new GUIStyleState() {
+ background = null,
+ textColor = Color.white
+ }
+ };
- private GUIStyle backButtonStyle = new GUIStyle(UIToolManager.DefaultSkin.toggle) {
+ private GUIStyle backButtonStyle = new GUIStyle(UIController.DefaultSkin.toggle) {
margin = new RectOffset(1, 1, 1, 1)
};
-
- private GUIStyle CommonHeaderStyle = new GUIStyle(UIToolManager.DefaultSkin.toggle) {
- margin = new RectOffset(1, 1, 1, 1),
- alignment = TextAnchor.LowerRight
- };
private static bool initialized = false;
private static bool isValidSnapshot = false;
@@ -83,10 +91,39 @@ private void Initialize()
localEmpireIndex = (int)Snapshots.GameSnapshot.PresentationData.LocalEmpireInfo.EmpireIndex;
Snapshot = new GameStatsSnapshot();
- grid = new GameStatisticsGrid();
Snapshot.SetLocalEmpireIndex(localEmpireIndex);
+ GameOverviewGrid = new GameGrid()
+ {
+ Snapshot = Snapshot,
+ VirtualGrid = new VirtualGrid()
+ {
+ Grid = new GameOverviewGrid(),
+ Distribution = HumankindGame.Empires.Select((e, i) => i).ToArray()
+ }
+ };
+ HeadersGrid = new CommonHeadersGrid()
+ {
+ Snapshot = Snapshot,
+ VirtualGrid = new VirtualGrid()
+ {
+ Grid = new StaticHeaderGrid(),
+ DrawRowHeaders = false,
+ DrawSectionHeaders = false
+ }
+ };
+ ShortcutsGrid = new KeyboardShortcutsGrid()
+ {
+ VirtualGrid = new VirtualGrid()
+ {
+ Grid = new ShortcutsGrid(),
+ }
+ };
+
+ ShortcutsGrid.VirtualGrid.RowHeaderCellSpan = ShortcutsGrid.VirtualGrid.Grid.CellSpan8;
+ ShortcutsGrid.VirtualGrid.SectionHorizontalLineWidth = ShortcutsGrid.VirtualGrid.Grid.GetCellWidth() * 8;
+
initialized = true;
isValidSnapshot = true;
IsVisibleFullscreen = true;
@@ -105,6 +142,7 @@ private void Initialize()
public override void Close(bool saveVisibilityStateBeforeClosing = false)
{
Unload();
+ HumankindGame.Update();
base.Close(false);
}
@@ -118,7 +156,7 @@ private void Unload()
forceUpdate = false;
if (UIManagerService == null)
- return;
+ return;
UIManagerService.IsUiVisible = true;
UIManagerService.AreTooltipsVisible = true;
}
@@ -150,6 +188,10 @@ public override void OnDrawUI()
Snapshot
.Snapshot()
.SetLocalEmpireIndex(localEmpireIndex);
+
+ GameOverviewGrid.Snapshot = Snapshot;
+ GameOverviewGrid.IsDirty = true;
+ HeadersGrid.IsDirty = true;
}
}
}
@@ -158,45 +200,58 @@ public override void OnDrawUI()
{
GUILayout.BeginVertical();
GUILayout.Space(4f);
- GUILayout.Label(" NOT A VALID SNAPSHOT ");
+ GUILayout.Label(" ");
GUILayout.Space(4f);
GUILayout.EndVertical();
return;
}
- grid.SetSnapshot(Snapshot);
+ GUILayout.BeginVertical(bgStyle, GUILayout.Width(Screen.width), GUILayout.Height(Screen.height));
+ DrawCommonContent();
+
BeginBackgroundScrollView();
{
- GUILayout.BeginHorizontal(GUILayout.Width(Screen.width), GUILayout.Height(Screen.height));
+ GUILayout.BeginHorizontal();
{
+ GUILayout.Space(60f);
GUILayout.FlexibleSpace();
GUILayout.BeginVertical();
{
- GUILayout.Space(24f);
- DrawCommonContent();
- GUILayout.Space(72f);
- GUILayout.FlexibleSpace();
- DrawWindowContent();
- // GUILayout.Space(16f);
- // DrawWindowContent();
+ GUILayout.Space(85f);
+
+ if (activeTab == 0)
+ {
+ GameOverviewGrid.Render();
+ }
+ else if (activeTab == 1)
+ {
+ if (previousActiveTab != 1)
+ ShortcutsGrid.ResyncKeyMappings();
+
+ ShortcutsGrid.Render();
+ }
+ GUILayout.Space(80f);
+
GUILayout.FlexibleSpace();
- GUILayout.Space(72f);
}
GUILayout.EndVertical();
GUILayout.FlexibleSpace();
+ GUILayout.Space(60f);
}
GUILayout.EndHorizontal();
}
GUILayout.EndScrollView();
DrawBackButton();
+
+ GUILayout.EndVertical();
}
private void BeginBackgroundScrollView()
@@ -207,37 +262,77 @@ private void BeginBackgroundScrollView()
false,
"horizontalscrollbar",
"verticalscrollbar",
- bgStyle,
- // "scrollview",
- GUILayout.Height(Screen.height));
+ "scrollview",
+ GUILayout.ExpandHeight(true));
}
- private void DrawCommonContent()
- {
- GUILayout.BeginHorizontal();
- grid.DrawCommonHeader();
- GUILayout.EndHorizontal();
- }
+
- private void DrawWindowContent()
+ private GUIStyle TabButtonStyle = new GUIStyle(UIController.DefaultSkin.FindStyle("TabButton")) {
+ fixedHeight = 28f,
+ fontSize = 14,
+ fontStyle = FontStyle.Bold,
+ padding = new RectOffset(22, 22, 0, 5),
+ normal = new GUIStyleState() {
+ background = Utils.CreateSinglePixelTexture2D(new Color(0.85f, 0.75f, 0f, 0.45f)),
+ textColor = Color.white
+ },
+ onNormal = new GUIStyleState()
+ {
+ background = Utils.TransparentTexture,
+ textColor = new Color32(85, 136, 254, 255)
+ },
+ onHover = new GUIStyleState()
+ {
+ background = null,
+ textColor = Color.white
+ },
+ onActive = new GUIStyleState()
+ {
+ background = null,
+ textColor = Color.white
+ },
+ active = new GUIStyleState()
+ {
+ background = Utils.TransparentTexture,
+ textColor = new Color32(85, 136, 254, 255)
+ },
+ hover = new GUIStyleState()
+ {
+ background = Utils.CreateSinglePixelTexture2D(new Color32(85, 136, 254, 155)),
+ textColor = Color.white
+ }
+ };
+
+ private void DrawCommonContent()
{
+ GUILayout.BeginHorizontal(bgStyleAlt);
+ GUILayout.Space(271f);
GUILayout.BeginVertical();
- GUILayout.Space(4f);
-
- grid.Draw();
-
- GUILayout.Space(4f);
+ GUILayout.Space(26f);
+ HeadersGrid.Render();
+ GUILayout.Space(22f);
GUILayout.EndVertical();
+ GUILayout.EndHorizontal();
+ GUILayout.BeginHorizontal();
+ GUILayout.BeginHorizontal(bgStyleAlt, GUILayout.Height(28f));
+ GUILayout.Space(395f);
+ GUILayout.EndHorizontal();
+ previousActiveTab = activeTab;
+ activeTab = GUILayout.Toolbar(activeTab, tabNames, TabButtonStyle, GUI.ToolbarButtonSize.FitToContents);
+ GUILayout.BeginHorizontal(bgStyleAlt, GUILayout.Height(28f));
+ GUILayout.FlexibleSpace();
+ GUILayout.EndHorizontal();
+ GUILayout.EndHorizontal();
}
private void DrawBackButton()
{
GUI.backgroundColor = Color.white;
- if (GUI.Button(new Rect(24f, 24f, 223f, 38f), "BACK TO THE GAME", backButtonStyle))
+ if (GUI.Button(new Rect(26f, 26f, 223f, 45f), "BACK TO THE GAME", backButtonStyle))
{
MainTools.ToggleGameOverviewWindow();
}
- // GUILayout.Label("HELLO WORLD!");
GUI.backgroundColor = Color.white;
}
}