diff --git a/.github/ISSUE_TEMPLATE/error-while-loading-mods.md b/.github/ISSUE_TEMPLATE/error-while-loading-mods.md index 6e4a68fe..bfe22f65 100644 --- a/.github/ISSUE_TEMPLATE/error-while-loading-mods.md +++ b/.github/ISSUE_TEMPLATE/error-while-loading-mods.md @@ -8,6 +8,8 @@ assignees: '' --- - Be sure that you are using the latest version of YAFC +- Try to remove outdated and disabled mods from your mod folder. If that helps, you may still make a report but you need to attach the whole contents of your mod folder, ioncluding all outdated and disabled mods. - Please note that YAFC is my personal project and I can't promise any support! -- Specify the YAFC version +- Specify the YAFC version and Factorio version +- While YAFC should work with mods down to Factorio 0.17 (and maybe even earlier), I actively support only latest stable and latest experimental versions. - Attach a new game save file so I can sync mods to yours. diff --git a/YAFC/Utils/Preferences.cs b/YAFC/Utils/Preferences.cs index ec737475..777313c0 100644 --- a/YAFC/Utils/Preferences.cs +++ b/YAFC/Utils/Preferences.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.InteropServices; diff --git a/YAFC/Widgets/PseudoScreen.cs b/YAFC/Widgets/PseudoScreen.cs index 4626f592..c1d10f6a 100644 --- a/YAFC/Widgets/PseudoScreen.cs +++ b/YAFC/Widgets/PseudoScreen.cs @@ -70,15 +70,16 @@ protected virtual void Save() {} public void Rebuild() => contents.Rebuild(); - public virtual void KeyDown(SDL.SDL_Keysym key) + public virtual bool KeyDown(SDL.SDL_Keysym key) { if (key.scancode == SDL.SDL_Scancode.SDL_SCANCODE_ESCAPE) Close(false); + return true; } - public virtual void TextInput(string input) {} + public virtual bool TextInput(string input) => true; - public virtual void KeyUp(SDL.SDL_Keysym key) {} + public virtual bool KeyUp(SDL.SDL_Keysym key) => true; public virtual void FocusChanged(bool focused) {} } diff --git a/YAFC/Windows/DependencyExplorer.cs b/YAFC/Windows/DependencyExplorer.cs index cfceacbd..105eaa79 100644 --- a/YAFC/Windows/DependencyExplorer.cs +++ b/YAFC/Windows/DependencyExplorer.cs @@ -182,15 +182,16 @@ public void Change(FactorioObject target) Rebuild(); } - public override void KeyDown(SDL.SDL_Keysym key) + public override bool KeyDown(SDL.SDL_Keysym key) { if (key.scancode == SDL.SDL_Scancode.SDL_SCANCODE_BACKSPACE && history.Count > 0) { var last = history[history.Count - 1]; Change(last); history.RemoveRange(history.Count-2, 2); + return true; } - base.KeyDown(key); + return base.KeyDown(key); } } } \ No newline at end of file diff --git a/YAFC/Windows/MainScreen.cs b/YAFC/Windows/MainScreen.cs index dd1908b7..f779b1f4 100644 --- a/YAFC/Windows/MainScreen.cs +++ b/YAFC/Windows/MainScreen.cs @@ -460,7 +460,7 @@ public void ClosePseudoScreen(PseudoScreen screen) rootGui.Rebuild(); } - public void KeyDown(SDL.SDL_Keysym key) + public bool KeyDown(SDL.SDL_Keysym key) { var ctrl = (key.mod & SDL.SDL_Keymod.KMOD_CTRL) != 0; if (ctrl) @@ -486,6 +486,7 @@ public void KeyDown(SDL.SDL_Keysym key) if (key.scancode == SDL.SDL_Scancode.SDL_SCANCODE_ESCAPE && pageSearch.query != null) SetSearch(default); + return true; } private async Task SaveProjectAs() @@ -546,8 +547,8 @@ private async void LoadProjectHeavy() Close(); } - public void TextInput(string input) {} - public void KeyUp(SDL.SDL_Keysym key) {} + public bool TextInput(string input) => true; + public bool KeyUp(SDL.SDL_Keysym key) => true; public void FocusChanged(bool focused) {} private class FadeDrawer : IRenderable diff --git a/YAFC/Windows/SelectObjectPanel.cs b/YAFC/Windows/SelectObjectPanel.cs index 60f708d0..9dd6d035 100644 --- a/YAFC/Windows/SelectObjectPanel.cs +++ b/YAFC/Windows/SelectObjectPanel.cs @@ -75,10 +75,10 @@ public override void Build(ImGui gui) list.Build(gui); } - public override void KeyDown(SDL.SDL_Keysym key) + public override bool KeyDown(SDL.SDL_Keysym key) { contents.SetTextInputFocus(searchBox, list.filter.query); - base.KeyDown(key); + return base.KeyDown(key); } } } \ No newline at end of file diff --git a/YAFC/Workspace/AutoPlannerView.cs b/YAFC/Workspace/AutoPlannerView.cs index ebc37e4f..a803266c 100644 --- a/YAFC/Workspace/AutoPlannerView.cs +++ b/YAFC/Workspace/AutoPlannerView.cs @@ -108,11 +108,11 @@ protected override void BuildContent(ImGui gui) public override void CreateModelDropdown(ImGui gui, Type type, Project project, ref bool close) { - /*if (gui.BuildContextMenuButton("Auto planner (Alpha)")) + if (gui.BuildContextMenuButton("Auto planner (Alpha)")) { close = true; WizardPanel.Show("New auto planner", CreateAutoPlannerWizard); - }*/ + } } } } \ No newline at end of file diff --git a/YAFC/Workspace/ProductionTable/ProductionTableView.cs b/YAFC/Workspace/ProductionTable/ProductionTableView.cs index 794a57c3..c6d28600 100644 --- a/YAFC/Workspace/ProductionTable/ProductionTableView.cs +++ b/YAFC/Workspace/ProductionTable/ProductionTableView.cs @@ -21,9 +21,9 @@ public ProductionTableView() new DataColumn("", BuildRecipePad, null, 3f), new DataColumn("Recipe", BuildRecipeName, BuildRecipeMenu, 13f, 16f, 30f), new DataColumn("Entity", BuildRecipeEntity, BuildEntityMenu, 8f), - new DataColumn("Ingredients", BuildRecipeIngredients, null, 32f, 16f, 40f), - new DataColumn("Products", BuildRecipeProducts, null, 12f, 10f, 31f), - new DataColumn("Modules", BuildRecipeModules, BuildModulesMenu, 7f), + new DataColumn("Ingredients", BuildRecipeIngredients, null, 32f, 16f, 100f), + new DataColumn("Products", BuildRecipeProducts, null, 12f, 10f, 70f), + new DataColumn("Modules", BuildRecipeModules, BuildModulesMenu, 7f, 7f, 13f), }; var grid = new DataGrid(columns); flatHierarchyBuilder = new ProductionTableFlatHierarchy(grid, BuildSummary); diff --git a/YAFC/Workspace/ProjectPageView.cs b/YAFC/Workspace/ProjectPageView.cs index 7d4804e6..b68f2f20 100644 --- a/YAFC/Workspace/ProjectPageView.cs +++ b/YAFC/Workspace/ProjectPageView.cs @@ -44,12 +44,12 @@ public void Build(ImGui gui, Vector2 visibleSize) { gui.spacing = 0f; var position = gui.AllocateRect(0f, 0f, 0f).Position; - var headerSize = headerContent.CalculateState(visibleSize.X-0.5f, gui.pixelsPerUnit); + var headerSize = headerContent.CalculateState(visibleSize.X-ScrollbarSize, gui.pixelsPerUnit); contentWidth = headerSize.X; headerHeight = headerSize.Y; var headerRect = gui.AllocateRect(visibleSize.X, headerHeight); position.Y += headerHeight; - var contentSize = bodyContent.CalculateState(visibleSize.X-0.5f, gui.pixelsPerUnit); + var contentSize = bodyContent.CalculateState(visibleSize.X-ScrollbarSize, gui.pixelsPerUnit); if (contentSize.X > contentWidth) contentWidth = contentSize.X; contentHeight = contentSize.Y; @@ -93,6 +93,7 @@ public override void SetModel(ProjectPage page) { if (model != null) projectPage.contentChanged -= Rebuild; + InputSystem.Instance.SetKeyboardFocus(this); projectPage = page; model = page?.content as T; if (model != null) diff --git a/YAFCui/Core/InputSystem.cs b/YAFCui/Core/InputSystem.cs index 4daea0db..e67335f8 100644 --- a/YAFCui/Core/InputSystem.cs +++ b/YAFCui/Core/InputSystem.cs @@ -8,9 +8,9 @@ namespace YAFC.UI { public interface IKeyboardFocus { - void KeyDown(SDL.SDL_Keysym key); - void TextInput(string input); - void KeyUp(SDL.SDL_Keysym key); + bool KeyDown(SDL.SDL_Keysym key); + bool TextInput(string input); + bool KeyUp(SDL.SDL_Keysym key); void FocusChanged(bool focused); } @@ -77,18 +77,21 @@ public void SetDefaultKeyboardFocus(IKeyboardFocus focus) internal void KeyDown(SDL.SDL_Keysym key) { keyMod = key.mod; - (activeKeyboardFocus ?? defaultKeyboardFocus)?.KeyDown(key); + if (activeKeyboardFocus == null || !activeKeyboardFocus.KeyDown(key)) + defaultKeyboardFocus?.KeyDown(key); } internal void KeyUp(SDL.SDL_Keysym key) { keyMod = key.mod; - (activeKeyboardFocus ?? defaultKeyboardFocus)?.KeyUp(key); + if (activeKeyboardFocus == null || !activeKeyboardFocus.KeyUp(key)) + defaultKeyboardFocus?.KeyUp(key); } internal void TextInput(string input) { - (activeKeyboardFocus ?? defaultKeyboardFocus)?.TextInput(input); + if (activeKeyboardFocus == null || !activeKeyboardFocus.TextInput(input)) + defaultKeyboardFocus?.TextInput(input); } internal void MouseScroll(int delta) diff --git a/YAFCui/Core/Window.cs b/YAFCui/Core/Window.cs index c92aa282..20e824bb 100644 --- a/YAFCui/Core/Window.cs +++ b/YAFCui/Core/Window.cs @@ -51,10 +51,10 @@ internal int CalculateUnitsToPixels(int display) { SDL.SDL_GetDisplayDPI(display, out var dpi, out _, out _); SDL.SDL_GetDisplayBounds(display, out var rect); - // 80x60 is the minimum screen size in units, plus some for borders + // 82x60 is the minimum screen size in units, plus some for borders var desiredUnitsToPixels = dpi == 0 ? 13 : MathUtils.Round(dpi / 6.8f); - if (desiredUnitsToPixels * 80f >= rect.w) - desiredUnitsToPixels = MathUtils.Floor(rect.w / 80f); + if (desiredUnitsToPixels * 82f >= rect.w) + desiredUnitsToPixels = MathUtils.Floor(rect.w / 82f); if (desiredUnitsToPixels * 65f >= rect.h) desiredUnitsToPixels = MathUtils.Floor(rect.h / 65f); return desiredUnitsToPixels; diff --git a/YAFCui/Core/WindowMain.cs b/YAFCui/Core/WindowMain.cs index b6c1e47d..e3cfc47e 100644 --- a/YAFCui/Core/WindowMain.cs +++ b/YAFCui/Core/WindowMain.cs @@ -15,7 +15,7 @@ protected void Create(string title, int display) if (visible) return; pixelsPerUnit = CalculateUnitsToPixels(display); - var minwidth = MathUtils.Round(80f * pixelsPerUnit); + var minwidth = MathUtils.Round(82f * pixelsPerUnit); var minheight = MathUtils.Round(60f * pixelsPerUnit); window = SDL.SDL_CreateWindow(title, SDL.SDL_WINDOWPOS_CENTERED_DISPLAY(display), diff --git a/YAFCui/ImGui/ImGuiTextInputHelper.cs b/YAFCui/ImGui/ImGuiTextInputHelper.cs index 9fb2042f..66be835e 100644 --- a/YAFCui/ImGui/ImGuiTextInputHelper.cs +++ b/YAFCui/ImGui/ImGuiTextInputHelper.cs @@ -222,7 +222,7 @@ private void AddEditHistory(EditHistoryEvent evt) } } - public void KeyDown(SDL.SDL_Keysym key) + public bool KeyDown(SDL.SDL_Keysym key) { var ctrl = (key.mod & SDL.SDL_Keymod.KMOD_CTRL) != 0; var shift = (key.mod & SDL.SDL_Keymod.KMOD_SHIFT) != 0; @@ -303,9 +303,11 @@ public void KeyDown(SDL.SDL_Keysym key) SetCaret(text.Length, 0); break; } + + return true; } - public void TextInput(string input) + public bool TextInput(string input) { if (input.IndexOf(' ') >= 0) lastEvent = EditHistoryEvent.None; @@ -315,9 +317,10 @@ public void TextInput(string input) text = text.Insert(caret, input); SetCaret(caret + input.Length); ResetCaret(); + return true; } - public void KeyUp(SDL.SDL_Keysym key) {} + public bool KeyUp(SDL.SDL_Keysym key) => true; public void FocusChanged(bool focused) { diff --git a/YAFCui/ImGui/ScrollArea.cs b/YAFCui/ImGui/ScrollArea.cs index 42df542a..6e8e939c 100644 --- a/YAFCui/ImGui/ScrollArea.cs +++ b/YAFCui/ImGui/ScrollArea.cs @@ -5,14 +5,16 @@ namespace YAFC.UI { - public abstract class Scrollable + public abstract class Scrollable : IKeyboardFocus { private readonly bool vertical, horizontal, collapsible; private Vector2 contentSize; private Vector2 maxScroll; private Vector2 _scroll; + private float height; private ImGui gui; + public const float ScrollbarSize = 1f; protected Scrollable(bool vertical, bool horizontal, bool collapsible) { @@ -26,10 +28,11 @@ protected Scrollable(bool vertical, bool horizontal, bool collapsible) public void Build(ImGui gui, float height) { this.gui = gui; + this.height = height; var rect = gui.statePosition; var width = rect.Width; if (vertical) - width -= 0.5f; + width -= ScrollbarSize; if (gui.isBuilding) { var innerRect = rect; @@ -40,7 +43,7 @@ public void Build(ImGui gui, float height) innerRect.Height = rect.Height = realHeight; if (horizontal && maxScroll.X > 0) { - realHeight -= 0.5f; + realHeight -= ScrollbarSize; innerRect.Height = realHeight; } gui.EncapsulateRect(rect); @@ -51,13 +54,16 @@ public void Build(ImGui gui, float height) { var realHeight = collapsible ? MathF.Min(contentSize.Y, height) : height; if (horizontal && maxScroll.X > 0) - realHeight -= 0.5f; + realHeight -= ScrollbarSize; rect.Height = realHeight; gui.EncapsulateRect(rect); } var size = new Vector2(width, height); var scrollSize = (size * size) / (size + maxScroll); + scrollSize = Vector2.Max(scrollSize, Vector2.One); var scrollStart = (_scroll / maxScroll) * (size - scrollSize); + if ((gui.action == ImGuiAction.MouseDown || gui.action == ImGuiAction.MouseScroll) && rect.Contains(gui.mousePosition)) + InputSystem.Instance.SetKeyboardFocus(this); if (gui.action == ImGuiAction.MouseScroll) { if (gui.ConsumeEvent(rect)) @@ -71,15 +77,15 @@ public void Build(ImGui gui, float height) { if (horizontal && maxScroll.X > 0f) { - var fullScrollRect = new Rect(rect.X, rect.Bottom-0.5f, rect.Width, 0.5f); - var scrollRect = new Rect(rect.X + scrollStart.X, fullScrollRect.Y, scrollSize.X, 0.5f); + var fullScrollRect = new Rect(rect.X, rect.Bottom-ScrollbarSize, rect.Width, ScrollbarSize); + var scrollRect = new Rect(rect.X + scrollStart.X, fullScrollRect.Y, scrollSize.X, ScrollbarSize); BuildScrollBar(gui, 0, in fullScrollRect, in scrollRect); } if (vertical && maxScroll.Y > 0f) { - var fullScrollRect = new Rect(rect.Right-0.5f, rect.Y, 0.5f, rect.Height); - var scrollRect = new Rect(fullScrollRect.X, rect.Y + scrollStart.Y, 0.5f, scrollSize.Y); + var fullScrollRect = new Rect(rect.Right-ScrollbarSize, rect.Y, ScrollbarSize, rect.Height); + var scrollRect = new Rect(fullScrollRect.X, rect.Y + scrollStart.Y, ScrollbarSize, scrollSize.Y); BuildScrollBar(gui, 1, in fullScrollRect, in scrollRect); } } @@ -134,6 +140,42 @@ public float scrollX } protected abstract Vector2 MeasureContent(Rect rect, ImGui gui); + public bool KeyDown(SDL.SDL_Keysym key) + { + switch (key.scancode) + { + case SDL.SDL_Scancode.SDL_SCANCODE_UP: + scroll -= 3; + return true; + case SDL.SDL_Scancode.SDL_SCANCODE_DOWN: + scroll += 3; + return true; + case SDL.SDL_Scancode.SDL_SCANCODE_LEFT: + scrollX -= 3; + return true; + case SDL.SDL_Scancode.SDL_SCANCODE_RIGHT: + scrollX += 3; + return true; + case SDL.SDL_Scancode.SDL_SCANCODE_PAGEDOWN: + scroll += height; + return true; + case SDL.SDL_Scancode.SDL_SCANCODE_PAGEUP: + scroll -= height; + return true; + case SDL.SDL_Scancode.SDL_SCANCODE_HOME: + scroll = 0; + return true; + case SDL.SDL_Scancode.SDL_SCANCODE_END: + scroll = maxScroll.Y; + return true; + default: + return false; + } + } + + public bool TextInput(string input) => false; + public bool KeyUp(SDL.SDL_Keysym key) => false; + public void FocusChanged(bool focused) {} } public abstract class ScrollArea : Scrollable