From f911bf5f5b5bcd5385483348c1ccb172aa737126 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 11 Jul 2017 15:02:44 -0400 Subject: [PATCH] Fix fuzzy text rendering and fix wrapping --- ShiftOS.Frontend/Apps/CodeShop.cs | 156 +++++++++++++++++ ShiftOS.Frontend/Desktop/Desktop.cs | 17 +- ShiftOS.Frontend/GUI/ListBox.cs | 162 ++++++++++++++++++ .../GraphicsSubsystem/GraphicsContext.cs | 4 +- .../GraphicsSubsystem/UIManager.cs | 14 +- ShiftOS.Frontend/ShiftOS.Frontend.csproj | 2 + ShiftOS.Frontend/ShiftOS.cs | 2 +- 7 files changed, 348 insertions(+), 9 deletions(-) create mode 100644 ShiftOS.Frontend/Apps/CodeShop.cs create mode 100644 ShiftOS.Frontend/GUI/ListBox.cs diff --git a/ShiftOS.Frontend/Apps/CodeShop.cs b/ShiftOS.Frontend/Apps/CodeShop.cs new file mode 100644 index 0000000..ad44fda --- /dev/null +++ b/ShiftOS.Frontend/Apps/CodeShop.cs @@ -0,0 +1,156 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using ShiftOS.Engine; +using ShiftOS.Frontend.GraphicsSubsystem; + +namespace ShiftOS.Frontend.Apps +{ + [WinOpen("shiftorium")] + public class CodeShop : GUI.Control, IShiftOSWindow + { + private GUI.ListBox upgradelist = null; + private ShiftoriumUpgrade selectedUpgrade = null; + private GUI.ProgressBar upgradeprogress = null; + private GUI.Button buy = null; + + public CodeShop() + { + Width = 720; + Height = 480; + } + + protected override void OnLayout() + { + try + { + upgradelist.X = 30; + upgradelist.Y = 75; + upgradelist.Width = this.Width / 2; + upgradelist.Width -= 30; + upgradelist.Height = this.Height - upgradelist.Y - 75; + upgradeprogress.X = upgradelist.X; + upgradeprogress.Y = upgradelist.Y + upgradelist.Height + 10; + upgradeprogress.Width = upgradelist.Width; + upgradeprogress.Height = 24; + upgradeprogress.Maximum = Shiftorium.GetDefaults().Count; + upgradeprogress.Value = SaveSystem.CurrentSave.CountUpgrades(); + buy.X = Width - buy.Width - 15; + buy.Y = Height - buy.Height - 15; + buy.Visible = (selectedUpgrade != null); + + } + catch + { + + } + } + + public void OnLoad() + { + buy = new GUI.Button(); + buy.Text = "Buy upgrade"; + buy.AutoSize = true; + buy.Font = SkinEngine.LoadedSkin.MainFont; + buy.Click += () => + { + if(Shiftorium.Buy(selectedUpgrade.ID, selectedUpgrade.Cost) == true) + { + Engine.Infobox.Show("Upgrade installed!", "You have successfully bought and installed the " + selectedUpgrade.Name + " upgrade for " + selectedUpgrade.Cost + " Codepoints."); + SelectUpgrade(null); + PopulateList(); + } + else + { + Engine.Infobox.Show("Insufficient funds.", "You do not have enough Codepoints to buy this upgrade. You need " + (selectedUpgrade.Cost - SaveSystem.CurrentSave.Codepoints) + " more."); + } + }; + AddControl(buy); + upgradelist = new GUI.ListBox(); + upgradeprogress = new GUI.ProgressBar(); + AddControl(upgradeprogress); + AddControl(upgradelist); + upgradelist.SelectedIndexChanged += () => + { + string itemtext = upgradelist.SelectedItem.ToString(); + var upg = Shiftorium.GetAvailable().FirstOrDefault(x => $"{x.Category}: {x.Name} - {x.Cost}CP" == itemtext); + if(upg != null) + { + SelectUpgrade(upg); + } + }; + PopulateList(); + } + + public void SelectUpgrade(ShiftoriumUpgrade upgrade) + { + if(selectedUpgrade != upgrade) + { + selectedUpgrade = upgrade; + Invalidate(); + } + } + + public void PopulateList() + { + upgradelist.ClearItems(); + foreach(var upgrade in Shiftorium.GetAvailable()) + { + upgradelist.AddItem($"{upgrade.Category}: {upgrade.Name} - {upgrade.Cost}CP"); + Invalidate(); + } + } + + public void OnSkinLoad() + { + } + + public bool OnUnload() + { + return true; + } + + public void OnUpgrade() + { + PopulateList(); + } + + protected override void OnPaint(GraphicsContext gfx) + { + base.OnPaint(gfx); + + string title = "Welcome to the Shiftorium!"; + string desc = @"The Shiftorium is a place where you can buy upgrades for your computer. These upgrades include hardware enhancements, kernel and software optimizations and features, new programs, upgrades to existing programs, and more. + +As you continue through your job, going further up the ranks, you will unlock additional upgrades which can be found here. You may also find upgrades which are not available within the Shiftorium when hacking more difficult and experienced targets. These upgrades are very rare and hard to find, though. You'll find them in the ""Installed Upgrades"" list."; + + if(selectedUpgrade != null) + { + title = selectedUpgrade.Category + ": " + selectedUpgrade.Name; + + desc = selectedUpgrade.Description; + } + + int wrapwidth = (Width - (upgradelist.X + upgradelist.Width)) - 45; + var titlemeasure = gfx.MeasureString(title, SkinEngine.LoadedSkin.Header2Font, wrapwidth); + + var descmeasure = gfx.MeasureString(desc, SkinEngine.LoadedSkin.MainFont, wrapwidth); + + int availablewidth = Width - (upgradelist.X + upgradelist.Width); + int titlelocx = (availablewidth - (int)titlemeasure.X) / 2; + titlelocx += (Width - availablewidth); + int titlelocy = 30; + gfx.DrawString(title, titlelocx, titlelocy, SkinEngine.LoadedSkin.ControlTextColor.ToMonoColor(), SkinEngine.LoadedSkin.Header2Font); + + int desclocy = (Height - (int)descmeasure.Y) / 2; + int desclocx = (Width - availablewidth) + ((availablewidth - (int)descmeasure.X) / 2); + gfx.DrawString(desc, desclocx, desclocy, SkinEngine.LoadedSkin.ControlTextColor.ToMonoColor(), SkinEngine.LoadedSkin.MainFont, wrapwidth); + + string shiftorium = "Shiftorium"; + var smeasure = gfx.MeasureString(shiftorium, SkinEngine.LoadedSkin.HeaderFont); + gfx.DrawString(shiftorium, upgradelist.X + ((upgradelist.Width - (int)smeasure.X) / 2), 20, SkinEngine.LoadedSkin.ControlTextColor.ToMonoColor(), SkinEngine.LoadedSkin.HeaderFont); + } + } +} diff --git a/ShiftOS.Frontend/Desktop/Desktop.cs b/ShiftOS.Frontend/Desktop/Desktop.cs index cf3f2d1..85949e2 100644 --- a/ShiftOS.Frontend/Desktop/Desktop.cs +++ b/ShiftOS.Frontend/Desktop/Desktop.cs @@ -213,6 +213,11 @@ namespace ShiftOS.Frontend.Desktop //This statement closes the app launcher. If we do this after opening it, we can't open it at all as it instantly closes. if (alOpen == true && MouseLeftDown == true) { + if(alSelectedItem != -1) + { + var item = LauncherItems[alSelectedItem]; + AppearanceManager.SetupWindow((IShiftOSWindow)Activator.CreateInstance(item.Data.LaunchType, null)); + } alOpen = false; Invalidate(); return; @@ -335,17 +340,19 @@ namespace ShiftOS.Frontend.Desktop if (alOpen) { - int height = LauncherItems[0].Height * LauncherItems.Count; - int width = LauncherItems[0].Width; - gfx.DrawRectangle(alX, alY, width, height, UIManager.SkinTextures["Menu_ToolStripDropDownBackground"]); + int height = (LauncherItems[0].Height * LauncherItems.Count) + 2; + int width = LauncherItems[0].Width + 2; + gfx.DrawRectangle(alX, alY, width, height, UIManager.SkinTextures["Menu_MenuBorder"]); + gfx.DrawRectangle(alX+1, alY+1, width-2, height-2, UIManager.SkinTextures["Menu_ToolStripDropDownBackground"]); + gfx.DrawRectangle(alX+1, alY+1, 18, height-2, UIManager.SkinTextures["Menu_ImageMarginGradientBegin"]); foreach(var item in LauncherItems) { if(LauncherItems.IndexOf(item) == alSelectedItem) { - gfx.DrawRectangle(alX, alY + item.Y, item.Width, item.Y, UIManager.SkinTextures["Menu_MenuItemSelected"]); + gfx.DrawRectangle(alX+1, alY + item.Y+1, item.Width-2, item.Height, UIManager.SkinTextures["Menu_MenuItemSelected"]); } - gfx.DrawString(Localization.Parse(item.Data.DisplayData.Name), alX + 20, alY + item.Y, LoadedSkin.Menu_TextColor.ToMonoColor(), LoadedSkin.MainFont); + gfx.DrawString(Localization.Parse(item.Data.DisplayData.Name), alX + 21, alY + item.Y+1, LoadedSkin.Menu_TextColor.ToMonoColor(), LoadedSkin.MainFont); } } } diff --git a/ShiftOS.Frontend/GUI/ListBox.cs b/ShiftOS.Frontend/GUI/ListBox.cs new file mode 100644 index 0000000..f9354e0 --- /dev/null +++ b/ShiftOS.Frontend/GUI/ListBox.cs @@ -0,0 +1,162 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Xna.Framework; +using ShiftOS.Frontend.GraphicsSubsystem; +using static ShiftOS.Engine.SkinEngine; + +namespace ShiftOS.Frontend.GUI +{ + public class ListBox : GUI.Control + { + private int fontheight = 0; + private List items = new List(); + private int selectedIndex = -1; + private int itemOffset = 0; + private int itemsPerPage = 1; + + public int SelectedIndex + { + get + { + return MathHelper.Clamp(selectedIndex, 0, items.Count - 1); + } + set + { + selectedIndex = MathHelper.Clamp(value, 0, items.Count - 1); + RecalculateItemsPerPage(); + SelectedIndexChanged?.Invoke(); + } + } + + public object SelectedItem + { + get + { + try + { + return items[SelectedIndex]; + } + catch + { + return ""; + } + } + } + + public void ClearItems() + { + selectedIndex = -1; + items.Clear(); + SelectedIndexChanged?.Invoke(); + Invalidate(); + } + + public void AddItem(object item) + { + items.Add(item); + RecalculateItemsPerPage(); + Invalidate(); + } + + public void RemoveItem(object item) + { + items.Remove(item); + selectedIndex = -1; + RecalculateItemsPerPage(); + SelectedIndexChanged?.Invoke(); + Invalidate(); + } + + public void RecalculateItemsPerPage() + { + itemsPerPage = 0; + while(itemsPerPage * fontheight < Height && itemsPerPage < items.Count - 1) + { + itemsPerPage++; + } + //We have the amount of items we can fit on screen. + //Now let's calculate the offset based on this, as well + //as the currently selected item. + //of course, if there IS one. + if(selectedIndex > -1) + { + if(selectedIndex >= items.Count) + { + selectedIndex = items.Count - 1; + } + while(this.itemOffset > selectedIndex) + { + itemOffset--; + } + while(this.itemOffset + itemsPerPage < selectedIndex) + { + itemOffset++; + } + } + } + + protected override void OnKeyEvent(KeyEvent e) + { + if(e.Key== Microsoft.Xna.Framework.Input.Keys.Down) + { + if(selectedIndex < items.Count - 2) + { + selectedIndex++; + RecalculateItemsPerPage(); + SelectedIndexChanged?.Invoke(); + Invalidate(); + } + } + else if(e.Key == Microsoft.Xna.Framework.Input.Keys.Up) + { + if(selectedIndex > 0) + { + selectedIndex--; + RecalculateItemsPerPage(); + SelectedIndexChanged?.Invoke(); + Invalidate(); + } + } + } + + protected override void OnPaint(GraphicsContext gfx) + { + gfx.Clear(LoadedSkin.ControlTextColor.ToMonoColor()); + gfx.DrawRectangle(1, 1, Width - 2, Height - 2, UIManager.SkinTextures["ControlColor"]); + for(int i = itemOffset; i < items.Count - 1 && i < itemsPerPage; i++) + { + int x = 1; + int y = fontheight * (i - itemOffset); + int width = Width - 2; + int height = fontheight; + if(i == selectedIndex) + { + //draw the string as selected + gfx.DrawRectangle(x, y, width, height, UIManager.SkinTextures["ControlTextColor"]); + gfx.DrawString(items[i].ToString(), x, y, LoadedSkin.ControlColor.ToMonoColor(), LoadedSkin.MainFont); + } + else + { + gfx.DrawRectangle(x, y, width, height, UIManager.SkinTextures["ControlColor"]); + gfx.DrawString(items[i].ToString(), x, y, LoadedSkin.ControlTextColor.ToMonoColor(), LoadedSkin.MainFont); + + } + } + } + + protected override void OnLayout() + { + if(fontheight != LoadedSkin.MainFont.Height) + { + fontheight = LoadedSkin.MainFont.Height; + Invalidate(); + } + base.OnLayout(); + } + + public event Action SelectedIndexChanged; + } +} diff --git a/ShiftOS.Frontend/GraphicsSubsystem/GraphicsContext.cs b/ShiftOS.Frontend/GraphicsSubsystem/GraphicsContext.cs index 772abc4..e2b93fe 100644 --- a/ShiftOS.Frontend/GraphicsSubsystem/GraphicsContext.cs +++ b/ShiftOS.Frontend/GraphicsSubsystem/GraphicsContext.cs @@ -160,9 +160,9 @@ namespace ShiftOS.Frontend.GraphicsSubsystem var sFormat = System.Drawing.StringFormat.GenericTypographic; sFormat.FormatFlags |= System.Drawing.StringFormatFlags.NoClip; - gfx.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias; + gfx.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit; - gfx.DrawString(text, font, System.Drawing.Brushes.White, 0, 0, sFormat); + gfx.DrawString(text, font, System.Drawing.Brushes.White, new System.Drawing.RectangleF(0, 0, bmp.Width, bmp.Height), sFormat); } var lck = bmp.LockBits(new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); diff --git a/ShiftOS.Frontend/GraphicsSubsystem/UIManager.cs b/ShiftOS.Frontend/GraphicsSubsystem/UIManager.cs index d8fdf2e..942b8b6 100644 --- a/ShiftOS.Frontend/GraphicsSubsystem/UIManager.cs +++ b/ShiftOS.Frontend/GraphicsSubsystem/UIManager.cs @@ -94,6 +94,18 @@ namespace ShiftOS.Frontend.GraphicsSubsystem else { _target = TextureCaches[hc]; + if(_target.Width != ctrl.Width || _target.Height != ctrl.Height) + { + _target = new RenderTarget2D( + graphics, + ctrl.Width, + ctrl.Height, + false, + graphics.PresentationParameters.BackBufferFormat, + DepthFormat.Depth24); + TextureCaches[hc] = _target; + + } } if (ctrl.RequiresPaint) { @@ -188,7 +200,7 @@ namespace ShiftOS.Frontend.GraphicsSubsystem { var color = (System.Drawing.Color)colorfield.GetValue(SkinEngine.LoadedSkin); var tex2 = new Texture2D(graphics, 1, 1); - tex2.SetData(new[] { color.B, color.G, color.R, color.A }); + tex2.SetData(new[] { color.R, color.G, color.B, color.A }); SkinTextures.Add(colorfield.Name, tex2); } diff --git a/ShiftOS.Frontend/ShiftOS.Frontend.csproj b/ShiftOS.Frontend/ShiftOS.Frontend.csproj index 7cc9513..709b7c8 100644 --- a/ShiftOS.Frontend/ShiftOS.Frontend.csproj +++ b/ShiftOS.Frontend/ShiftOS.Frontend.csproj @@ -42,6 +42,7 @@ app.manifest + @@ -52,6 +53,7 @@ + diff --git a/ShiftOS.Frontend/ShiftOS.cs b/ShiftOS.Frontend/ShiftOS.cs index 1ab0ad1..56ffc38 100644 --- a/ShiftOS.Frontend/ShiftOS.cs +++ b/ShiftOS.Frontend/ShiftOS.cs @@ -90,7 +90,7 @@ namespace ShiftOS.Frontend }; //We'll use sandbox mode - SaveSystem.IsSandbox = true; + SaveSystem.IsSandbox = false; Engine.Infobox.Show("Test window", "This is a test window."); SaveSystem.Begin(true);