diff --git a/ShiftOS.Frontend/Apps/Terminal.cs b/ShiftOS.Frontend/Apps/Terminal.cs index 0f8ddde..9fe71de 100644 --- a/ShiftOS.Frontend/Apps/Terminal.cs +++ b/ShiftOS.Frontend/Apps/Terminal.cs @@ -23,6 +23,13 @@ namespace ShiftOS.Frontend.Apps { private TerminalControl _terminal = null; + public TerminalControl TerminalControl + { + get + { + return _terminal; + } + } public Terminal() { @@ -133,6 +140,19 @@ namespace ShiftOS.Frontend.Apps protected void RecalculateLayout() { + using(var gfx = Graphics.FromImage(new Bitmap(1, 1))) + { + var cloc = GetPointAtIndex(gfx); + var csize = gfx.MeasureString("#", new Font(LoadedSkin.TerminalFont.Name, LoadedSkin.TerminalFont.Size * _zoomFactor, LoadedSkin.TerminalFont.Style)); + if(cloc.Y - _vertOffset < 0) + { + _vertOffset += cloc.Y - _vertOffset; + } + while((cloc.Y + csize.Height) - _vertOffset > Height) + { + _vertOffset += csize.Height; + } + } } private bool blinkStatus = false; @@ -370,12 +390,12 @@ namespace ShiftOS.Frontend.Apps cursorPos.X = lineMeasure.X; } - gfx.DrawRectangle((int)cursorPos.X, (int)cursorPos.Y, (int)cursorSize.X, (int)cursorSize.Y, LoadedSkin.TerminalForeColorCC.ToColor().ToMonoColor()); + gfx.DrawRectangle((int)cursorPos.X, (int)(cursorPos.Y - _vertOffset), (int)cursorSize.X, (int)cursorSize.Y, LoadedSkin.TerminalForeColorCC.ToColor().ToMonoColor()); } //Draw the text - gfx.DrawString(Text, 2, 2, LoadedSkin.TerminalForeColorCC.ToColor().ToMonoColor(), font, Width - 4); + gfx.DrawString(Text, 0, (int)(0 - _vertOffset), LoadedSkin.TerminalForeColorCC.ToColor().ToMonoColor(), font, Width - 4); } } diff --git a/ShiftOS.Frontend/Desktop/Desktop.cs b/ShiftOS.Frontend/Desktop/Desktop.cs index 7bd5d3c..1bca3f8 100644 --- a/ShiftOS.Frontend/Desktop/Desktop.cs +++ b/ShiftOS.Frontend/Desktop/Desktop.cs @@ -25,6 +25,10 @@ namespace ShiftOS.Frontend.Desktop { Show(); SetupDesktop(); + if (!Shiftorium.UpgradeInstalled("tutorial1")) + { + Story.Start("tutorial1"); + } }; MouseMove += (loc) => diff --git a/ShiftOS.Frontend/Desktop/WindowManager.cs b/ShiftOS.Frontend/Desktop/WindowManager.cs index f1ca59b..fbd42f4 100644 --- a/ShiftOS.Frontend/Desktop/WindowManager.cs +++ b/ShiftOS.Frontend/Desktop/WindowManager.cs @@ -136,26 +136,35 @@ namespace ShiftOS.Frontend.Desktop public void TileWindows() { - - if (AppearanceManager.OpenForms.Count == 0) - return; - int start = 0; - var brdr = AppearanceManager.OpenForms.FirstOrDefault(x => x.IsSidePanel()) as WindowBorder; - if (brdr != null) + try { - brdr.X = 0; - brdr.Y = DesktopStart; - brdr.ResizeWindow(UIManager.Viewport.Width / 4, UIManager.Viewport.Height - LoadedSkin.DesktopPanelHeight); - start = UIManager.Viewport.Width / 4; + if (AppearanceManager.OpenForms.Count == 0) + return; + int start = 0; + var brdr = AppearanceManager.OpenForms.FirstOrDefault(x => x.IsSidePanel()) as WindowBorder; + if (brdr != null) + { + brdr.X = 0; + brdr.Y = DesktopStart; + brdr.ResizeWindow(UIManager.Viewport.Width / 4, UIManager.Viewport.Height - LoadedSkin.DesktopPanelHeight); + start = UIManager.Viewport.Width / 4; + } + + + var wb = (WindowBorder)AppearanceManager.OpenForms.FirstOrDefault(x => !x.IsSidePanel()); + if (wb != null) + { + wb.X = start; + wb.Y = DesktopStart; + wb.ResizeWindow(UIManager.Viewport.Width - start, UIManager.Viewport.Height - LoadedSkin.DesktopPanelHeight); + } } - - - var wb = (WindowBorder)AppearanceManager.OpenForms.FirstOrDefault(x => !x.IsSidePanel()); - if (wb != null) + catch(Exception ex) { - wb.X = start; - wb.Y = DesktopStart; - wb.ResizeWindow(UIManager.Viewport.Width - start, UIManager.Viewport.Height - LoadedSkin.DesktopPanelHeight); +#if DEBUG + Debug.WriteLine(" [WARN] Window management fucked up."); + Debug.WriteLine(" [WARN] " + ex.ToString()); +#endif } } } diff --git a/ShiftOS.Frontend/ShiftOS.Frontend.csproj b/ShiftOS.Frontend/ShiftOS.Frontend.csproj index 8decbc6..cb06b3d 100644 --- a/ShiftOS.Frontend/ShiftOS.Frontend.csproj +++ b/ShiftOS.Frontend/ShiftOS.Frontend.csproj @@ -80,6 +80,7 @@ + diff --git a/ShiftOS.Frontend/ShiftOS.cs b/ShiftOS.Frontend/ShiftOS.cs index 866f7f5..61a20fb 100644 --- a/ShiftOS.Frontend/ShiftOS.cs +++ b/ShiftOS.Frontend/ShiftOS.cs @@ -235,10 +235,11 @@ namespace ShiftOS.Frontend timeSinceLastPurge += gameTime.ElapsedGameTime.TotalSeconds; - if(timeSinceLastPurge > 30) + if(timeSinceLastPurge > 2) { GraphicsContext.StringCaches.Clear(); timeSinceLastPurge = 0; + GC.Collect(); } @@ -309,38 +310,21 @@ namespace ShiftOS.Frontend double fps = Math.Round(1 / gameTime.ElapsedGameTime.TotalSeconds); if (fps <= 20) color = Color.Red; - gfxContext.DrawString($@"ShiftOS 1.0 Beta 4 -Copyright (c) 2017 Michael VanOverbeek, Rylan Arbour, RogueAI, william341 -This is an unstable build. -FPS: {(fps)} -An FPS below 20 can cause glitches in keyboard and mouse handling. It is advised that if you are getting these -framerates, press CTRL+E to disable fancy effects, close any apps you are not using, and try running in windowed mode -or in a lower resolution. + gfxContext.DrawString($@"ShiftOS +======================= -If all else fails, you can set a breakpoint somewhere in the ShiftOS.Update() or ShiftOS.Draw() methods in the game's source -code and use Visual Studio's debugger to step through the code to find bottlenecks. +Copyright (c) 2017 ShiftOS Developers -If a method takes more than 30 milliseconds to complete, that is a sign that it is bottlenecking the game and may need to be -optimized. +Debug information - {fps} FPS -Try using the SkinTextures cache when rendering skin elements, and try using the GraphicsContext.DrawString() method when drawing -text. In this build, we are aware that this method causes bottlenecking, we are working on a caching system for fonts so we do not need to -use the System.Drawing.Graphics class to draw text. +CTRL+D: toggle debug menu +CTRL+E: toggle experimental effects (experimental effects enabled: {UIManager.ExperimentalEffects}) +Use the ""debug"" Terminal Command for engine debug commands. -UI render target count: {UIManager.TextureCaches.Count} -Skin texture caches: {UIManager.SkinTextures.Count} -Open windows (excluding dialog boxes): {AppearanceManager.OpenForms.Count} +Red text means low framerate, a low framerate could be a sign of CPU hogging code or a memory leak. -Experimental effects enabled: {UIManager.ExperimentalEffects} -Fullscreen: {UIManager.Fullscreen} -Game resolution: {graphicsDevice.PreferredBackBufferWidth}x{graphicsDevice.PreferredBackBufferHeight} -Mouse state: -X: {LastMouseState.X} -Y: {LastMouseState.Y} -Last left click MS: {mouseMS} - -", 0, 0, color, new System.Drawing.Font("Lucida Console", 9F, System.Drawing.FontStyle.Bold)); +Text cache: {GraphicsContext.StringCaches.Count}", 0, 0, color, new System.Drawing.Font("Lucida Console", 9F, System.Drawing.FontStyle.Bold)); } spriteBatch.End(); diff --git a/ShiftOS.Frontend/Stories/BeginTutorials.cs b/ShiftOS.Frontend/Stories/BeginTutorials.cs new file mode 100644 index 0000000..2356a1d --- /dev/null +++ b/ShiftOS.Frontend/Stories/BeginTutorials.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using ShiftOS.Engine; +using ShiftOS.Frontend.GraphicsSubsystem; +namespace ShiftOS.Frontend.Stories +{ + public static class BeginTutorials + { + [Story("tutorial1")] + public static void SystemTutorial() + { + while(AppearanceManager.OpenForms.Count > 0) + { + var frm = AppearanceManager.OpenForms[0]; + AppearanceManager.Close(frm.ParentWindow); + } + int position = 0; + Action keylistener = (e) => + { + switch (position) + { + case 0: + if(e.Key == Microsoft.Xna.Framework.Input.Keys.Enter) + { + position = 1; + } + break; + } + }; + + Action> commandListener = (text, args) => + { + Thread.Sleep(25); + switch (position) + { + case 1: + if(text == "help") + { + position++; + } + break; + } + }; + TerminalBackend.CommandFinished += commandListener; + + Engine.Story.Context.AutoComplete = false; + TerminalBackend.PrefixEnabled = false; + TerminalBackend.InStory = true; + var term = new Apps.Terminal(); + AppearanceManager.SetupWindow(term); + var ctl = term.TerminalControl; + ctl.KeyEvent += keylistener; + ctl.WriteLine(" System installation completed successfully."); + ctl.WriteLine(" Starting system tutorial..."); + Thread.Sleep(500); + ctl.WriteLine(""); + ctl.WriteLine(""); + ctl.WriteLine("Hey there, and welcome to ShiftOS. You are now running the system usage tutorial."); + ctl.WriteLine("This tutorial will guide you through the bare minimum basics of using ShiftOS."); + ctl.WriteLine("When you are ready, strike the [ENTER] key."); + ctl.WriteLine(""); + while (position == 0) + Thread.Sleep(10); + ctl.WriteLine("Enter keypress detected."); + Thread.Sleep(244); + ctl.WriteLine(""); + ctl.WriteLine(" Starting command shell on tty0."); + Thread.Sleep(100); + ctl.WriteLine("The below prompt is a Command Shell. This shell allows you to input commands into ShiftOS to tell it what to do."); + ctl.WriteLine("To get a list of usable ShiftOS commands, type the \"help\" command."); + TerminalBackend.InStory = false; + TerminalBackend.PrefixEnabled = true; + TerminalBackend.PrintPrompt(); + while (position == 1) + Thread.Sleep(10); + + ctl.WriteLine(""); + ctl.WriteLine("Any time you are unsure of a command to run, type the help command."); + ctl.WriteLine("Now, try typing the \"status\" command to see your current system status."); + } + } +} diff --git a/ShiftOS_TheReturn/TerminalBackend.cs b/ShiftOS_TheReturn/TerminalBackend.cs index dcc4625..4e7392e 100644 --- a/ShiftOS_TheReturn/TerminalBackend.cs +++ b/ShiftOS_TheReturn/TerminalBackend.cs @@ -231,11 +231,13 @@ namespace ShiftOS.Engine try { CommandHandler.Invoke(null, new[] { args }); + } catch { CommandHandler.Invoke(null, null); } + CommandFinished?.Invoke(Localization.Parse(this.CommandInfo.name), args); } } @@ -270,6 +272,8 @@ namespace ShiftOS.Engine } + public static event Action> CommandFinished; + public class MemoryTextWriter : System.IO.TextWriter { public override Encoding Encoding @@ -402,14 +406,12 @@ namespace ShiftOS.Engine { if (string.IsNullOrWhiteSpace(text)) return; - var tw = new MemoryTextWriter(); - Console.SetOut(tw); + var args = GetArgs(ref text); + var oargs = JsonConvert.DeserializeObject>(GetSentArgs(args)); try { - var args = GetArgs(ref text); bool commandWasClient = RunClient(text, args, isRemote); - if (!commandWasClient) { Console.WriteLine("Error: Command not found."); @@ -423,12 +425,6 @@ namespace ShiftOS.Engine PrefixEnabled = true; } - string buffer = tw.ToString(); - LastCommandBuffer = buffer; - Console.SetOut(new TerminalTextWriter()); - if(!isRemote) - Console.Write(buffer); - } ///