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; } }