aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ShiftOS.Frontend/Content/Content.mgcb15
-rw-r--r--ShiftOS.Frontend/Desktop/Desktop.cs85
-rw-r--r--ShiftOS.Frontend/Desktop/WindowManager.cs383
-rw-r--r--ShiftOS.Frontend/GUI/Button.cs49
-rw-r--r--ShiftOS.Frontend/GUI/Control.cs642
-rw-r--r--ShiftOS.Frontend/GUI/ItemGroup.cs64
-rw-r--r--ShiftOS.Frontend/GUI/PictureBox.cs146
-rw-r--r--ShiftOS.Frontend/GUI/ProgressBar.cs57
-rw-r--r--ShiftOS.Frontend/GUI/TextControl.cs112
-rw-r--r--ShiftOS.Frontend/GUI/TextInput.cs89
-rw-r--r--ShiftOS.Frontend/GraphicsSubsystem/UIManager.cs353
-rw-r--r--ShiftOS.Frontend/Icon.bmpbin0 -> 262282 bytes
-rw-r--r--ShiftOS.Frontend/Icon.icobin0 -> 147541 bytes
-rw-r--r--ShiftOS.Frontend/Infobox.cs189
-rw-r--r--ShiftOS.Frontend/Program.cs20
-rw-r--r--ShiftOS.Frontend/Properties/AssemblyInfo.cs36
-rw-r--r--ShiftOS.Frontend/Properties/Resources.Designer.cs83
-rw-r--r--ShiftOS.Frontend/Properties/Resources.resx127
-rw-r--r--ShiftOS.Frontend/Resources/cursor_9x_pointer.pngbin0 -> 219 bytes
-rw-r--r--ShiftOS.Frontend/Resources/justthes.pngbin0 -> 10030 bytes
-rw-r--r--ShiftOS.Frontend/ShiftOS.Frontend.csproj156
-rw-r--r--ShiftOS.Frontend/ShiftOS.cs240
-rw-r--r--ShiftOS.Frontend/Window.cs32
-rw-r--r--ShiftOS.Frontend/app.manifest42
-rw-r--r--ShiftOS.Objects/ShiftOS.Objects.csproj3
-rw-r--r--ShiftOS.WinForms/Program.cs1
-rw-r--r--ShiftOS/App.config6
-rw-r--r--ShiftOS/Program.cs15
-rw-r--r--ShiftOS/Properties/AssemblyInfo.cs36
-rw-r--r--ShiftOS/ShiftOS.csproj60
-rw-r--r--ShiftOS/packages.config4
-rw-r--r--ShiftOS_TheReturn.sln6
-rw-r--r--ShiftOS_TheReturn/App.config24
-rw-r--r--ShiftOS_TheReturn/Desktop.cs9
-rw-r--r--ShiftOS_TheReturn/Localization.cs105
-rw-r--r--ShiftOS_TheReturn/Properties/Resources.Designer.cs23
-rw-r--r--ShiftOS_TheReturn/Properties/Settings.Designer.cs26
-rw-r--r--ShiftOS_TheReturn/ShiftOS.Engine.csproj3
-rw-r--r--ShiftOS_TheReturn/Shiftorium.cs2
39 files changed, 3144 insertions, 99 deletions
diff --git a/ShiftOS.Frontend/Content/Content.mgcb b/ShiftOS.Frontend/Content/Content.mgcb
new file mode 100644
index 0000000..ddc4c36
--- /dev/null
+++ b/ShiftOS.Frontend/Content/Content.mgcb
@@ -0,0 +1,15 @@
+
+#----------------------------- Global Properties ----------------------------#
+
+/outputDir:bin/$(Platform)
+/intermediateDir:obj/$(Platform)
+/platform:DesktopGL
+/config:
+/profile:Reach
+/compress:False
+
+#-------------------------------- References --------------------------------#
+
+
+#---------------------------------- Content ---------------------------------#
+
diff --git a/ShiftOS.Frontend/Desktop/Desktop.cs b/ShiftOS.Frontend/Desktop/Desktop.cs
new file mode 100644
index 0000000..5bcf3a9
--- /dev/null
+++ b/ShiftOS.Frontend/Desktop/Desktop.cs
@@ -0,0 +1,85 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using ShiftOS.Engine;
+
+namespace ShiftOS.Frontend.Desktop
+{
+ public class Desktop : GUI.Control, IDesktop
+ {
+ public string DesktopName
+ {
+ get
+ {
+ return "ShiftOS MonoGame Desktop";
+ }
+ }
+
+ public void Close()
+ {
+ throw new NotImplementedException();
+ }
+
+ public Size GetSize()
+ {
+ return new Size(Width, Height);
+ }
+
+ public void HideAppLauncher()
+ {
+
+ }
+
+ public void InvokeOnWorkerThread(Action act)
+ {
+ act?.Invoke();
+ }
+
+ public void KillWindow(IWindowBorder border)
+ {
+ }
+
+ public void MaximizeWindow(IWindowBorder brdr)
+ {
+ }
+
+ public void MinimizeWindow(IWindowBorder brdr)
+ {
+ }
+
+ public void OpenAppLauncher(Point loc)
+ {
+ }
+
+ public void PopulateAppLauncher(LauncherItem[] items)
+ {
+ }
+
+ public void PopulatePanelButtons()
+ {
+ }
+
+ public void PushNotification(string app, string title, string message)
+ {
+ }
+
+ public void RestoreWindow(IWindowBorder brdr)
+ {
+ }
+
+ public void SetupDesktop()
+ {
+ }
+
+ public void Show()
+ {
+ }
+
+ public void ShowWindow(IWindowBorder border)
+ {
+ }
+ }
+}
diff --git a/ShiftOS.Frontend/Desktop/WindowManager.cs b/ShiftOS.Frontend/Desktop/WindowManager.cs
new file mode 100644
index 0000000..5efb30e
--- /dev/null
+++ b/ShiftOS.Frontend/Desktop/WindowManager.cs
@@ -0,0 +1,383 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using ShiftOS.Engine;
+using ShiftOS.Frontend.GraphicsSubsystem;
+using static ShiftOS.Engine.SkinEngine;
+
+namespace ShiftOS.Frontend.Desktop
+{
+ public class WindowManager : Engine.WindowManager
+ {
+ public override void Close(IShiftOSWindow win)
+ {
+ var brdr = RunningBorders.FirstOrDefault(x => x.ParentWindow == win);
+ if (brdr != null)
+ {
+ brdr.Close();
+ win = null;
+ }
+ }
+
+ private List<WindowBorder> RunningBorders = new List<WindowBorder>();
+
+ public override void InvokeAction(Action act)
+ {
+ act?.Invoke();
+ }
+
+ public override void Maximize(IWindowBorder border)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override void Minimize(IWindowBorder border)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override void SetTitle(IShiftOSWindow win, string title)
+ {
+ var brdr = RunningBorders.FirstOrDefault(x => x.ParentWindow == win);
+ if (brdr != null)
+ brdr.Text = title;
+ }
+
+ public override void SetupDialog(IShiftOSWindow win)
+ {
+ var wb = new WindowBorder();
+ wb.Width = (win as GUI.Control).Width + LoadedSkin.LeftBorderWidth + LoadedSkin.RightBorderWidth;
+ wb.Height = (win as GUI.Control).Height + LoadedSkin.TitlebarHeight + LoadedSkin.BottomBorderWidth;
+ wb.ParentWindow = win;
+ wb.IsDialog = true;
+ UIManager.AddTopLevel(wb);
+ RunningBorders.Add(wb);
+ win.OnLoad();
+ win.OnUpgrade();
+ win.OnSkinLoad();
+ }
+
+ public override void SetupWindow(IShiftOSWindow win)
+ {
+ if (!Shiftorium.UpgradeAttributesUnlocked(win.GetType()))
+ {
+ Console.WriteLine("Application not found on system.");
+ return;
+ }
+ var wb = new WindowBorder();
+ wb.Width = (win as GUI.Control).Width + LoadedSkin.LeftBorderWidth + LoadedSkin.RightBorderWidth;
+ wb.Height = (win as GUI.Control).Height + LoadedSkin.TitlebarHeight + LoadedSkin.BottomBorderWidth;
+ wb.ParentWindow = win;
+ wb.IsDialog = true;
+ UIManager.AddTopLevel(wb);
+ AppearanceManager.OpenForms.Add(wb);
+ RunningBorders.Add(wb);
+ win.OnLoad();
+ win.OnUpgrade();
+ win.OnSkinLoad();
+
+ }
+ }
+
+ public class WindowBorder : GUI.Control, IWindowBorder
+ {
+ private string _text = "ShiftOS window";
+ private GUI.Control _hostedwindow = null;
+
+ public WindowBorder()
+ {
+ X = 720;
+ Y = 480;
+ }
+
+ public IShiftOSWindow ParentWindow
+ {
+ get
+ {
+ return (IShiftOSWindow)_hostedwindow;
+ }
+
+ set
+ {
+ _hostedwindow = (GUI.Control)value;
+ ClearControls();
+ AddControl(_hostedwindow);
+ Width = (LoadedSkin.LeftBorderWidth*2) + _hostedwindow.Width + LoadedSkin.RightBorderWidth;
+ Height = LoadedSkin.BottomBorderWidth + _hostedwindow.Height + (LoadedSkin.TitlebarHeight*2);
+
+ }
+ }
+
+ public bool IsDialog { get; set; }
+
+ public string Text
+ {
+ get
+ {
+ return _text;
+ }
+
+ set
+ {
+ _text = value;
+ }
+ }
+
+ public void Close()
+ {
+ Visible = false;
+ UIManager.StopHandling(this);
+ }
+
+ private int lastmousex, lastmousey = 0;
+
+ protected override void OnLayout()
+ {
+ if (moving)
+ {
+ var screenpoint = PointToScreen(MouseX, MouseY);
+ this.X = lastmousex + screenpoint.X;
+ this.Y = lastmousey + screenpoint.Y;
+ }
+ int titlebarheight = Shiftorium.UpgradeInstalled("wm_titlebar") ? LoadedSkin.TitlebarHeight : 0;
+ int borderleft = Shiftorium.UpgradeInstalled("window_borders") ? LoadedSkin.LeftBorderWidth : 0;
+ int borderright = Shiftorium.UpgradeInstalled("window_borders") ? LoadedSkin.RightBorderWidth : 0;
+ int borderbottom = Shiftorium.UpgradeInstalled("window_borders") ? LoadedSkin.BottomBorderWidth : 0;
+ _hostedwindow.X = borderleft;
+ _hostedwindow.Y = titlebarheight;
+ }
+
+ private bool moving = false;
+
+ public override void MouseStateChanged()
+ {
+ if (Shiftorium.UpgradeInstalled("wm_titlebar"))
+ {
+ if (Shiftorium.UpgradeInstalled("close_button"))
+ {
+ var closebuttonsize = LoadedSkin.CloseButtonSize;
+ var closebuttonloc = LoadedSkin.CloseButtonFromSide;
+ if (LoadedSkin.TitleButtonPosition == 0)
+ closebuttonloc = new Point(Width - closebuttonsize.Width - closebuttonloc.X, closebuttonloc.Y);
+ if(MouseX > closebuttonloc.X && MouseY > closebuttonloc.Y && MouseX < closebuttonloc.X + closebuttonsize.Width && MouseY < closebuttonloc.Y + closebuttonsize.Height)
+ {
+ Close();
+ }
+ }
+ if (Shiftorium.UpgradeInstalled("minimize_button"))
+ {
+ var closebuttonsize = LoadedSkin.MinimizeButtonSize;
+ var closebuttonloc = LoadedSkin.MinimizeButtonFromSide;
+ if (LoadedSkin.TitleButtonPosition == 0)
+ closebuttonloc = new Point(Width - closebuttonsize.Width - closebuttonloc.X, closebuttonloc.Y);
+ if (MouseX > closebuttonloc.X && MouseY > closebuttonloc.Y && MouseX < closebuttonloc.X + closebuttonsize.Width && MouseY < closebuttonloc.Y + closebuttonsize.Height)
+ {
+ if (IsFocusedControl || ContainsFocusedControl)
+ UIManager.FocusedControl = null;
+ Visible = false;
+ }
+ }
+ if (Shiftorium.UpgradeInstalled("maximize_button"))
+ {
+ var closebuttonsize = LoadedSkin.MaximizeButtonSize;
+ var closebuttonloc = LoadedSkin.MaximizeButtonFromSide;
+ if (LoadedSkin.TitleButtonPosition == 0)
+ closebuttonloc = new Point(Width - closebuttonsize.Width - closebuttonloc.X, closebuttonloc.Y);
+ if (MouseX > closebuttonloc.X && MouseY > closebuttonloc.Y && MouseX < closebuttonloc.X + closebuttonsize.Width && MouseY < closebuttonloc.Y + closebuttonsize.Height)
+ {
+ AppearanceManager.Maximize(this);
+ }
+ }
+ if (MouseY < LoadedSkin.TitlebarHeight)
+ {
+ var screenpoint = PointToScreen(MouseX, MouseY);
+ lastmousex = this.X - screenpoint.X;
+ lastmousey = this.Y - screenpoint.Y;
+
+ moving = MouseLeftDown;
+ CaptureMouse = moving;
+ }
+ }
+ }
+
+ protected override void OnPaint(Graphics gfx)
+ {
+ int titleheight = LoadedSkin.TitlebarHeight;
+ int leftborderwidth = LoadedSkin.LeftBorderWidth;
+ int rightborderwidth = LoadedSkin.RightBorderWidth;
+ int bottomborderwidth = LoadedSkin.BottomBorderWidth;
+
+ if (Shiftorium.UpgradeInstalled("wm_titlebar"))
+ {
+ var titlebarcolor = LoadedSkin.TitleBackgroundColor;
+ var titlefont = LoadedSkin.TitleFont;
+ var titletextcolor = LoadedSkin.TitleTextColor;
+ var titletextleft = LoadedSkin.TitleTextLeft;
+ bool titletextcentered = LoadedSkin.TitleTextCentered;
+
+ var titlebarbg = GetImage("titlebar");
+ var titlebarlayout = GetImageLayout("titlebar");
+
+ var drawcorners = LoadedSkin.ShowTitleCorners;
+ int titlebarleft = 0;
+ int titlebarwidth = Width;
+ if (drawcorners)
+ {
+ //set titleleft to the first corner width
+ titlebarleft = LoadedSkin.TitleLeftCornerWidth;
+ titlebarwidth -= titlebarleft;
+ titlebarwidth -= LoadedSkin.TitleRightCornerWidth;
+
+ //Let's get the left and right images.
+ var leftimage = GetImage("titlebarleft");
+ var rightimage = GetImage("titlebarright");
+ //and the colors
+ var leftcolor = LoadedSkin.TitleLeftCornerBackground;
+ var rightcolor = LoadedSkin.TitleRightCornerBackground;
+ //and the layouts...
+ var leftlayout = GetImageLayout("titlebarleft");
+ var rightlayout = GetImageLayout("titlebarright");
+ //and the widths
+ var leftwidth = LoadedSkin.TitleLeftCornerWidth;
+ var rightwidth = LoadedSkin.TitleRightCornerWidth;
+
+ //draw left corner
+ if(leftimage != null)
+ {
+ var resized = ResizeImage(leftimage, leftwidth, titleheight);
+ gfx.DrawImage(resized, 0, 0);
+ }
+ else
+ {
+ gfx.FillRectangle(new SolidBrush(leftcolor), new Rectangle(0, 0, leftwidth, titleheight));
+ }
+
+ //draw right corner
+ if (rightimage != null)
+ {
+ var resized = ResizeImage(rightimage, rightwidth, titleheight);
+ gfx.DrawImage(resized, titlebarleft+titlebarwidth, 0);
+ }
+ else
+ {
+ gfx.FillRectangle(new SolidBrush(rightcolor), new Rectangle(titlebarleft+titlebarwidth, 0, rightwidth, titleheight));
+ }
+ }
+
+ if (titlebarbg == null)
+ {
+ //draw the title bg
+ gfx.FillRectangle(new SolidBrush(titlebarcolor), new Rectangle(titlebarleft, 0, titlebarwidth, titleheight));
+
+
+ }
+ else
+ {
+ var resized = ResizeImage(titlebarbg, titlebarwidth, titleheight);
+ gfx.DrawImage(resized, titlebarleft, 0);
+ }
+ //Now we draw the title text.
+ var textMeasure = gfx.MeasureString(_text, titlefont);
+ PointF textloc;
+ if (titletextcentered)
+ textloc = new PointF((titlebarwidth - textMeasure.Width) / 2,
+ titletextleft.Y);
+ else
+ textloc = new PointF(titlebarleft + titletextleft.X, titletextleft.Y);
+
+ gfx.DrawString(_text, titlefont, new SolidBrush(titletextcolor), textloc);
+
+ var tbuttonpos = LoadedSkin.TitleButtonPosition;
+
+ //Draw close button
+ if(Shiftorium.UpgradeInstalled("close_button"))
+ {
+ var closebuttoncolor = LoadedSkin.CloseButtonColor;
+ var closebuttonsize = LoadedSkin.CloseButtonSize;
+ var closebuttonright = LoadedSkin.CloseButtonFromSide;
+ if (LoadedSkin.TitleButtonPosition == 0)
+ closebuttonright = new Point(Width - closebuttonsize.Width - closebuttonright.X, closebuttonright.Y);
+
+ gfx.FillRectangle(new SolidBrush(closebuttoncolor), new Rectangle(closebuttonright, closebuttonsize));
+
+ }
+ //Draw maximize button
+ if (Shiftorium.UpgradeInstalled("maximize_button"))
+ {
+ var closebuttoncolor = LoadedSkin.MaximizeButtonColor;
+ var closebuttonsize = LoadedSkin.MaximizeButtonSize;
+ var closebuttonright = LoadedSkin.MaximizeButtonFromSide;
+ if (LoadedSkin.TitleButtonPosition == 0)
+ closebuttonright = new Point(Width - closebuttonsize.Width - closebuttonright.X, closebuttonright.Y);
+
+ gfx.FillRectangle(new SolidBrush(closebuttoncolor), new Rectangle(closebuttonright, closebuttonsize));
+
+ }
+ //Draw minimize button
+ if (Shiftorium.UpgradeInstalled("minimize_button"))
+ {
+ var closebuttoncolor = LoadedSkin.MinimizeButtonColor;
+ var closebuttonsize = LoadedSkin.MinimizeButtonSize;
+ var closebuttonright = LoadedSkin.MinimizeButtonFromSide;
+ if (LoadedSkin.TitleButtonPosition == 0)
+ closebuttonright = new Point(Width - closebuttonsize.Width - closebuttonright.X, closebuttonright.Y);
+
+ gfx.FillRectangle(new SolidBrush(closebuttoncolor), new Rectangle(closebuttonright, closebuttonsize));
+
+ }
+ }
+ else
+ {
+ //Set the titleheight to 0.
+ titleheight = 0;
+
+ }
+
+ if (Shiftorium.UpgradeInstalled("window_borders"))
+ {
+ //Some variables we'll need...
+ int bottomlocy = Height - LoadedSkin.BottomBorderWidth;
+ int bottomlocx = leftborderwidth;
+ int bottomwidth = Width - bottomlocx - rightborderwidth;
+ int brightlocx = Width - rightborderwidth;
+
+ var borderleftcolor = (ContainsFocusedControl || IsFocusedControl) ? LoadedSkin.BorderLeftBackground : LoadedSkin.BorderInactiveLeftBackground;
+ var borderrightcolor = (ContainsFocusedControl || IsFocusedControl) ? LoadedSkin.BorderRightBackground : LoadedSkin.BorderInactiveRightBackground;
+ var borderbottomcolor = (ContainsFocusedControl || IsFocusedControl) ? LoadedSkin.BorderBottomBackground : LoadedSkin.BorderInactiveBottomBackground;
+ var borderbleftcolor = (ContainsFocusedControl || IsFocusedControl) ? LoadedSkin.BorderBottomLeftBackground : LoadedSkin.BorderInactiveBottomLeftBackground;
+ var borderbrightcolor = (ContainsFocusedControl || IsFocusedControl) ? LoadedSkin.BorderBottomRightBackground : LoadedSkin.BorderInactiveBottomRightBackground;
+
+
+ //draw border corners
+ //BOTTOM LEFT
+ gfx.FillRectangle(new SolidBrush(borderbleftcolor), new Rectangle(0, bottomlocy, leftborderwidth, bottomborderwidth));
+
+
+ //BOTTOM RIGHT
+ gfx.FillRectangle(new SolidBrush(borderbrightcolor), new Rectangle(brightlocx, bottomlocy, rightborderwidth, bottomborderwidth));
+
+ //BOTTOM
+ gfx.FillRectangle(new SolidBrush(borderbottomcolor), new Rectangle(bottomlocx, bottomlocy, bottomwidth, bottomborderwidth));
+
+ //LEFT
+ gfx.FillRectangle(new SolidBrush(borderleftcolor), new Rectangle(0, titleheight, leftborderwidth, Height - titleheight - bottomborderwidth));
+
+ //RIGHT
+ gfx.FillRectangle(new SolidBrush(borderrightcolor), new Rectangle(brightlocx, titleheight, rightborderwidth, Height - titleheight - bottomborderwidth));
+
+
+ }
+
+ //So here's what we're gonna do now.
+ //Now that we have a titlebar and window borders...
+ //We're going to composite the hosted window
+ //and draw it to the remaining area.
+
+ //Painting of the canvas is done by the Paint() method.
+ }
+
+ }
+}
diff --git a/ShiftOS.Frontend/GUI/Button.cs b/ShiftOS.Frontend/GUI/Button.cs
new file mode 100644
index 0000000..551d0d4
--- /dev/null
+++ b/ShiftOS.Frontend/GUI/Button.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using ShiftOS.Engine;
+
+namespace ShiftOS.Frontend.GUI
+{
+ public class Button : TextControl
+ {
+ public Button()
+ {
+ TextAlign = TextAlign.MiddleCenter;
+ Text = "Click me!";
+ }
+
+ protected override void OnLayout()
+ {
+ if(AutoSize == true)
+ {
+ int borderwidth = SkinEngine.LoadedSkin.ButtonBorderWidth * 2;
+
+ using (var gfx = Graphics.FromImage(new Bitmap(1, 1)))
+ {
+ var measure = gfx.MeasureString(this.Text, this.Font);
+ Width = borderwidth + (int)measure.Width + 16;
+ Height = borderwidth + (int)measure.Height + 12;
+ }
+ }
+ }
+
+ protected override void OnPaint(Graphics gfx)
+ {
+ Color bgCol = SkinEngine.LoadedSkin.ButtonBackgroundColor;
+ Color fgCol = SkinEngine.LoadedSkin.ControlTextColor;
+ if (ContainsMouse)
+ bgCol = SkinEngine.LoadedSkin.ButtonHoverColor;
+ if (MouseLeftDown)
+ bgCol = SkinEngine.LoadedSkin.ButtonPressedColor;
+
+ gfx.Clear(bgCol);
+ gfx.DrawRectangle(new Pen(new SolidBrush(fgCol), SkinEngine.LoadedSkin.ButtonBorderWidth), new Rectangle(0, 0, Width, Height));
+ base.OnPaint(gfx);
+
+ }
+ }
+}
diff --git a/ShiftOS.Frontend/GUI/Control.cs b/ShiftOS.Frontend/GUI/Control.cs
new file mode 100644
index 0000000..90e7ba5
--- /dev/null
+++ b/ShiftOS.Frontend/GUI/Control.cs
@@ -0,0 +1,642 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.Xna.Framework.Graphics;
+using Microsoft.Xna.Framework.Input;
+using System.Drawing;
+using ShiftOS.Frontend.GraphicsSubsystem;
+using System.Drawing.Imaging;
+using System.Drawing.Drawing2D;
+using Microsoft.Xna.Framework;
+
+namespace ShiftOS.Frontend.GUI
+{
+ public abstract class Control
+ {
+ private int _x = 0;
+ private int _y = 0;
+ private int _w = 0;
+ private int _h = 0;
+ private Control _parent = null;
+ private List<Control> _children = new List<Control>();
+ private bool _wasMouseInControl = false;
+ private bool _leftState = false;
+ private bool _rightState = false;
+ private bool _middleState = false;
+ private bool _visible = true;
+ private DockStyle _dock = DockStyle.None;
+ private bool _focused = false;
+ private bool _autoSize = false;
+ private double _opacity = 1.0;
+ private bool _invalidated = true;
+ private Bitmap _texCache = null;
+ private Anchor _anchor = null;
+ private int _mouseX = 0;
+ private int _mouseY = 0;
+ private bool _captureMouse = false;
+
+ public bool CaptureMouse
+ {
+ get
+ {
+ return _captureMouse;
+ }
+ set
+ {
+ _captureMouse = value;
+ }
+ }
+
+ public int MouseX
+ {
+ get
+ {
+ return _mouseX;
+ }
+ }
+
+ public int MouseY
+ {
+ get
+ {
+ return _mouseY;
+ }
+ }
+
+
+ public Anchor Anchor
+ {
+ get
+ {
+ return _anchor;
+ }
+ set
+ {
+ _anchor = value;
+ Invalidate();
+ }
+ }
+
+ public void Invalidate()
+ {
+ _invalidated = true;
+ foreach(var child in _children)
+ {
+ child.Invalidate();
+ }
+ }
+
+ public double Opacity
+ {
+ get
+ {
+ return _opacity;
+ }
+ set
+ {
+ _opacity = value;
+ Invalidate();
+ }
+ }
+
+ public bool AutoSize
+ {
+ get
+ {
+ return _autoSize;
+ }
+ set
+ {
+ _autoSize = value;
+ }
+ }
+
+ //Thank you, StackOverflow.
+ public static Bitmap ResizeImage(Image image, int width, int height)
+ {
+ var destRect = new System.Drawing.Rectangle(0, 0, width, height);
+ var destImage = new Bitmap(width, height);
+
+ destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
+
+ using (var graphics = Graphics.FromImage(destImage))
+ {
+ graphics.CompositingMode = CompositingMode.SourceCopy;
+ graphics.CompositingQuality = CompositingQuality.HighQuality;
+ graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
+ graphics.SmoothingMode = SmoothingMode.HighQuality;
+ graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
+
+ using (var wrapMode = new ImageAttributes())
+ {
+ wrapMode.SetWrapMode(WrapMode.TileFlipXY);
+ graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
+ }
+ }
+
+ return destImage;
+ }
+
+ public DockStyle Dock
+ {
+ get
+ {
+ return _dock;
+ }
+ set
+ {
+ _dock = value;
+ }
+ }
+
+ public bool ContainsMouse
+ {
+ get { return _wasMouseInControl; }
+ }
+
+ public bool Visible
+ {
+ get
+ {
+ return _visible;
+ }
+ set
+ {
+ _visible = value;
+ Invalidate();
+ }
+ }
+
+ public void AddControl(Control ctrl)
+ {
+ if (!_children.Contains(ctrl))
+ {
+ ctrl._parent = this;
+ _children.Add(ctrl);
+ Invalidate();
+ }
+ }
+
+ public bool MouseLeftDown
+ {
+ get
+ {
+ return _leftState;
+ }
+ }
+
+ public bool MouseMiddleDown
+ {
+ get
+ {
+ return _middleState;
+ }
+ }
+
+ public bool MouseRightDown
+ {
+ get
+ {
+ return _rightState;
+ }
+ }
+
+
+
+ public int X
+ {
+ get
+ {
+ return _x;
+ }
+ set
+ {
+ _x = value;
+ Invalidate();
+ }
+ }
+
+ public int Y
+ {
+ get
+ {
+ return _y;
+ }
+ set
+ {
+ _y = value;
+ Invalidate();
+ }
+ }
+
+ public int Width
+ {
+ get
+ {
+ return _w;
+ }
+ set
+ {
+ _w = value;
+ Invalidate();
+ }
+ }
+
+ public int Height
+ {
+ get
+ {
+ return _h;
+ }
+ set
+ {
+ _h = value;
+ Invalidate();
+ }
+ }
+
+ public Control Parent
+ {
+ get
+ {
+ return _parent;
+ }
+ }
+
+ public Control[] Children
+ {
+ get
+ {
+ return _children.ToArray();
+ }
+ }
+
+ public Point PointToParent(int x, int y)
+ {
+ return new Point(x + _x, y + _y);
+ }
+
+ public Point PointToScreen(int x, int y)
+ {
+ var parentCoords = PointToParent(x, y);
+ Control parent = this._parent;
+ while(parent != null)
+ {
+ parentCoords = parent.PointToParent(parentCoords.X, parentCoords.Y);
+ parent = parent.Parent;
+ }
+ return parentCoords;
+ }
+
+ public void ClearControls()
+ {
+ _children.Clear();
+ Invalidate();
+ }
+
+ public Point PointToLocal(int x, int y)
+ {
+ return new GUI.Point(x - _x, y - _y);
+ }
+
+ public virtual void MouseStateChanged() { }
+
+ protected virtual void OnPaint(Graphics gfx)
+ {
+
+ }
+
+ public void InvalidateTopLevel()
+ {
+ var parent = this;
+ while (parent.Parent != null)
+ parent = parent.Parent;
+ parent.Invalidate();
+ }
+
+ public void Paint(System.Drawing.Graphics gfx)
+ {
+ if (_visible == true)
+ {
+ if (_invalidated)
+ {
+ _texCache = new Bitmap(Width, Height);
+ using (var cGfx = Graphics.FromImage(_texCache))
+ {
+ OnPaint(cGfx);
+ }
+ _invalidated = false;
+ }
+ gfx.DrawImage(_texCache, 0, 0);
+ foreach (var child in _children)
+ {
+ if (child.Visible)
+ {
+ if (child._invalidated)
+ {
+ var cBmp = new Bitmap(child.Width, child.Height);
+ child.Paint(System.Drawing.Graphics.FromImage(cBmp));
+ cBmp.SetOpacity((float)child.Opacity);
+ child._invalidated = false;
+ child._texCache = cBmp;
+ gfx.DrawImage(cBmp, new System.Drawing.Point(child.X, child.Y));
+
+
+
+ }
+ else
+ {
+ gfx.DrawImage(child._texCache, child.X, child.Y);
+ }
+ }
+ }
+
+ }
+ }
+
+ public void Layout()
+ {
+ //Dock style
+ if(_parent != null)
+ {
+ if(_anchor != null)
+ {
+
+ }
+
+ switch (_dock)
+ {
+ case DockStyle.Top:
+ X = 0;
+ Y = 0;
+ Width = _parent.Width;
+ break;
+ case DockStyle.Left:
+ X = 0;
+ Y = 0;
+ Height = _parent.Height;
+ break;
+ case DockStyle.Right:
+ Y = 0;
+ X = _parent.Width - Width;
+ Height = _parent.Height;
+ break;
+ case DockStyle.Bottom:
+ X = 0;
+ Y = _parent.Height - Height;
+ Width = _parent.Width;
+ break;
+ case DockStyle.Fill:
+ X = 0;
+ Y = 0;
+ Width = _parent.Width;
+ Height = _parent.Height;
+ break;
+ }
+ }
+ OnLayout();
+ foreach (var child in _children)
+ child.Layout();
+ }
+
+ protected virtual void OnLayout()
+ {
+ //do nothing
+ }
+
+ public bool IsFocusedControl
+ {
+ get
+ {
+ return UIManager.FocusedControl == this;
+ }
+ }
+
+ public bool ContainsFocusedControl
+ {
+ get
+ {
+ if (UIManager.FocusedControl == null)
+ return false;
+ else
+ {
+ bool contains = false;
+
+ var ctrl = UIManager.FocusedControl;
+ while(ctrl.Parent != null)
+ {
+ ctrl = ctrl.Parent;
+ if (ctrl == this)
+ contains = true;
+ }
+ return contains;
+ }
+ }
+ }
+
+ public virtual bool ProcessMouseState(MouseState state)
+ {
+ //If we aren't rendering the control, we aren't accepting input.
+ if (_visible == false)
+ return false;
+
+
+ //Firstly, we get the mouse coordinates in the local space
+ var coords = PointToLocal(state.Position.X, state.Position.Y);
+ _mouseX = coords.X;
+ _mouseY = coords.Y;
+ //Now we check if the mouse is within the bounds of the control
+ if(coords.X >= 0 && coords.Y >= 0 && coords.X <= _w && coords.Y <= _h)
+ {
+ //We're in the local space. Let's fire the MouseMove event.
+ MouseMove?.Invoke(coords);
+ //Also, if the mouse hasn't been in the local space last time it moved, fire MouseEnter.
+ if(_wasMouseInControl == false)
+ {
+ _wasMouseInControl = true;
+ MouseEnter?.Invoke();
+ Invalidate();
+ }
+
+ //Things are going to get a bit complicated.
+ //Firstly, we need to find out if we have any children.
+ bool _requiresMoreWork = true;
+ if(_children.Count > 0)
+ {
+ //We do. We're going to iterate through them all and process the mouse state.
+ foreach(var control in _children)
+ {
+
+ //If the process method returns true, then we do not need to do anything else on our end.
+
+ //We need to first create a new mousestate object with the new coordinates
+
+ var nstate = new MouseState(coords.X, coords.Y, state.ScrollWheelValue, state.LeftButton, state.MiddleButton, state.RightButton, state.XButton1, state.XButton2);
+ //pass that state to the process method, and set the _requiresMoreWork value to the opposite of the return value
+ _requiresMoreWork = !control.ProcessMouseState(nstate);
+ //If it's false, break the loop.
+ if (_requiresMoreWork == false)
+ break;
+ }
+ }
+
+ //If we need to do more work...
+ if(_requiresMoreWork == true)
+ {
+ bool fire = false; //so we know to fire a MouseStateChanged method
+ //Let's get the state values of each button
+ bool ld = state.LeftButton == ButtonState.Pressed;
+ bool md = state.MiddleButton == ButtonState.Pressed;
+ bool rd = state.RightButton == ButtonState.Pressed;
+ if(ld != _leftState || md != _middleState || rd != _rightState)
+ {
+ fire = true;
+ }
+ if (_leftState == true && ld == false)
+ {
+ Click?.Invoke();
+ Invalidate();
+ }
+ if (_leftState == false && ld == true)
+ {
+ var focused = UIManager.FocusedControl;
+ UIManager.FocusedControl = this;
+ focused?.InvalidateTopLevel();
+ InvalidateTopLevel();
+ }
+ _leftState = ld;
+ _middleState = md;
+ _rightState = rd;
+ if (fire)
+ MouseStateChanged();
+ }
+ return true;
+ }
+ else
+ {
+ _leftState = false;
+ _rightState = false;
+ _middleState = false;
+ MouseStateChanged();
+ //If the mouse was in local space before, fire MouseLeave
+ if (_wasMouseInControl == true)
+ {
+ if (CaptureMouse == true)
+ {
+ _wasMouseInControl = true;
+ int newX = MathHelper.Clamp(state.X, X, X + Width);
+ int newY = MathHelper.Clamp(state.Y, Y, Y + Height);
+ Mouse.SetPosition(newX, newY);
+
+ }
+ else
+ {
+ _wasMouseInControl = false;
+ MouseLeave?.Invoke();
+ Invalidate();
+ }
+ }
+ }
+ if (CaptureMouse == true)
+ {
+ _mouseX = coords.X;
+ _mouseY = coords.Y;
+ Layout();
+ _wasMouseInControl = true;
+ int newX = MathHelper.Clamp(state.X, X, X + Width);
+ int newY = MathHelper.Clamp(state.Y, Y, Y + Height);
+ Mouse.SetPosition(newX, newY);
+ return true;
+ }
+
+ //Mouse is not in the local space, don't do anything.
+ return false;
+ }
+
+ protected virtual void OnKeyEvent(KeyEvent e)
+ {
+
+ }
+
+ public void ProcessKeyEvent(KeyEvent e)
+ {
+ OnKeyEvent(e);
+ KeyEvent?.Invoke(e);
+ }
+
+ public event Action<Point> MouseMove;
+ public event Action MouseEnter;
+ public event Action MouseLeave;
+ public event Action Click;
+ public event Action<KeyEvent> KeyEvent;
+ }
+
+ public struct Point
+ {
+ public Point(int x, int y)
+ {
+ X = x;
+ Y = y;
+ }
+
+ public int X { get; set; }
+ public int Y { get; set; }
+ }
+
+ public enum DockStyle
+ {
+ None,
+ Top,
+ Bottom,
+ Left,
+ Right,
+ Fill
+ }
+
+ //Thanks, StackOverflow.
+ public static class BitmapExtensions
+ {
+ public static Image SetOpacity(this Image image, float opacity)
+ {
+ var colorMatrix = new ColorMatrix();
+ colorMatrix.Matrix33 = opacity;
+ var imageAttributes = new ImageAttributes();
+ imageAttributes.SetColorMatrix(
+ colorMatrix,
+ ColorMatrixFlag.Default,
+ ColorAdjustType.Bitmap);
+ var output = new Bitmap(image.Width, image.Height);
+ using (var gfx = Graphics.FromImage(output))
+ {
+ gfx.SmoothingMode = SmoothingMode.AntiAlias;
+ gfx.DrawImage(
+ image,
+ new System.Drawing.Rectangle(0, 0, image.Width, image.Height),
+ 0,
+ 0,
+ image.Width,
+ image.Height,
+ GraphicsUnit.Pixel,
+ imageAttributes);
+ }
+ return output;
+ }
+ }
+
+ [Flags]
+ public enum AnchorStyle
+ {
+ Top,
+ Left,
+ Bottom,
+ Right
+ }
+
+ public class Anchor
+ {
+ public AnchorStyle Style { get; set; }
+ public int Distance { get; set; }
+ }
+}
diff --git a/ShiftOS.Frontend/GUI/ItemGroup.cs b/ShiftOS.Frontend/GUI/ItemGroup.cs
new file mode 100644
index 0000000..e52a17f
--- /dev/null
+++ b/ShiftOS.Frontend/GUI/ItemGroup.cs
@@ -0,0 +1,64 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ShiftOS.Frontend.GUI
+{
+ public class ItemGroup : Control
+ {
+ private int _gap = 3;
+ private FlowDirection _flowDir = FlowDirection.LeftToRight;
+ private int _initialgap = 2;
+
+ protected override void OnLayout()
+ {
+ if (AutoSize)
+ {
+ int _highesty = _initialgap;
+ int _xx = _initialgap;
+ foreach(var ctrl in Children)
+ {
+ _xx += ctrl.Width + _gap;
+ if (_highesty < ctrl.Height + _initialgap + _gap)
+ _highesty = ctrl.Height + _initialgap + _gap;
+ }
+ Width = _xx;
+ Height = _highesty;
+ }
+
+ int _x = _initialgap;
+ int _y = _initialgap;
+ int _maxYForRow = 0;
+ foreach (var ctrl in Children)
+ {
+ if (_x + ctrl.Width + _gap > Width)
+ {
+ _x = _initialgap;
+ _y = _maxYForRow;
+ _maxYForRow = 0;
+ if (_maxYForRow < ctrl.Height + _gap)
+ _maxYForRow = ctrl.Height + _gap;
+ }
+ ctrl.X = _x;
+ ctrl.Y = _y;
+ ctrl.Dock = DockStyle.None;
+ ctrl.Layout();
+ _x += ctrl.Width + _gap;
+
+ if (_maxYForRow < ctrl.Height + _gap)
+ _maxYForRow = ctrl.Height + _gap;
+
+ }
+ }
+ }
+
+ public enum FlowDirection
+ {
+ LeftToRight,
+ TopDown,
+ RightToLeft,
+ BottomUp
+ }
+}
diff --git a/ShiftOS.Frontend/GUI/PictureBox.cs b/ShiftOS.Frontend/GUI/PictureBox.cs
new file mode 100644
index 0000000..9a234d4
--- /dev/null
+++ b/ShiftOS.Frontend/GUI/PictureBox.cs
@@ -0,0 +1,146 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using ShiftOS.Engine;
+using System.Drawing.Imaging;
+
+namespace ShiftOS.Frontend.GUI
+{
+ public class PictureBox : Control
+ {
+ private System.Drawing.Image img = null;
+ private ImageLayout _layout = ImageLayout.Fit;
+
+ public ImageLayout ImageLayout
+ {
+ get
+ {
+ return _layout;
+ }
+ set
+ {
+ _layout = value;
+ }
+ }
+
+ public System.Drawing.Image Image
+ {
+ get
+ {
+ return img;
+ }
+ set
+ {
+ if (img != null)
+ img.Dispose();
+ img = value;
+ }
+ }
+
+ protected override void OnLayout()
+ {
+ if (AutoSize)
+ {
+ Width = (img == null) ? 0 : img.Width;
+ Height = (img == null) ? 0 : img.Height;
+ }
+ }
+
+ protected override void OnPaint(Graphics gfx)
+ {
+ if(img != null)
+ switch (_layout)
+ {
+ case ImageLayout.None:
+ //Just draw the image.
+ gfx.DrawImage(img, new PointF(0, 0));
+ break;
+ case ImageLayout.Stretch:
+ //Stretch the image, with no regard for aspect ratio.
+ var stretched = ResizeImage(img, Width, Height);
+ gfx.DrawImage(stretched, 0, 0);
+ break;
+ case ImageLayout.Fit:
+ //Resize image to fit the control but keep aspect ratio.
+ var fitted = FixedSize(img, Width, Height);
+ gfx.DrawImage(fitted, 0, 0);
+ break;
+ case ImageLayout.Tile:
+ //Keep original size but tile the image.
+
+ for(int x = 0; x < Width; x += img.Width)
+ {
+ for (int y = 0; y < Height; y += img.Height)
+ {
+ gfx.DrawImage(img, x, y);
+ }
+ }
+
+ break;
+ }
+ }
+
+ //Again, thanks StackOverflow
+ static Image FixedSize(Image imgPhoto, int Width, int Height)
+ {
+ int sourceWidth = imgPhoto.Width;
+ int sourceHeight = imgPhoto.Height;
+ int sourceX = 0;
+ int sourceY = 0;
+ int destX = 0;
+ int destY = 0;
+
+ float nPercent = 0;
+ float nPercentW = 0;
+ float nPercentH = 0;
+
+ nPercentW = ((float)Width / (float)sourceWidth);
+ nPercentH = ((float)Height / (float)sourceHeight);
+ if (nPercentH < nPercentW)
+ {
+ nPercent = nPercentH;
+ destX = System.Convert.ToInt16((Width -
+ (sourceWidth * nPercent)) / 2);
+ }
+ else
+ {
+ nPercent = nPercentW;
+ destY = System.Convert.ToInt16((Height -
+ (sourceHeight * nPercent)) / 2);
+ }
+
+ int destWidth = (int)(sourceWidth * nPercent);
+ int destHeight = (int)(sourceHeight * nPercent);
+
+ Bitmap bmPhoto = new Bitmap(Width, Height,
+ PixelFormat.Format24bppRgb);
+ bmPhoto.SetResolution(imgPhoto.HorizontalResolution,
+ imgPhoto.VerticalResolution);
+
+ Graphics grPhoto = Graphics.FromImage(bmPhoto);
+ grPhoto.Clear(SkinEngine.LoadedSkin.ControlColor);
+ grPhoto.InterpolationMode =
+ InterpolationMode.HighQualityBicubic;
+
+ grPhoto.DrawImage(imgPhoto,
+ new Rectangle(destX, destY, destWidth, destHeight),
+ new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
+ GraphicsUnit.Pixel);
+
+ grPhoto.Dispose();
+ return bmPhoto;
+ }
+ }
+
+ public enum ImageLayout
+ {
+ None,
+ Stretch,
+ Tile,
+ Fit,
+ }
+}
diff --git a/ShiftOS.Frontend/GUI/ProgressBar.cs b/ShiftOS.Frontend/GUI/ProgressBar.cs
new file mode 100644
index 0000000..e35dc27
--- /dev/null
+++ b/ShiftOS.Frontend/GUI/ProgressBar.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using static ShiftOS.Engine.SkinEngine;
+
+namespace ShiftOS.Frontend.GUI
+{
+ public class ProgressBar : Control
+ {
+ private int _maximum = 100;
+ private int _value = 0;
+
+ public int Maximum
+ {
+ get
+ {
+ return _maximum;
+ }
+ set
+ {
+ _maximum = value;
+ }
+ }
+
+ public int Value
+ {
+ get
+ {
+ return _value;
+ }
+ set
+ {
+ _value = value;
+ }
+ }
+
+ protected override void OnPaint(Graphics gfx)
+ {
+ gfx.Clear(LoadedSkin.ProgressBarBackgroundColor);
+ int w = (int)linear(_value, 0, _maximum, 0, Width);
+ gfx.FillRectangle(new SolidBrush(LoadedSkin.ProgressColor), new Rectangle(0, 0, w, Height));
+ }
+
+ static public double linear(double x, double x0, double x1, double y0, double y1)
+ {
+ if ((x1 - x0) == 0)
+ {
+ return (y0 + y1) / 2;
+ }
+ return y0 + (x - x0) * (y1 - y0) / (x1 - x0);
+ }
+
+ }
+}
diff --git a/ShiftOS.Frontend/GUI/TextControl.cs b/ShiftOS.Frontend/GUI/TextControl.cs
new file mode 100644
index 0000000..37b9ca7
--- /dev/null
+++ b/ShiftOS.Frontend/GUI/TextControl.cs
@@ -0,0 +1,112 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ShiftOS.Frontend.GUI
+{
+ public class TextControl : Control
+ {
+ private string _text = "Text Control";
+ private TextAlign _textAlign = TextAlign.TopLeft;
+ private Font _font = new Font("Tahoma", 9f);
+
+ protected override void OnLayout()
+ {
+ if (AutoSize)
+ {
+ using (var bmp = new Bitmap(1, 1))
+ {
+ using(var gfx = Graphics.FromImage(bmp))
+ {
+ var measure = gfx.MeasureString(_text, _font);
+ Width = (int)measure.Width;
+ Height = (int)measure.Height;
+ }
+ }
+ }
+ }
+
+ public string Text
+ {
+ get { return _text; }
+ set { _text = value; }
+ }
+
+ public Font Font
+ {
+ get
+ {
+ return _font;
+ }
+ set
+ {
+ _font = value;
+ }
+ }
+
+ public TextAlign TextAlign
+ {
+ get { return _textAlign; }
+ set { _textAlign = value; }
+ }
+
+ protected override void OnPaint(Graphics gfx)
+ {
+ var sMeasure = gfx.MeasureString(_text, _font, Width);
+ PointF loc = new PointF(2, 2);
+ float centerH = (Width - sMeasure.Width) / 2;
+ float centerV = (Height - sMeasure.Height) / 2;
+ switch (_textAlign)
+ {
+ case TextAlign.TopCenter:
+ loc.X = centerH;
+ break;
+ case TextAlign.TopRight:
+ loc.X = Width - sMeasure.Width;
+ break;
+ case TextAlign.MiddleLeft:
+ loc.Y = centerV;
+ break;
+ case TextAlign.MiddleCenter:
+ loc.Y = centerV;
+ loc.X = centerH;
+ break;
+ case TextAlign.MiddleRight:
+ loc.Y = centerV;
+ loc.X = (Width - sMeasure.Width);
+ break;
+ case TextAlign.BottomLeft:
+ loc.Y = (Height - sMeasure.Height);
+ break;
+ case TextAlign.BottomCenter:
+ loc.Y = (Height - sMeasure.Height);
+ loc.X = centerH;
+ break;
+ case TextAlign.BottomRight:
+ loc.Y = (Height - sMeasure.Height);
+ loc.X = (Width - sMeasure.Width);
+ break;
+
+
+ }
+
+ gfx.DrawString(_text, _font, new SolidBrush(Color.White), new RectangleF(loc.X, loc.Y, sMeasure.Width, sMeasure.Height));
+ }
+ }
+
+ public enum TextAlign
+ {
+ TopLeft,
+ TopCenter,
+ TopRight,
+ MiddleLeft,
+ MiddleCenter,
+ MiddleRight,
+ BottomLeft,
+ BottomCenter,
+ BottomRight
+ }
+}
diff --git a/ShiftOS.Frontend/GUI/TextInput.cs b/ShiftOS.Frontend/GUI/TextInput.cs
new file mode 100644
index 0000000..7466cfd
--- /dev/null
+++ b/ShiftOS.Frontend/GUI/TextInput.cs
@@ -0,0 +1,89 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+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 TextInput : Control
+ {
+ private string _label = "Type here!";
+ private string _text = "";
+ private int _index = 0;
+ private Font _font = new Font("Tahoma", 9f);
+
+ protected override void OnKeyEvent(KeyEvent e)
+ {
+ if(e.Key == Microsoft.Xna.Framework.Input.Keys.Left)
+ {
+ if (_index > 0)
+ _index--;
+
+ }
+ if (e.Key == Microsoft.Xna.Framework.Input.Keys.Right)
+ if (_index < _text.Length)
+ _index++;
+ if (e.KeyChar != '\0') {
+ _text = _text.Insert(_index, e.KeyChar.ToString());
+ _index++;
+ }
+ CalculateVisibleText();
+ Invalidate();
+ base.OnKeyEvent(e);
+ }
+
+ private int textInputOffset = 0;
+ private int maxCanFit = 5;
+ string visibleText = "";
+ float caretPos = 2f;
+
+ protected void CalculateVisibleText()
+ {
+ visibleText = "";
+ caretPos = -1f;
+ using (var gfx = Graphics.FromImage(new Bitmap(1, 1)))
+ {
+ for (int i = textInputOffset; i < _text.Length; i++)
+ {
+ visibleText += _text[i];
+ var measure = gfx.MeasureString(visibleText, _font);
+ if (measure.Width > Width)
+ {
+ maxCanFit = visibleText.Length;
+ if(_index < textInputOffset)
+ {
+ textInputOffset = MathHelper.Clamp(_index - (maxCanFit / 2), 0, _text.Length - 1);
+
+ }
+ if(_index > textInputOffset + maxCanFit)
+ {
+ textInputOffset = MathHelper.Clamp(_index + (maxCanFit / 2), 0, _text.Length - 1) - maxCanFit;
+ }
+ break;
+ }
+ Height = (int)measure.Height + 4;
+ }
+ }
+ }
+
+
+ protected override void OnPaint(Graphics gfx)
+ {
+ gfx.Clear(LoadedSkin.ControlColor);
+ gfx.DrawString(visibleText, _font, new SolidBrush(LoadedSkin.ControlTextColor), 2, 2);
+ if (IsFocusedControl)
+ {
+ //Draw caret.
+ gfx.FillRectangle(new SolidBrush(LoadedSkin.ControlTextColor), new RectangleF(caretPos, 2, 2, Height - 4));
+ }
+ gfx.DrawRectangle(new Pen(new SolidBrush(LoadedSkin.ControlTextColor), 1), new Rectangle(0, 0, Width - 1, Height - 1));
+
+
+ }
+ }
+}
diff --git a/ShiftOS.Frontend/GraphicsSubsystem/UIManager.cs b/ShiftOS.Frontend/GraphicsSubsystem/UIManager.cs
new file mode 100644
index 0000000..372c5a6
--- /dev/null
+++ b/ShiftOS.Frontend/GraphicsSubsystem/UIManager.cs
@@ -0,0 +1,353 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
+using Microsoft.Xna.Framework.Input;
+using ShiftOS.Engine;
+using ShiftOS.Frontend.Desktop;
+using ShiftOS.Frontend.GUI;
+
+namespace ShiftOS.Frontend.GraphicsSubsystem
+{
+ public static class UIManager
+ {
+ private static List<GUI.Control> topLevels = new List<GUI.Control>();
+
+ public static GUI.Control FocusedControl = null;
+
+ public static void LayoutUpdate()
+ {
+ foreach (var toplevel in topLevels)
+ toplevel.Layout();
+ }
+
+ public static void Animate(object owner, System.Reflection.PropertyInfo prop, double from, double to, int timeMs)
+ {
+ var t = new System.Threading.Thread(() =>
+ {
+ for(int i = 0; i < timeMs; i++)
+ {
+ double value = ProgressBar.linear(i, 0, timeMs, from, to);
+ prop.SetValue(owner, value);
+ System.Threading.Thread.Sleep(1);
+ }
+ });
+ t.IsBackground = true;
+ t.Start();
+ }
+
+
+ public static void DrawControls(GraphicsDevice graphics, SpriteBatch batch)
+ {
+ foreach (var ctrl in topLevels.ToArray())
+ {
+ using(var bmp = new System.Drawing.Bitmap(ctrl.Width, ctrl.Height))
+ {
+ var gfx = System.Drawing.Graphics.FromImage(bmp);
+ ctrl.Paint(gfx);
+ bmp.SetOpacity((float)ctrl.Opacity);
+ //get the bits of the bitmap
+ var data = bmp.LockBits(new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
+ byte[] rgb = new byte[Math.Abs(data.Stride) * data.Height];
+ Marshal.Copy(data.Scan0, rgb, 0, rgb.Length);
+ bmp.UnlockBits(data);
+ for(int i = 0; i < rgb.Length; i+=4)
+ {
+ byte r = rgb[i];
+ byte b = rgb[i + 2];
+ rgb[i] = b;
+ rgb[i + 2] = r;
+ }
+ var tex2 = new Texture2D(graphics, bmp.Width, bmp.Height);
+ tex2.SetData<byte>(rgb);
+ batch.Draw(tex2, new Rectangle(ctrl.X, ctrl.Y, ctrl.Width, ctrl.Height), Color.White);
+ }
+ }
+ }
+
+ public static void AddTopLevel(GUI.Control ctrl)
+ {
+ if (!topLevels.Contains(ctrl))
+ topLevels.Add(ctrl);
+ ctrl.Layout();
+ }
+
+ public static void ProcessMouseState(MouseState state)
+ {
+ foreach(var ctrl in topLevels.ToArray())
+ {
+ ctrl.ProcessMouseState(state);
+ }
+ }
+
+ public static void ProcessKeyEvent(KeyEvent e)
+ {
+ FocusedControl?.ProcessKeyEvent(e);
+ }
+
+ public static void DrawBackgroundLayer(GraphicsDevice graphics, SpriteBatch batch, int width, int height)
+ {
+ if (SkinEngine.LoadedSkin == null)
+ SkinEngine.Init();
+ graphics.Clear(SkinEngine.LoadedSkin.DesktopColor.ToMonoColor());
+ var desktopbg = SkinEngine.GetImage("desktopbackground");
+ if(desktopbg != null)
+ {
+ var tex2 = new Texture2D(graphics, desktopbg.Width, desktopbg.Height);
+ tex2.SetData<byte>(SkinEngine.LoadedSkin.DesktopBackgroundImage);
+ batch.Draw(tex2, new Rectangle(0, 0, width, height), Color.White);
+ }
+ }
+
+ public static Color ToMonoColor(this System.Drawing.Color color)
+ {
+ return new Color(color.R, color.G, color.B, color.A);
+ }
+
+ internal static void StopHandling(GUI.Control ctrl)
+ {
+ if (topLevels.Contains(ctrl))
+ topLevels.Remove(ctrl);
+ ctrl = null;
+ }
+ }
+
+ public class KeyEvent
+ {
+ public KeyEvent(bool control, bool alt, bool shift, Keys key)
+ {
+ ControlDown = control;
+ AltDown = alt;
+ ShiftDown = shift;
+ Key = key;
+ KeyChar = key.ToCharacter(shift);
+ }
+
+ public bool ControlDown { get; private set; }
+ public bool AltDown { get; private set; }
+ public bool ShiftDown { get; set; }
+ public Keys Key { get; private set; }
+
+ public char KeyChar { get; private set; }
+ }
+
+ public static class KeysExtensions
+ {
+ public static char ToCharacter(this Keys key, bool shift)
+ {
+ char c = ' ';
+ switch (key)
+ {
+ case Keys.Space:
+ c = ' ';
+ break;
+ case Keys.A:
+ c = 'a';
+ break;
+ case Keys.B:
+ c = 'b';
+ break;
+ case Keys.C:
+ c = 'c';
+ break;
+ case Keys.D:
+ c = 'd';
+ break;
+ case Keys.E:
+ c = 'e';
+ break;
+ case Keys.F:
+ c = 'f';
+ break;
+ case Keys.G:
+ c = 'g';
+ break;
+ case Keys.H:
+ c = 'h';
+ break;
+ case Keys.I:
+ c = 'i';
+ break;
+ case Keys.J:
+ c = 'j';
+ break;
+ case Keys.K:
+ c = 'k';
+ break;
+ case Keys.L:
+ c = 'l';
+ break;
+ case Keys.M:
+ c = 'm';
+ break;
+ case Keys.N:
+ c = 'n';
+ break;
+ case Keys.O:
+ c = 'o';
+ break;
+ case Keys.P:
+ c = 'p';
+ break;
+ case Keys.Q:
+ c = 'q';
+ break;
+ case Keys.R:
+ c = 'r';
+ break;
+ case Keys.S:
+ c = 's';
+ break;
+ case Keys.T:
+ c = 't';
+ break;
+ case Keys.U:
+ c = 'u';
+ break;
+ case Keys.V:
+ c = 'v';
+ break;
+ case Keys.W:
+ c = 'w';
+ break;
+ case Keys.X:
+ c = 'x';
+ break;
+ case Keys.Y:
+ c = 'y';
+ break;
+ case Keys.Z:
+ c = 'z';
+ break;
+ case Keys.D0:
+ if (shift)
+ c = ')';
+ else
+ c = '0';
+ break;
+ case Keys.D1:
+ if (shift)
+ c = '!';
+ else
+ c = '1';
+ break;
+ case Keys.D2:
+ if (shift)
+ c = '@';
+ else
+ c = '2';
+ break;
+ case Keys.D3:
+ if (shift)
+ c = '#';
+ else
+ c = '3';
+ break;
+ case Keys.D4:
+ if (shift)
+ c = '$';
+ else
+ c = '4';
+ break;
+ case Keys.D5:
+ if (shift)
+ c = '%';
+ else
+ c = '5';
+ break;
+ case Keys.D6:
+ if (shift)
+ c = '^';
+ else
+ c = '6';
+ break;
+ case Keys.D7:
+ if (shift)
+ c = '&';
+ else
+ c = '7';
+ break;
+ case Keys.D8:
+ if (shift)
+ c = '*';
+ else
+ c = '8';
+ break;
+ case Keys.D9:
+ if (shift)
+ c = '(';
+ else
+ c = '9';
+ break;
+ case Keys.OemBackslash:
+ if (shift)
+ c = '|';
+ else
+ c = '\\';
+ break;
+ case Keys.OemCloseBrackets:
+ if (shift)
+ c = '}';
+ else
+ c = ']';
+ break;
+ case Keys.OemComma:
+ if (shift)
+ c = '<';
+ else
+ c = ',';
+ break;
+ case Keys.OemPeriod:
+ if (shift)
+ c = '>';
+ else
+ c = '.';
+ break;
+ case Keys.OemQuestion:
+ if (shift)
+ c = '?';
+ else
+ c = '/';
+ break;
+ case Keys.OemSemicolon:
+ if (shift)
+ c = ':';
+ else
+ c = ';';
+ break;
+ case Keys.OemQuotes:
+ if (shift)
+ c = '"';
+ else
+ c = '\'';
+ break;
+ case Keys.OemTilde:
+ if (shift)
+ c = '~';
+ else
+ c = '`';
+ break;
+ case Keys.OemMinus:
+ if (shift)
+ c = '_';
+ else
+ c = '-';
+ break;
+ case Keys.OemPlus:
+ if (shift)
+ c = '+';
+ else
+ c = '=';
+ break;
+ }
+ if (char.IsLetter(c))
+ if (shift)
+ c = char.ToUpper(c);
+ return c;
+ }
+ }
+}
diff --git a/ShiftOS.Frontend/Icon.bmp b/ShiftOS.Frontend/Icon.bmp
new file mode 100644
index 0000000..2b48165
--- /dev/null
+++ b/ShiftOS.Frontend/Icon.bmp
Binary files differ
diff --git a/ShiftOS.Frontend/Icon.ico b/ShiftOS.Frontend/Icon.ico
new file mode 100644
index 0000000..7d9dec1
--- /dev/null
+++ b/ShiftOS.Frontend/Icon.ico
Binary files differ
diff --git a/ShiftOS.Frontend/Infobox.cs b/ShiftOS.Frontend/Infobox.cs
new file mode 100644
index 0000000..53b4857
--- /dev/null
+++ b/ShiftOS.Frontend/Infobox.cs
@@ -0,0 +1,189 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using ShiftOS.Engine;
+using ShiftOS.Frontend.GUI;
+
+namespace ShiftOS.Frontend
+{
+ public class Infobox : IInfobox
+ {
+ public void Open(string title, string msg, Action callback = null)
+ {
+ var imsg = new InfoboxMessage(title, msg);
+ imsg.ShowPrompt(callback);
+ }
+
+ public void PromptText(string title, string message, Action<string> callback, bool isPassword)
+ {
+ var imsg = new InfoboxMessage(title, message);
+ imsg.ShowText(callback);
+ }
+
+ public void PromptYesNo(string title, string message, Action<bool> callback)
+ {
+ var imsg = new InfoboxMessage(title, message);
+ imsg.ShowYesNo(callback);
+
+ }
+ }
+
+ public class InfoboxMessage : GUI.Control, IShiftOSWindow
+ {
+ public InfoboxMessage(string title, string message)
+ {
+ InitializeComponent();
+ lbmessage.Text = Localization.Parse(message);
+ Title = title;
+ }
+
+ public string Title { get; private set; }
+
+ public void OnLoad()
+ {
+ AppearanceManager.SetWindowTitle(this, Title);
+ }
+
+ public void ShowPrompt(Action callback)
+ {
+ AppearanceManager.SetupDialog(this);
+ flyesno.Visible = false;
+ txtinput.Visible = false;
+ btnok.Visible = true;
+ btnok.Click += () =>
+ {
+ callback?.Invoke();
+ AppearanceManager.Close(this);
+ };
+ }
+
+ public void ShowYesNo(Action<bool> callback)
+ {
+ AppearanceManager.SetupDialog(this);
+ flyesno.Visible = true;
+ txtinput.Visible = false;
+ btnok.Visible = false;
+ btnyes.Click += () =>
+ {
+ callback?.Invoke(true);
+ AppearanceManager.Close(this);
+ };
+ btnno.Click += () =>
+ {
+ callback?.Invoke(false);
+ AppearanceManager.Close(this);
+ };
+ }
+
+ public void ShowText(Action<string> callback)
+ {
+ Title = "Not yet implemented.";
+ lbmessage.Text = "This feature hasn't yet been implemented.";
+ ShowPrompt(null);
+
+ }
+
+ public void OnSkinLoad()
+ {
+ }
+
+ public bool OnUnload()
+ {
+ return true;
+ }
+
+ public void OnUpgrade()
+ {
+ }
+
+ //NOTE: The following code is ported over from Windows Forms.
+ /// <summary>
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ /// </summary>
+ private void InitializeComponent()
+ {
+ this.txtinput = new TextInput();
+ this.lbmessage = new TextControl();
+ this.flyesno = new ItemGroup();
+ this.btnyes = new Button();
+ this.btnno = new Button();
+ this.btnok = new Button();
+ this.pbicon = new PictureBox();
+ //
+ // txtinput
+ //
+ this.txtinput.X = 88;
+ this.txtinput.Y = 116;
+ this.txtinput.Width = 250;
+ this.txtinput.Height = 20;
+ //
+ // lbmessage
+ //
+ this.lbmessage.X = 85;
+ this.lbmessage.Y = 19;
+ this.lbmessage.Width = 213;
+ this.lbmessage.Height = 94;
+ this.lbmessage.Text = "label1";
+ this.lbmessage.TextAlign = TextAlign.MiddleLeft;
+ //
+ // flyesno
+ //
+ this.flyesno.AutoSize = true;
+ this.flyesno.AddControl(this.btnyes);
+ this.flyesno.AddControl(this.btnno);
+ this.flyesno.X = 129;
+ this.flyesno.Y = 134;
+ //
+ // btnyes
+ //
+ this.btnyes.AutoSize = true;
+ this.btnyes.Text = Localization.Parse("{GEN_YES}");
+ //
+ // btnno
+ //
+ this.btnno.AutoSize = true;
+ this.btnno.Text = Localization.Parse("{GEN_NO}");
+ //
+ // btnok
+ //
+ this.btnok.AutoSize = true;
+ this.btnok.X = 140;
+ this.btnok.Y = 140;
+ this.btnok.Text = Localization.Parse("{GEN_OK}");
+ //
+ // pbicon
+ //
+ this.pbicon.X = 14;
+ this.pbicon.Y = 19;
+ this.pbicon.Width = 64;
+ this.pbicon.Height = 64;
+ this.pbicon.Image = Properties.Resources.justthes;
+ this.pbicon.ImageLayout = ImageLayout.Stretch;
+ //
+ // Dialog
+ //
+ this.Width = 341;
+ this.Height = 157;
+ this.AddControl(pbicon);
+ this.AddControl(btnok);
+ this.AddControl(flyesno);
+ this.AddControl(lbmessage);
+
+ this.Layout();
+ }
+
+
+ private Control panel1;
+ private TextControl lbmessage;
+ private ItemGroup flyesno;
+ private Button btnyes;
+ private Button btnno;
+ private Button btnok;
+ private PictureBox pbicon;
+ private TextInput txtinput;
+
+ }
+}
diff --git a/ShiftOS.Frontend/Program.cs b/ShiftOS.Frontend/Program.cs
new file mode 100644
index 0000000..031b2ab
--- /dev/null
+++ b/ShiftOS.Frontend/Program.cs
@@ -0,0 +1,20 @@
+using System;
+
+namespace ShiftOS.Frontend
+{
+ /// <summary>
+ /// The main class.
+ /// </summary>
+ public static class Program
+ {
+ /// <summary>
+ /// The main entry point for the application.
+ /// </summary>
+ [STAThread]
+ static void Main()
+ {
+ using (var game = new ShiftOS())
+ game.Run();
+ }
+ }
+}
diff --git a/ShiftOS.Frontend/Properties/AssemblyInfo.cs b/ShiftOS.Frontend/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..f25b1d7
--- /dev/null
+++ b/ShiftOS.Frontend/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("ShiftOS.Frontend")]
+[assembly: AssemblyProduct("ShiftOS.Frontend")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyCopyright("Copyright © 2017")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("13e2a4c8-a6cc-405b-a4ec-5d39531993c2")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/ShiftOS.Frontend/Properties/Resources.Designer.cs b/ShiftOS.Frontend/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..fc35525
--- /dev/null
+++ b/ShiftOS.Frontend/Properties/Resources.Designer.cs
@@ -0,0 +1,83 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace ShiftOS.Frontend.Properties {
+ using System;
+
+
+ /// <summary>
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ /// </summary>
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ /// <summary>
+ /// Returns the cached ResourceManager instance used by this class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ShiftOS.Frontend.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ /// <summary>
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ /// </summary>
+ internal static System.Drawing.Bitmap cursor_9x_pointer {
+ get {
+ object obj = ResourceManager.GetObject("cursor_9x_pointer", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ /// </summary>
+ internal static System.Drawing.Bitmap justthes {
+ get {
+ object obj = ResourceManager.GetObject("justthes", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+ }
+}
diff --git a/ShiftOS.Frontend/Properties/Resources.resx b/ShiftOS.Frontend/Properties/Resources.resx
new file mode 100644
index 0000000..e309997
--- /dev/null
+++ b/ShiftOS.Frontend/Properties/Resources.resx
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+ <data name="cursor_9x_pointer" type="System.Resources.ResXFileRef, System.Windows.Forms">
+ <value>..\Resources\cursor_9x_pointer.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+ </data>
+ <data name="justthes" type="System.Resources.ResXFileRef, System.Windows.Forms">
+ <value>..\Resources\justthes.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+ </data>
+</root> \ No newline at end of file
diff --git a/ShiftOS.Frontend/Resources/cursor_9x_pointer.png b/ShiftOS.Frontend/Resources/cursor_9x_pointer.png
new file mode 100644
index 0000000..ff48150
--- /dev/null
+++ b/ShiftOS.Frontend/Resources/cursor_9x_pointer.png
Binary files differ
diff --git a/ShiftOS.Frontend/Resources/justthes.png b/ShiftOS.Frontend/Resources/justthes.png
new file mode 100644
index 0000000..a85ba27
--- /dev/null
+++ b/ShiftOS.Frontend/Resources/justthes.png
Binary files differ
diff --git a/ShiftOS.Frontend/ShiftOS.Frontend.csproj b/ShiftOS.Frontend/ShiftOS.Frontend.csproj
new file mode 100644
index 0000000..61ff0c6
--- /dev/null
+++ b/ShiftOS.Frontend/ShiftOS.Frontend.csproj
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\MonoGame\v3.0\MonoGame.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\MonoGame\v3.0\MonoGame.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{4DFC3088-1B08-4A0E-A9F5-483A7B9811FD}</ProjectGuid>
+ <OutputType>WinExe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>ShiftOS.Frontend</RootNamespace>
+ <AssemblyName>ShiftOS.Frontend</AssemblyName>
+ <FileAlignment>512</FileAlignment>
+ <MonoGamePlatform>DesktopGL</MonoGamePlatform>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\$(MonoGamePlatform)\$(Platform)\$(Configuration)\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;LINUX</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>false</Prefer32Bit>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
+ <OutputPath>bin\$(MonoGamePlatform)\$(Platform)\$(Configuration)\</OutputPath>
+ <DefineConstants>TRACE;LINUX</DefineConstants>
+ <Optimize>true</Optimize>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <Prefer32Bit>false</Prefer32Bit>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup>
+ <ApplicationIcon>Icon.ico</ApplicationIcon>
+ </PropertyGroup>
+ <PropertyGroup>
+ <ApplicationManifest>app.manifest</ApplicationManifest>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="Desktop\Desktop.cs" />
+ <Compile Include="Desktop\WindowManager.cs" />
+ <Compile Include="GraphicsSubsystem\UIManager.cs" />
+ <Compile Include="GUI\Button.cs" />
+ <Compile Include="GUI\Control.cs" />
+ <Compile Include="GUI\ItemGroup.cs" />
+ <Compile Include="GUI\PictureBox.cs" />
+ <Compile Include="GUI\ProgressBar.cs" />
+ <Compile Include="GUI\TextControl.cs" />
+ <Compile Include="GUI\TextInput.cs" />
+ <Compile Include="Infobox.cs" />
+ <Compile Include="Properties\Resources.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DesignTime>True</DesignTime>
+ <DependentUpon>Resources.resx</DependentUpon>
+ </Compile>
+ <Compile Include="ShiftOS.cs" />
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="Window.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <Reference Include="MonoGame.Framework">
+ <HintPath>$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\DesktopGL\MonoGame.Framework.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Drawing" />
+ <Reference Include="System.Windows.Forms" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Icon.ico" />
+ <EmbeddedResource Include="Icon.bmp" />
+ <EmbeddedResource Include="Properties\Resources.resx">
+ <Generator>ResXFileCodeGenerator</Generator>
+ <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+ </EmbeddedResource>
+ </ItemGroup>
+ <ItemGroup>
+ <MonoGameContentReference Include="Content\Content.mgcb" />
+ <None Include="$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\DesktopGL\x86\SDL2.dll">
+ <Link>x86\SDL2.dll</Link>
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </None>
+ <None Include="$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\DesktopGL\x64\SDL2.dll">
+ <Link>x64\SDL2.dll</Link>
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </None>
+ <None Include="$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\DesktopGL\x86\soft_oal.dll">
+ <Link>x86\soft_oal.dll</Link>
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </None>
+ <None Include="$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\DesktopGL\x64\soft_oal.dll">
+ <Link>x64\soft_oal.dll</Link>
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </None>
+ <None Include="$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\DesktopGL\x86\libSDL2-2.0.so.0">
+ <Link>x86\libSDL2-2.0.so.0</Link>
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </None>
+ <None Include="$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\DesktopGL\x64\libSDL2-2.0.so.0">
+ <Link>x64\libSDL2-2.0.so.0</Link>
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </None>
+ <None Include="$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\DesktopGL\x86\libopenal.so.1">
+ <Link>x86\libopenal.so.1</Link>
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </None>
+ <None Include="$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\DesktopGL\x64\libopenal.so.1">
+ <Link>x64\libopenal.so.1</Link>
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </None>
+ <None Include="$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\DesktopGL\libSDL2-2.0.0.dylib">
+ <Link>libSDL2-2.0.0.dylib</Link>
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </None>
+ <None Include="$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\DesktopGL\libopenal.1.dylib">
+ <Link>libopenal.1.dylib</Link>
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </None>
+ <None Include="$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\DesktopGL\MonoGame.Framework.dll.config">
+ <Link>MonoGame.Framework.dll.config</Link>
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </None>
+ <None Include="app.manifest" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\ShiftOS.Objects\ShiftOS.Objects.csproj">
+ <Project>{a069089a-8962-4607-b2b2-4cf4a371066e}</Project>
+ <Name>ShiftOS.Objects</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\ShiftOS_TheReturn\ShiftOS.Engine.csproj">
+ <Project>{7c979b07-0585-4033-a110-e5555b9d6651}</Project>
+ <Name>ShiftOS.Engine</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="Resources\cursor_9x_pointer.png" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="Resources\justthes.png" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <Import Project="$(MSBuildExtensionsPath)\MonoGame\v3.0\MonoGame.Content.Builder.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/ShiftOS.Frontend/ShiftOS.cs b/ShiftOS.Frontend/ShiftOS.cs
new file mode 100644
index 0000000..6bfa4dc
--- /dev/null
+++ b/ShiftOS.Frontend/ShiftOS.cs
@@ -0,0 +1,240 @@
+using System;
+using System.Linq;
+using System.Runtime.InteropServices;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
+using Microsoft.Xna.Framework.Input;
+using ShiftOS.Engine;
+using ShiftOS.Frontend.GraphicsSubsystem;
+
+namespace ShiftOS.Frontend
+{
+ /// <summary>
+ /// This is the main type for your game.
+ /// </summary>
+ public class ShiftOS : Game
+ {
+ GraphicsDeviceManager GraphicsDevice;
+ SpriteBatch spriteBatch;
+
+ public ShiftOS()
+ {
+ GraphicsDevice = new GraphicsDeviceManager(this);
+ GraphicsDevice.PreferredBackBufferHeight = 1080;
+ GraphicsDevice.PreferredBackBufferWidth = 1920;
+
+ Content.RootDirectory = "Content";
+
+
+ //Make window borderless
+ Window.IsBorderless = false;
+
+ //Set the title
+ Window.Title = "ShiftOS";
+
+
+
+ //Fullscreen
+ GraphicsDevice.IsFullScreen = false;
+
+ }
+
+ private GUI.TextControl _titleLabel = null;
+
+ /// <summary>
+ /// Allows the game to perform any initialization it needs to before starting to run.
+ /// This is where it can query for any required services and load any non-graphic
+ /// related content. Calling base.Initialize will enumerate through any components
+ /// and initialize them as well.
+ /// </summary>
+ protected override void Initialize()
+ {
+ //Before we do ANYTHING, we've got to initiate the ShiftOS engine.
+
+ //First things first, let's initiate the window manager.
+ AppearanceManager.Initiate(new Desktop.WindowManager());
+ //Cool. Now the engine's window management system talks to us.
+
+ //Also initiate the desktop
+ Engine.Desktop.Init(new Desktop.Desktop());
+
+ //Now we can initiate the Infobox subsystem
+ Engine.Infobox.Init(new Infobox());
+
+
+ //Let's give it a try.
+ Engine.Infobox.Show("Welcome to ShiftOS!", "This is a test infobox. Clicking OK will dismiss it.");
+
+ //Let's initiate the engine just for a ha.
+
+ //We'll create a few UI elements when the save system loads
+ SaveSystem.GameReady += () =>
+ {
+ var headerLabel = new GUI.TextControl();
+ headerLabel.Font = SkinEngine.LoadedSkin.HeaderFont;
+ headerLabel.AutoSize = true;
+ headerLabel.Text = "ShiftOS engine startup stats";
+ headerLabel.X = 30;
+ headerLabel.Y = 30;
+ UIManager.AddTopLevel(headerLabel);
+
+ var statslabel = new GUI.TextControl();
+ statslabel.AutoSize = true;
+ statslabel.X = 30;
+ statslabel.Y = headerLabel.Y + headerLabel.Height + 30;
+ UIManager.AddTopLevel(statslabel);
+ statslabel.Text = $@"Save System
+=======================
+
+System name: {SaveSystem.CurrentSave.SystemName}
+Users: {SaveSystem.CurrentSave.Users.Count}
+
+Current user: {SaveSystem.CurrentUser.Username}
+
+Sandbox mode: {SaveSystem.IsSandbox}
+Installed upgrades: {SaveSystem.CurrentSave.CountUpgrades()} - may be inaccurate if in sandbox mode
+Available upgrades: {Shiftorium.GetAvailable().Count()}
+Total upgrades: {Shiftorium.GetDefaults().Count()}
+
+ShiftFS
+============================
+
+Mounted file systems: {Objects.ShiftFS.Utils.Mounts.Count}
+
+Reflection Manager
+=====================
+
+Reflection manager found {ReflectMan.Types.Count()} Common Language Runtime types that ShiftOS can reflect over.
+
+
+";
+ statslabel.Layout();
+ };
+
+ //We'll use sandbox mode
+ SaveSystem.IsSandbox = true;
+
+ SaveSystem.Begin();
+
+ var textinput = new GUI.TextInput();
+ textinput.Width = 250;
+ textinput.Height = 20;
+ textinput.X = 0;
+ textinput.Y = 0;
+ UIManager.AddTopLevel(textinput);
+
+ base.Initialize();
+
+ }
+
+ /// <summary>
+ /// LoadContent will be called once per game and is the place to load
+ /// all of your content.
+ /// </summary>
+ protected override void LoadContent()
+ {
+ // Create a new SpriteBatch, which can be used to draw textures.
+ this.spriteBatch = new SpriteBatch(base.GraphicsDevice);
+
+ // TODO: use this.Content to load your game content here
+ }
+
+ /// <summary>
+ /// UnloadContent will be called once per game and is the place to unload
+ /// game-specific content.
+ /// </summary>
+ protected override void UnloadContent()
+ {
+ // TODO: Unload any non ContentManager content here
+ }
+
+ /// <summary>
+ /// Allows the game to run logic such as updating the world,
+ /// checking for collisions, gathering input, and playing audio.
+ /// </summary>
+ /// <param name="gameTime">Provides a snapshot of timing values.</param>
+ protected override void Update(GameTime gameTime)
+ {
+ //Let's get the mouse state
+ var mouseState = Mouse.GetState(this.Window);
+
+ //Now let's process it.
+ UIManager.ProcessMouseState(mouseState);
+
+ //Cause layout update on all elements
+ UIManager.LayoutUpdate();
+
+ //set framerate
+ framerate.Text = "ShiftOS 1.0 Beta 4\r\nCopyright (c) 2017 ShiftOS\r\nFPS: " + (1 / gameTime.ElapsedGameTime.TotalSeconds);
+
+ //So we have mouse input, and the UI layout system working...
+
+ //But an OS isn't useful without the keyboard!
+
+ //Let's see how keyboard input works.
+
+ //Hmmm... just like the mouse...
+ var keystate = Keyboard.GetState();
+
+ //Simple... just iterate through this list and generate some key events?
+ var keys = keystate.GetPressedKeys();
+ if (keys.Length > 0)
+ {
+ //Of course, we need modifier keys...
+ //First for Control.
+ bool controlDown = keys.Contains(Keys.LeftControl) || keys.Contains(Keys.RightControl);
+ //Now SHIFT.
+ bool shiftDown = keys.Contains(Keys.LeftShift) || keys.Contains(Keys.RightShift);
+ //And ALT.
+ bool altDown = keys.Contains(Keys.LeftAlt) || keys.Contains(Keys.RightAlt);
+
+ foreach(var key in keys)
+ {
+ //This'll make it so we skip the modifier keys.
+ if(key != Keys.LeftAlt && key != Keys.RightAlt && key != Keys.LeftControl && key != Keys.RightControl && key != Keys.LeftShift && key != Keys.RightShift)
+ {
+ var keyevent = new KeyEvent(controlDown, altDown, shiftDown, key);
+ UIManager.ProcessKeyEvent(keyevent);
+ }
+ }
+ }
+
+ base.Update(gameTime);
+ }
+
+ private GUI.TextControl framerate = new GUI.TextControl();
+
+ /// <summary>
+ /// This is called when the game should draw itself.
+ /// </summary>
+ /// <param name="gameTime">Provides a snapshot of timing values.</param>
+ protected override void Draw(GameTime gameTime)
+ {
+ this.spriteBatch.Begin();
+ //Draw the desktop BG.
+ var graphics = GraphicsDevice.GraphicsDevice;
+ UIManager.DrawBackgroundLayer(graphics, spriteBatch, 640, 480);
+
+ //The desktop is drawn, now we can draw the UI.
+ UIManager.DrawControls(graphics, spriteBatch);
+
+ //Draw a mouse cursor
+
+
+ var bmp = Properties.Resources.cursor_9x_pointer;
+ var data = bmp.LockBits(new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
+ byte[] rgb = new byte[Math.Abs(data.Stride) * data.Height];
+ Marshal.Copy(data.Scan0, rgb, 0, rgb.Length);
+ bmp.UnlockBits(data);
+ var mousepos = Mouse.GetState(this.Window).Position;
+ var tex2 = new Texture2D(graphics, bmp.Width, bmp.Height);
+ tex2.SetData<byte>(rgb);
+ spriteBatch.Draw(tex2, new Rectangle(mousepos.X, mousepos.Y, bmp.Width, bmp.Height), Color.White);
+
+
+
+ spriteBatch.End();
+ base.Draw(gameTime);
+ }
+ }
+}
diff --git a/ShiftOS.Frontend/Window.cs b/ShiftOS.Frontend/Window.cs
new file mode 100644
index 0000000..4fd08a5
--- /dev/null
+++ b/ShiftOS.Frontend/Window.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using ShiftOS.Engine;
+
+namespace ShiftOS.Frontend
+{
+ public abstract class Window : IShiftOSWindow
+ {
+ public void OnLoad()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void OnSkinLoad()
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool OnUnload()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void OnUpgrade()
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/ShiftOS.Frontend/app.manifest b/ShiftOS.Frontend/app.manifest
new file mode 100644
index 0000000..048d329
--- /dev/null
+++ b/ShiftOS.Frontend/app.manifest
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
+ <assemblyIdentity version="1.0.0.0" name="ShiftOS.Frontend"/>
+ <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
+ <security>
+ <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
+ <requestedExecutionLevel level="asInvoker" uiAccess="false" />
+ </requestedPrivileges>
+ </security>
+ </trustInfo>
+
+ <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+ <application>
+ <!-- A list of the Windows versions that this application has been tested on and is
+ is designed to work with. Uncomment the appropriate elements and Windows will
+ automatically selected the most compatible environment. -->
+
+ <!-- Windows Vista -->
+ <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />
+
+ <!-- Windows 7 -->
+ <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
+
+ <!-- Windows 8 -->
+ <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />
+
+ <!-- Windows 8.1 -->
+ <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />
+
+ <!-- Windows 10 -->
+ <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
+
+ </application>
+ </compatibility>
+
+ <application xmlns="urn:schemas-microsoft-com:asm.v3">
+ <windowsSettings>
+ <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/pm</dpiAware>
+ </windowsSettings>
+ </application>
+
+</assembly>
diff --git a/ShiftOS.Objects/ShiftOS.Objects.csproj b/ShiftOS.Objects/ShiftOS.Objects.csproj
index 9ed8c3b..4936c01 100644
--- a/ShiftOS.Objects/ShiftOS.Objects.csproj
+++ b/ShiftOS.Objects/ShiftOS.Objects.csproj
@@ -9,8 +9,9 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>ShiftOS.Objects</RootNamespace>
<AssemblyName>ShiftOS.Objects</AssemblyName>
- <TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
+ <TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
diff --git a/ShiftOS.WinForms/Program.cs b/ShiftOS.WinForms/Program.cs
index c73f067..7b3acfa 100644
--- a/ShiftOS.WinForms/Program.cs
+++ b/ShiftOS.WinForms/Program.cs
@@ -50,7 +50,6 @@ namespace ShiftOS.WinForms
Application.SetCompatibleTextRenderingDefault(false);
//if ANYONE puts code before those two winforms config lines they will be declared a drunky. - Michael
SkinEngine.SetPostProcessor(new DitheringSkinPostProcessor());
- LoginManager.Init(new GUILoginFrontend());
CrashHandler.SetGameMetadata(Assembly.GetExecutingAssembly());
SkinEngine.SetIconProber(new ShiftOSIconProvider());
TerminalBackend.TerminalRequested += () =>
diff --git a/ShiftOS/App.config b/ShiftOS/App.config
new file mode 100644
index 0000000..88fa402
--- /dev/null
+++ b/ShiftOS/App.config
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<configuration>
+ <startup>
+ <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
+ </startup>
+</configuration> \ No newline at end of file
diff --git a/ShiftOS/Program.cs b/ShiftOS/Program.cs
new file mode 100644
index 0000000..42ed8bc
--- /dev/null
+++ b/ShiftOS/Program.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ShiftOS
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ }
+ }
+}
diff --git a/ShiftOS/Properties/AssemblyInfo.cs b/ShiftOS/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..dc8476a
--- /dev/null
+++ b/ShiftOS/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("ShiftOS")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("ShiftOS")]
+[assembly: AssemblyCopyright("Copyright © 2017")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("518dae89-d558-4118-bd21-71246f356caf")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/ShiftOS/ShiftOS.csproj b/ShiftOS/ShiftOS.csproj
new file mode 100644
index 0000000..af6b643
--- /dev/null
+++ b/ShiftOS/ShiftOS.csproj
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{518DAE89-D558-4118-BD21-71246F356CAF}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>ShiftOS</RootNamespace>
+ <AssemblyName>ShiftOS</AssemblyName>
+ <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Net.Http" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="App.config" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/ShiftOS/packages.config b/ShiftOS/packages.config
new file mode 100644
index 0000000..5cd6937
--- /dev/null
+++ b/ShiftOS/packages.config
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="MonoGame.Framework.WindowsDX" version="3.6.0.1625" targetFramework="net452" />
+</packages> \ No newline at end of file
diff --git a/ShiftOS_TheReturn.sln b/ShiftOS_TheReturn.sln
index 04f0c5d..b14cb3f 100644
--- a/ShiftOS_TheReturn.sln
+++ b/ShiftOS_TheReturn.sln
@@ -21,6 +21,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModLauncher", "ModLauncher\
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShiftOS.Updater", "ShiftOS.Updater\ShiftOS.Updater.csproj", "{36BC512F-6FD4-4139-AED7-565FC8D5BCBC}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShiftOS.Frontend", "ShiftOS.Frontend\ShiftOS.Frontend.csproj", "{4DFC3088-1B08-4A0E-A9F5-483A7B9811FD}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -63,6 +65,10 @@ Global
{36BC512F-6FD4-4139-AED7-565FC8D5BCBC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{36BC512F-6FD4-4139-AED7-565FC8D5BCBC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{36BC512F-6FD4-4139-AED7-565FC8D5BCBC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4DFC3088-1B08-4A0E-A9F5-483A7B9811FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4DFC3088-1B08-4A0E-A9F5-483A7B9811FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4DFC3088-1B08-4A0E-A9F5-483A7B9811FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4DFC3088-1B08-4A0E-A9F5-483A7B9811FD}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/ShiftOS_TheReturn/App.config b/ShiftOS_TheReturn/App.config
index b899c11..4765378 100644
--- a/ShiftOS_TheReturn/App.config
+++ b/ShiftOS_TheReturn/App.config
@@ -1,27 +1,27 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
- <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
+ <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
</startup>
<runtime>
- <loadFromRemoteSources enabled="true" />
+ <loadFromRemoteSources enabled="true"/>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
- <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
- <bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
+ <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral"/>
+ <bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0"/>
</dependentAssembly>
<dependentAssembly>
- <assemblyIdentity name="System.Interactive.Async" publicKeyToken="94bc3704cddfc263" culture="neutral" />
- <bindingRedirect oldVersion="0.0.0.0-3.0.1000.0" newVersion="3.0.1000.0" />
+ <assemblyIdentity name="System.Interactive.Async" publicKeyToken="94bc3704cddfc263" culture="neutral"/>
+ <bindingRedirect oldVersion="0.0.0.0-3.0.1000.0" newVersion="3.0.1000.0"/>
</dependentAssembly>
<dependentAssembly>
- <assemblyIdentity name="Microsoft.Scripting" publicKeyToken="7f709c5b713576e1" culture="neutral" />
- <bindingRedirect oldVersion="0.0.0.0-1.1.2.22" newVersion="1.1.2.22" />
+ <assemblyIdentity name="Microsoft.Scripting" publicKeyToken="7f709c5b713576e1" culture="neutral"/>
+ <bindingRedirect oldVersion="0.0.0.0-1.1.2.22" newVersion="1.1.2.22"/>
</dependentAssembly>
<dependentAssembly>
- <assemblyIdentity name="IronPython" publicKeyToken="7f709c5b713576e1" culture="neutral" />
- <bindingRedirect oldVersion="0.0.0.0-2.7.7.0" newVersion="2.7.7.0" />
+ <assemblyIdentity name="IronPython" publicKeyToken="7f709c5b713576e1" culture="neutral"/>
+ <bindingRedirect oldVersion="0.0.0.0-2.7.7.0" newVersion="2.7.7.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
-</configuration> \ No newline at end of file
+</configuration>
diff --git a/ShiftOS_TheReturn/Desktop.cs b/ShiftOS_TheReturn/Desktop.cs
index fac5e6b..714d457 100644
--- a/ShiftOS_TheReturn/Desktop.cs
+++ b/ShiftOS_TheReturn/Desktop.cs
@@ -246,7 +246,14 @@ namespace ShiftOS.Engine
public static void InvokeOnWorkerThread(Action act)
{
- _desktop.InvokeOnWorkerThread(act);
+ try
+ {
+ _desktop.InvokeOnWorkerThread(act);
+ }
+ catch
+ {
+ act?.Invoke();
+ }
}
public static void ResetPanelButtons()
diff --git a/ShiftOS_TheReturn/Localization.cs b/ShiftOS_TheReturn/Localization.cs
index 8adfa5a..2414bd9 100644
--- a/ShiftOS_TheReturn/Localization.cs
+++ b/ShiftOS_TheReturn/Localization.cs
@@ -99,63 +99,65 @@ namespace ShiftOS.Engine
public static string Parse(string original, Dictionary<string, string> replace)
{
- Dictionary<string, string> localizationStrings = new Dictionary<string, string>();
-
-
try
{
- localizationStrings = JsonConvert.DeserializeObject<Dictionary<string, string>>(_provider.GetCurrentTranscript());
- }
- catch
- {
- localizationStrings = JsonConvert.DeserializeObject<Dictionary<string, string>>(Utils.ReadAllText(Paths.GetPath("english.local"))); //if no provider fall back to english
- }
-
- foreach (var kv in localizationStrings.Where(x=>original.Contains(x.Key)))
- {
- original = original.Replace(kv.Key, kv.Value); // goes through and replaces all the localization blocks
- }
+ Dictionary<string, string> localizationStrings = new Dictionary<string, string>();
- //string original2 = Parse(original);
- string usernameReplace = "";
- string domainReplace = "";
-
- // if the user has saved then store their username and systemname in these string variables please
- if (SaveSystem.CurrentSave != null)
- {
try
{
- usernameReplace = SaveSystem.CurrentUser.Username;
+ localizationStrings = JsonConvert.DeserializeObject<Dictionary<string, string>>(_provider.GetCurrentTranscript());
}
catch
{
- usernameReplace = "user";
+ localizationStrings = JsonConvert.DeserializeObject<Dictionary<string, string>>(Utils.ReadAllText(Paths.GetPath("english.local"))); //if no provider fall back to english
}
- try
+ foreach (var kv in localizationStrings.Where(x => original.Contains(x.Key)))
{
- domainReplace = SaveSystem.CurrentSave.SystemName;
+ original = original.Replace(kv.Key, kv.Value); // goes through and replaces all the localization blocks
}
- catch
+
+ //string original2 = Parse(original);
+
+ string usernameReplace = "";
+ string domainReplace = "";
+
+ // if the user has saved then store their username and systemname in these string variables please
+ if (SaveSystem.CurrentSave != null)
{
- domainReplace = "system";
+ try
+ {
+ usernameReplace = SaveSystem.CurrentUser.Username;
+ }
+ catch
+ {
+ usernameReplace = "user";
+ }
+
+ try
+ {
+ domainReplace = SaveSystem.CurrentSave.SystemName;
+ }
+ catch
+ {
+ domainReplace = "system";
+ }
+
}
-
- }
- string namespaceReplace = "";
- string commandReplace = "";
+ string namespaceReplace = "";
+ string commandReplace = "";
- // if the user did a command in the terminal and it had a period in it then split it up into the part before the period and the part after and then store them into these two string variables please
- if (TerminalBackend.latestCommmand != "" && TerminalBackend.latestCommmand.IndexOf('.') > -1)
- {
- namespaceReplace = TerminalBackend.latestCommmand.Split('.')[0];
- commandReplace = TerminalBackend.latestCommmand.Split('.')[1];
- }
+ // if the user did a command in the terminal and it had a period in it then split it up into the part before the period and the part after and then store them into these two string variables please
+ if (TerminalBackend.latestCommmand != "" && TerminalBackend.latestCommmand.IndexOf('.') > -1)
+ {
+ namespaceReplace = TerminalBackend.latestCommmand.Split('.')[0];
+ commandReplace = TerminalBackend.latestCommmand.Split('.')[1];
+ }
- // if you see these then replace them with what you need to
- Dictionary<string, string> defaultReplace = new Dictionary<string, string>() {
+ // if you see these then replace them with what you need to
+ Dictionary<string, string> defaultReplace = new Dictionary<string, string>() {
{"%username", usernameReplace},
{"%domain", domainReplace},
{"%ns", namespaceReplace},
@@ -165,19 +167,24 @@ namespace ShiftOS.Engine
#endif
};
- // actually do the replacement
- foreach (KeyValuePair<string, string> replacement in replace.Where(x => original.Contains(x.Key)))
- {
- original = original.Replace(replacement.Key, Parse(replacement.Value));
- }
+ // actually do the replacement
+ foreach (KeyValuePair<string, string> replacement in replace.Where(x => original.Contains(x.Key)))
+ {
+ original = original.Replace(replacement.Key, Parse(replacement.Value));
+ }
+
+ // do the replacement but default
+ foreach (KeyValuePair<string, string> replacement in defaultReplace.Where(x => original.Contains(x.Key)))
+ {
+ original = original.Replace(replacement.Key, replacement.Value);
+ }
- // do the replacement but default
- foreach (KeyValuePair<string, string> replacement in defaultReplace.Where(x => original.Contains(x.Key)))
+ return original; // returns the now replaced string
+ }
+ catch
{
- original = original.Replace(replacement.Key, replacement.Value);
+ return original;
}
-
- return original; // returns the now replaced string
}
// a few things are defined here
diff --git a/ShiftOS_TheReturn/Properties/Resources.Designer.cs b/ShiftOS_TheReturn/Properties/Resources.Designer.cs
index 85b350f..bfadf74 100644
--- a/ShiftOS_TheReturn/Properties/Resources.Designer.cs
+++ b/ShiftOS_TheReturn/Properties/Resources.Designer.cs
@@ -82,7 +82,17 @@ namespace ShiftOS.Engine.Properties {
}
/// <summary>
- /// Looks up a localized string similar to .
+ /// Looks up a localized string similar to /*
+ /// * MIT License
+ /// *
+ /// * Copyright (c) 2017 Michael VanOverbeek and ShiftOS devs
+ /// *
+ /// * Permission is hereby granted, free of charge, to any person obtaining a copy
+ /// * of this software and associated documentation files (the &quot;Software&quot;), to deal
+ /// * in the Software without restriction, including without limitation the rights
+ /// * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ /// * copies of the Software, and to permit persons to whom the Software is
+ /// * furnished to do so, sub [rest of string was truncated]&quot;;.
/// </summary>
internal static string pywintemplate {
get {
@@ -108,8 +118,7 @@ namespace ShiftOS.Engine.Properties {
/// {
/// Name: &quot;WM 4 Windows&quot;,
/// Cost: 150,
- /// Description: &quot;Display up to 4 simultaneous windows on-screen in a 2x2 grid.&quot;,
- /// [rest of string was truncated]&quot;;.
+ /// Description: &quot;Display up to 4 simultaneous windows on-screen i [rest of string was truncated]&quot;;.
/// </summary>
internal static string Shiftorium {
get {
@@ -138,8 +147,7 @@ namespace ShiftOS.Engine.Properties {
///Eine kurze Erklärung wie du das Terminal benutzt lautet wiefolgt. Du kannst das command &apos;sos.help&apos; benutzen um eine Liste aller commands aufzurufen. Schreib es
///einfach in das Terminal und drücke &lt;enter&gt; um alle commands anzuzeigen.
///
- ///Commands können mit argumenten versehen werden, indem du ein key-value Paar in einem {} Block hinter dem command angibst. Zum Beispiel:
- /// [rest of string was truncated]&quot;;.
+ ///Commands können mit argumenten versehen werden, indem du ein key-value Paar in einem {} Block hinter dem command angibst. Zum Be [rest of string was truncated]&quot;;.
/// </summary>
internal static string strings_de {
get {
@@ -158,8 +166,7 @@ namespace ShiftOS.Engine.Properties {
///Commands can be sent arguments by specifying a key-value pair inside a {} block at the end of the command. For example:
///
///some.command{print:\&quot;hello\&quot;}
- ///math.add{op1:1,op2:2}
- /// [rest of string was truncated]&quot;;.
+ ///math.add{op1 [rest of string was truncated]&quot;;.
/// </summary>
internal static string strings_en {
get {
@@ -177,7 +184,7 @@ namespace ShiftOS.Engine.Properties {
/// &quot;Before you can begin with ShiftOS, you&apos;ll need to know a few things about it.&quot;,
/// &quot;One: Terminal command syntax.&quot;,
/// &quot;Inside ShiftOS, the bulk of your time is going to be spent within the Terminal.&quot;,
- /// &quot;The Terminal is an application that starts up when you turn on your computer. It allows you to execute system commands, open program [rest of string was truncated]&quot;;.
+ /// &quot;The Terminal is an application that starts up when you turn on your computer. It allows you to execute system commands, ope [rest of string was truncated]&quot;;.
/// </summary>
internal static string sys_shiftoriumstory {
get {
diff --git a/ShiftOS_TheReturn/Properties/Settings.Designer.cs b/ShiftOS_TheReturn/Properties/Settings.Designer.cs
index 3d7c7cd..a1e2e32 100644
--- a/ShiftOS_TheReturn/Properties/Settings.Designer.cs
+++ b/ShiftOS_TheReturn/Properties/Settings.Designer.cs
@@ -1,28 +1,4 @@
-/*
- * MIT License
- *
- * Copyright (c) 2017 Michael VanOverbeek and ShiftOS devs
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
diff --git a/ShiftOS_TheReturn/ShiftOS.Engine.csproj b/ShiftOS_TheReturn/ShiftOS.Engine.csproj
index f1946ad..02a5eeb 100644
--- a/ShiftOS_TheReturn/ShiftOS.Engine.csproj
+++ b/ShiftOS_TheReturn/ShiftOS.Engine.csproj
@@ -9,7 +9,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>ShiftOS.Engine</RootNamespace>
<AssemblyName>ShiftOS.Engine</AssemblyName>
- <TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<PublishUrl>publish\</PublishUrl>
@@ -27,6 +27,7 @@
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
+ <TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
diff --git a/ShiftOS_TheReturn/Shiftorium.cs b/ShiftOS_TheReturn/Shiftorium.cs
index 0362566..e4c2a08 100644
--- a/ShiftOS_TheReturn/Shiftorium.cs
+++ b/ShiftOS_TheReturn/Shiftorium.cs
@@ -426,7 +426,7 @@ namespace ShiftOS.Engine
try
{
if (SaveSystem.CurrentSave == null)
- return false;
+ return true;
if (SaveSystem.CurrentSave.StoriesExperienced == null)
SaveSystem.CurrentSave.StoriesExperienced = new List<string>();