Fix fuzzy text rendering and fix wrapping

This commit is contained in:
Michael 2017-07-11 15:02:44 -04:00
parent 2f54ddc6b0
commit f911bf5f5b
7 changed files with 348 additions and 9 deletions

View file

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

View file

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

View file

@ -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<object> items = new List<object>();
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;
}
}

View file

@ -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);

View file

@ -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<byte>(new[] { color.B, color.G, color.R, color.A });
tex2.SetData<byte>(new[] { color.R, color.G, color.B, color.A });
SkinTextures.Add(colorfield.Name, tex2);
}

View file

@ -42,6 +42,7 @@
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>
<ItemGroup>
<Compile Include="Apps\CodeShop.cs" />
<Compile Include="Apps\Pong.cs" />
<Compile Include="Apps\Terminal.cs" />
<Compile Include="Commands.cs" />
@ -52,6 +53,7 @@
<Compile Include="GUI\Button.cs" />
<Compile Include="GUI\Control.cs" />
<Compile Include="GUI\ItemGroup.cs" />
<Compile Include="GUI\ListBox.cs" />
<Compile Include="GUI\PictureBox.cs" />
<Compile Include="GUI\ProgressBar.cs" />
<Compile Include="GUI\TextControl.cs" />

View file

@ -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);