public async Task Setup() { src = CreateTestSource(messagesCount: 20); screenBuffer = new ScreenBuffer(changeNotification, 4.6); await screenBuffer.SetSources(new[] { src }, cancel); await screenBuffer.MoveToStreamsEnd(cancel); }
public void Render(IScreenBuffer screen, PlayerInfo player) { screen.Clear(); var center = screen.Dimensions.DivideBy(2).ToVector2(); var shortestSide = center.SmallestSide(); var radius = 0.9f * shortestSide; const int numSegments = 5; var radianOffset = MathHelper.TwoPi / numSegments / 2; // This fixes jittering var pixelOffset = new Vector2(0.5f, 0.5f); foreach (var segment in Enumerable.Range(0, numSegments)) { var rotation = Matrix.CreateRotationZ(segment * radianOffset + _angle); var direction = Vector2.Transform(Vector2.UnitX, rotation); var start = (center - direction * radius + pixelOffset).ToPoint(); var end = (center + direction * radius + pixelOffset).ToPoint(); _drawLine(screen, start, end, Color.Red); } }
public static (bool shouldDraw, Point p0, Point p1) ClipToScreen( IScreenBuffer buffer, Point p0, Point p1) { OutCode outCode0 = ComputeOutCode(p0, buffer.Dimensions); OutCode outCode1 = ComputeOutCode(p1, buffer.Dimensions); bool accept = false; while (true) { if ((outCode0 | outCode1) == OutCode.Inside) { accept = true; break; } if ((outCode0 & outCode1) != OutCode.Inside) { break; } int x = 0; int y = 0; OutCode outCodeOut = (outCode0 != OutCode.Inside) ? outCode0 : outCode1; if ((outCodeOut & OutCode.Top) == OutCode.Top) { x = (int)(p0.X + (p1.X - p0.X) * (buffer.Dimensions.Y - p0.Y) / ((double)p1.Y - p0.Y)); y = buffer.Dimensions.Y; } else if ((outCodeOut & OutCode.Bottom) == OutCode.Bottom) { x = (int)(p0.X + (p1.X - p0.X) * -p0.Y / ((double)p1.Y - p0.Y)); y = 0; } else if ((outCodeOut & OutCode.Right) == OutCode.Right) { y = (int)(p0.Y + (p1.Y - p0.Y) * (buffer.Dimensions.X - p0.X) / ((double)p1.X - p0.X)); x = buffer.Dimensions.X; } else if ((outCodeOut & OutCode.Left) == OutCode.Left) { y = (int)(p0.Y + (p1.Y - p0.Y) * -p0.X / ((double)p1.X - p0.X)); x = 0; } if (outCodeOut == outCode0) { p0 = new Point(x, y); outCode0 = ComputeOutCode(p0, buffer.Dimensions); } else { p1 = new Point(x, y); outCode1 = ComputeOutCode(p1, buffer.Dimensions); } } return(accept, p0, p1); }
public async Task Setup() { src1 = CreateTestSource(messagesCount: 10, linesPerMessage: 3, messagesPrefix: "a"); src2 = CreateTestSource(messagesCount: 10, linesPerMessage: 2, messagesPrefix: "b"); screenBuffer = new ScreenBuffer(changeNotification, 4.4); await screenBuffer.SetSources(new[] { src1, src2 }, cancel); }
private static void PlotLineHigh(IScreenBuffer buffer, int x0, int y0, int x1, int y1, Color color) { int dx = x1 - x0; int dy = y1 - y0; int xi = 1; if (dx < 0) { xi = -1; dx = -dx; } int D = 2 * dx - dy; int x = x0; for (int y = y0; y <= y1; y++) { buffer.DrawPixel(x, y, color); if (D > 0) { x = x + xi; D = D - 2 * dy; } D = D + 2 * dx; } }
public static void PlotLine(this IScreenBuffer buffer, int x0, int y0, int x1, int y1, Color color) { if (Abs(y1 - y0) < Abs(x1 - x0)) { if (x0 > x1) { PlotLineLow(buffer, x1, y1, x0, y0, color); } else { PlotLineLow(buffer, x0, y0, x1, y1, color); } } else { if (y0 > y1) { PlotLineHigh(buffer, x1, y1, x0, y0, color); } else { PlotLineHigh(buffer, x0, y0, x1, y1, color); } } }
private static void PlotLineLow(IScreenBuffer buffer, int x0, int y0, int x1, int y1, Color color) { int dx = x1 - x0; int dy = y1 - y0; int yi = 1; if (dy < 0) { yi = -1; dy = -dy; } int D = 2 * dy - dx; int y = y0; for (int x = x0; x <= x1; x++) { buffer.DrawPixel(x, y, color); if (D > 0) { y = y + yi; D = D - 2 * dx; } D = D + 2 * dy; } }
public async Task Setup() { src = CreateTestSource(messagesCount: 10, linesPerMessage: 2, rawLinesPerMessage: 3); screenBuffer = new ScreenBuffer(changeNotification, 3.3); await screenBuffer.SetSources(new[] { src }, cancel); await screenBuffer.MoveToStreamsBegin(cancel); }
public async Task Setup() { src1 = CreateTestSource(messagesCount: 20, messagesPrefix: "a:"); src2 = CreateTestSource(messagesCount: 18, timestampShiftMillis: 7, messagesPrefix: "b:"); screenBuffer = new ScreenBuffer(changeNotification, 6.3); await screenBuffer.SetSources(new[] { src1, src2 }, cancel); }
/// <summary> /// Make a screen snapshot of the current state of the screenbuffer. /// </summary> public ScreenSnapShot(IScreenBuffer fromScreen) { Buffer = fromScreen.GetBuffer(); TopRow = fromScreen.TopRow; CursorColumn = fromScreen.CursorColumnShow; CursorRow = fromScreen.CursorRowShow; RowCount = fromScreen.RowCount; }
static void VerifyMessages(IScreenBuffer screenBuffer, string expected, double? expectedTopLineScroll = null, bool verifyRaw = false) { var actual = string.Join("\r\n", screenBuffer.Messages.Select(m => (verifyRaw ? m.Message.RawTextAsMultilineText : m.Message.TextAsMultilineText).GetNthTextLine(m.TextLineIndex))); Assert.AreEqual(StringUtils.NormalizeLinebreakes(expected.Replace("\t", "")), actual); if (expectedTopLineScroll != null) Assert.AreEqual(expectedTopLineScroll.Value, screenBuffer.TopLineScrollValue, 1e-3); }
public void Render(IScreenBuffer screen, PlayerInfo player) { screen.Clear(); // The screen has an origin in the top left. Positive Y is DOWN // Maps have an origin in the bottom left. Positive Y is UP var screenDimensionsV = screen.Dimensions.ToVector2(); var desiredMapScreenBounds = screenDimensionsV * DefaultMapToScreenRatio; var gameToScreenFactor = Math.Min(desiredMapScreenBounds.X / _map.Area.X, desiredMapScreenBounds.Y / _map.Area.Y); var screenAreaInMapCoords = screenDimensionsV / gameToScreenFactor; var mapCenteringOffset = (screenAreaInMapCoords - _map.Area) / 2 - _map.BottomLeftCorner; // Transform all vertices for (int v = 0; v < _map.Vertices.Length; v++) { _verticesInScreenCoords[v] = ToScreenCoords(_map.Vertices[v]); } Point ToScreenCoords(Vector2 worldCoordinate) { var shiftedWorldCoordinate = worldCoordinate + mapCenteringOffset; // This fixes jittering var pixelOffset = new Vector2(0.5f, 0.5f); return(((shiftedWorldCoordinate * gameToScreenFactor) + pixelOffset).ToPoint().InvertY(screen.Height)); } void DrawLineFromVertices(int v1, int v2, Color c) => DrawLineFromScreenCoordinates(_verticesInScreenCoords[v1], _verticesInScreenCoords[v2], c); void DrawLineFromWorldCoordinates(Vector2 wc1, Vector2 wc2, Color c) { var sc1 = ToScreenCoords(wc1); var sc2 = ToScreenCoords(wc2); DrawLineFromScreenCoordinates(sc1, sc2, c); } void DrawLineFromScreenCoordinates(Point sc1, Point sc2, Color c) { var result = LineClipping.ClipToScreen(screen, sc1, sc2); if (result.shouldDraw) { screen.PlotLineSmooth(result.p0, result.p1, c); } } foreach (var lineDef in _map.Map.LineDefs.Take((int)_linesToDraw)) { ref Vector2 vertex1 = ref _map.Vertices[lineDef.V1]; ref Vector2 vertex2 = ref _map.Vertices[lineDef.V2];
internal int NotifyOfScreenResize(IScreenBuffer sb) { WindowRect = new Rect(WindowRect.xMin, WindowRect.yMin, sb.ColumnCount * CHARSIZE + 65, sb.RowCount * CHARSIZE + 100); foreach (TelnetSingletonServer telnet in telnets) { ResizeAndRepaintTelnet(telnet, sb.ColumnCount, sb.RowCount, false); } return(0); }
public void Render(IScreenBuffer screen, PlayerInfo player) { screen.Clear(); Interpreter.Settings = player.CameraSettings; void DrawLineFromScreenCoordinates(Point sc1, Point sc2, Color c) { var result = LineClipping.ClipToScreen(screen, sc1, sc2); if (result.shouldDraw) { _drawLine(screen, result.p0, result.p1, c); } } foreach (SectorInfo sector in _map.Sectors) { foreach (Line line in sector.Lines) { Vector3 cameraPosition = new Vector3(player.Position, player.VerticalPosition + player.ViewHeight); _camera.Center = cameraPosition; _camera.RotationInRadians = player.Angle - MathHelper.PiOver2; Vector3 topLeftConverted = _camera.WorldToPerspective(new Vector3(line.Vertex1.X, line.Vertex1.Y, sector.Info.HeightCeiling)); Vector3 topRightConverted = _camera.WorldToPerspective(new Vector3(line.Vertex2.X, line.Vertex2.Y, sector.Info.HeightCeiling)); Vector3 bottomLeftConverted = _camera.WorldToPerspective(new Vector3(line.Vertex1.X, line.Vertex1.Y, sector.Info.HeightFloor)); Vector3 bottomRightConverted = _camera.WorldToPerspective(new Vector3(line.Vertex2.X, line.Vertex2.Y, sector.Info.HeightFloor)); var topLineResult = Interpreter.ConvertWorldLineToScreenPoints(screen, topLeftConverted, topRightConverted); if (topLineResult.shouldDraw) { DrawLineFromScreenCoordinates(topLineResult.p1, topLineResult.p2, Color.Red); } var bottomLineResult = Interpreter.ConvertWorldLineToScreenPoints(screen, bottomLeftConverted, bottomRightConverted); if (bottomLineResult.shouldDraw) { DrawLineFromScreenCoordinates(bottomLineResult.p1, bottomLineResult.p2, Color.Red); } var leftLineResult = Interpreter.ConvertWorldLineToScreenPoints(screen, topLeftConverted, bottomLeftConverted); if (leftLineResult.shouldDraw) { DrawLineFromScreenCoordinates(leftLineResult.p1, leftLineResult.p2, Color.Red); } var rightLineResult = Interpreter.ConvertWorldLineToScreenPoints(screen, topRightConverted, bottomRightConverted); if (rightLineResult.shouldDraw) { DrawLineFromScreenCoordinates(rightLineResult.p1, rightLineResult.p2, Color.Red); } } } }
private static void PlotCircleSegments(IScreenBuffer buffer, int xc, int yc, int x, int y, Color color) { buffer.DrawPixel(xc + x, yc + y, color); buffer.DrawPixel(xc - x, yc + y, color); buffer.DrawPixel(xc + x, yc - y, color); buffer.DrawPixel(xc - x, yc - y, color); buffer.DrawPixel(xc + y, yc + x, color); buffer.DrawPixel(xc - y, yc + x, color); buffer.DrawPixel(xc + y, yc - x, color); buffer.DrawPixel(xc - y, yc - x, color); }
=> WindowRectangle = GetConsoleRect(); // fill the entire console with the root "desktop" public override void Draw(IScreenBuffer screenBuffer) { base.Draw(screenBuffer); var clientRect = ClientRectangle; var y = 0; screenBuffer.Draw(clientRect.X, clientRect.Y + y++, "F1 - List animals"); screenBuffer.Draw(clientRect.X, clientRect.Y + y++, "F2 - Advance week"); screenBuffer.Draw(clientRect.X, clientRect.Y + y++, "F3 - Show this weeks food requirement"); screenBuffer.Draw(clientRect.X, clientRect.Y + y++, "F4 - Wipe and restart database"); }
public override void Draw(IScreenBuffer screenBuffer) { base.Draw(screenBuffer); var rc = ClientRectangle; var text1 = "Do you want to reset database?"; var text2 = "Press Y for yes or Escape to cancel."; screenBuffer.Draw(rc.X + rc.Width / 2 - text1.Length / 2, rc.Y, text1); screenBuffer.Draw(rc.X + rc.Width / 2 - text2.Length / 2, rc.Y + 1, text2); }
/// <summary> /// A factory that constructs an empty screen buffer of a correct size for the fromScreen /// </summary> /// <param name="fromScreen">The screen - only used to determine the needed width/height</param> /// <returns>An empty snapshot buffer</returns> public static ScreenSnapShot EmptyScreen(IScreenBuffer fromScreen) { ScreenSnapShot newThing = new ScreenSnapShot(); newThing.TopRow = fromScreen.TopRow; newThing.CursorColumn = fromScreen.CursorColumnShow; newThing.CursorRow = fromScreen.CursorRowShow; newThing.RowCount = fromScreen.RowCount; newThing.Buffer = new List<IScreenBufferLine>(); for (int i = 0; i < newThing.RowCount ; ++i) newThing.Buffer.Add(new ScreenBufferLine(fromScreen.ColumnCount)); return newThing; }
public async Task ShouldLoadNothingIsViewSizeIsZero() { src = CreateTestSource(messagesCount: 20); screenBuffer = new ScreenBuffer(changeNotification, 0); await screenBuffer.SetSources(new[] { src }, cancel); await screenBuffer.MoveToBookmark( bmks.CreateBookmark(src.messages.Items[5], 0), BookmarkLookupMode.ExactMatch, cancel); Assert.AreEqual(0, screenBuffer.Messages.Count); await screenBuffer.MoveToStreamsEnd(cancel); Assert.AreEqual(0, screenBuffer.Messages.Count); }
public void Draw(IScreenBuffer screenBuffer, Point location) { screenBuffer.Draw(location.X, location.Y, Title, ConsoleColor.Magenta); screenBuffer.EnableUnderline = true; screenBuffer.Draw( location.X, location.Y + 1, Value.ToString().PadRight(MaxLength, ' '), ConsoleColor.Gray); screenBuffer.EnableUnderline = false; }
public async Task CanLoadExactMessageWhenViewIsLargerThanLogg_WithScrollingToTopMiddleOfScreen() { src = CreateTestSource(messagesCount: 2, linesPerMessage: 3); screenBuffer = new ScreenBuffer(changeNotification, 8.2); await screenBuffer.SetSources(new[] { src }, cancel); Assert.IsTrue(await screenBuffer.MoveToBookmark(bmks.CreateBookmark(src.messages.Items[1], 2), BookmarkLookupMode.ExactMatch | BookmarkLookupMode.MoveBookmarkToMiddleOfScreen, cancel)); VerifyMessages(screenBuffer, @"0-ln_0 0-ln_1 0-ln_2 1-ln_0 1-ln_1 1-ln_2", 0); }
public async Task Setup() { src = CreateTestSource(messagesCount: 5, linesPerMessage: 10); screenBuffer = new ScreenBuffer(changeNotification, 6.8); await screenBuffer.SetSources(new[] { src }, cancel); await screenBuffer.MoveToStreamsEnd(cancel); VerifyMessages(screenBuffer, @"4-ln_3 4-ln_4 4-ln_5 4-ln_6 4-ln_7 4-ln_8 4-ln_9", 0.2); }
public async Task Setup() { src = CreateTestSource(messagesCount: 20); screenBuffer = new ScreenBuffer(changeNotification, 6.8); await screenBuffer.SetSources(new[] { src }, cancel); await screenBuffer.MoveToStreamsEnd(cancel); VerifyMessages(screenBuffer, @"13-ln_0 14-ln_0 15-ln_0 16-ln_0 17-ln_0 18-ln_0 19-ln_0", 0.2); }
/// <summary> /// A factory that constructs an empty screen buffer of a correct size for the fromScreen /// </summary> /// <param name="fromScreen">The screen - only used to determine the needed width/height</param> /// <returns>An empty snapshot buffer</returns> public static ScreenSnapShot EmptyScreen(IScreenBuffer fromScreen) { ScreenSnapShot newThing = new ScreenSnapShot(); newThing.TopRow = fromScreen.TopRow; newThing.CursorColumn = fromScreen.CursorColumnShow; newThing.CursorRow = fromScreen.CursorRowShow; newThing.RowCount = fromScreen.RowCount; newThing.Buffer = new List <IScreenBufferLine>(); for (int i = 0; i < newThing.RowCount; ++i) { newThing.Buffer.Add(new ScreenBufferLine(fromScreen.ColumnCount)); } return(newThing); }
/// <summary>Whenever the terminal resizes, resize the progress bar,</summary> /// <param name="sb">The method operates on self (this), and the parameter sb would /// be unnecessary if it wasn't required by AddResizeNotifyer().</parm> private int CreateProgressBarSubBuffer(IScreenBuffer sb) { if (progressBarSubBuffer == null) { progressBarSubBuffer = new SubBuffer(); progressBarSubBuffer.WillTruncate = true; AddSubBuffer(progressBarSubBuffer); } progressBarSubBuffer.SetSize(3, ColumnCount); progressBarSubBuffer.Fixed = true; progressBarSubBuffer.PositionRow = RowCount - progressBarSubBuffer.RowCount; var separator = new string('-', progressBarSubBuffer.ColumnCount); progressBarSubBuffer.Buffer[0].ArrayCopyFrom(separator.ToCharArray(), 0, 0); return(0); }
public override void Draw(IScreenBuffer screenBuffer) { base.Draw(screenBuffer); var y = ClientRectangle.Y; foreach (var component in _components) { component.Draw(screenBuffer, new Point(ClientRectangle.X, y)); if (component == _components[_focusedComponentIndex]) { screenBuffer.Draw(ClientRectangle.X + component.Value.Length, y + 1, ' ', ConsoleColor.Gray, ConsoleColor.Gray); } y += 3; } }
public SelectionManager( IView view, IScreenBuffer screenBuffer, LJTraceSource tracer, IPresentationDataAccess presentationDataAccess, IClipboardAccess clipboard, IScreenBufferFactory screenBufferFactory, IBookmarksFactory bookmarksFactory ) { this.view = view; this.screenBuffer = screenBuffer; this.clipboard = clipboard; this.presentationDataAccess = presentationDataAccess; this.tracer = tracer; this.screenBufferFactory = screenBufferFactory; this.bookmarksFactory = bookmarksFactory; }
public (bool shouldDraw, Point p1, Point p2) ConvertWorldLineToScreenPoints( IScreenBuffer buffer, Vector3 vector1, Vector3 vector2) { var point1Result = ConvertWorldPointToScreenDegrees(vector1); var point2Result = ConvertWorldPointToScreenDegrees(vector2); var point1HorizontalDegrees = point1Result.horizontalDegrees; var point1VerticalDegrees = point1Result.verticalDegrees; var point2HorizontalDegrees = point2Result.horizontalDegrees; var point2VerticalDegrees = point2Result.verticalDegrees; if (point1Result.isFacing && point1Result.isInView && !point2Result.isInView && !point2Result.isFacing && vector2.X < 0) { point2HorizontalDegrees += 360; } if (point2Result.isFacing && point2Result.isInView && !point1Result.isInView && !point1Result.isFacing && vector1.X > 0) { point1HorizontalDegrees -= 360; } var point1 = new Point( (int)(((point1HorizontalDegrees / _settings.FieldOfView) + 0.5f) * buffer.Width), (int)(((-point1VerticalDegrees / _settings.FieldOfView) + 0.5f) * buffer.Height)); var point2 = new Point( (int)(((point2HorizontalDegrees / _settings.FieldOfView) + 0.5f) * buffer.Width), (int)(((-point2VerticalDegrees / _settings.FieldOfView) + 0.5f) * buffer.Height)); float cameraDistanceTo1 = vector1.Length(); float cameraDistanceTo2 = vector2.Length(); bool isCloseEnough = Math.Min(cameraDistanceTo1, cameraDistanceTo2) < _settings.MaxClippingDistance; bool isFarEnough = Math.Min(cameraDistanceTo1, cameraDistanceTo2) > _settings.MinClippingDistance; var showBoth = isCloseEnough && isFarEnough && ( point1Result.isInView || point2Result.isInView || (point1Result.isFacing && point2Result.isFacing)); return(showBoth, point1, point2); }
public async Task CanLoadBookmarkWhenManyMessagesShareTheTimestamp() { src1 = CreateTestSource(messagesCount: 20, linesPerMessage: 1, messagesPrefix: "a", messagesPerTimestamp: 10); src2 = CreateTestSource(messagesCount: 20, linesPerMessage: 1, messagesPrefix: "b", messagesPerTimestamp: 10); screenBuffer = new ScreenBuffer(changeNotification, 3); await screenBuffer.SetSources(new[] { src1, src2 }, cancel); await screenBuffer.MoveToBookmark( bmks.CreateBookmark(src1.messages.Items[5], 0), BookmarkLookupMode.ExactMatch, cancel); VerifyMessages(screenBuffer, @"a5-ln_0 a6-ln_0 a7-ln_0", 0); await screenBuffer.MoveToBookmark( bmks.CreateBookmark(src2.messages.Items[0], 0), BookmarkLookupMode.ExactMatch | BookmarkLookupMode.MoveBookmarkToMiddleOfScreen, cancel); VerifyMessages(screenBuffer, @"a9-ln_0 b0-ln_0 b1-ln_0", 0); }
public static void PlotCircle(this IScreenBuffer buffer, int xCenter, int yCenter, int radius, Color color) { int x = 0, y = radius; int d = 3 - 2 * radius; PlotCircleSegments(buffer, xCenter, yCenter, x, y, color); while (y >= x) { x++; if (d > 0) { y--; d = d + 4 * (x - y) + 10; } else { d = d + 4 * x + 6; } PlotCircleSegments(buffer, xCenter, yCenter, x, y, color); } }
public override void Draw(IScreenBuffer screenBuffer) { base.Draw(screenBuffer); if (_database == null) { return; } screenBuffer.Draw(ClientRectangle.X, ClientRectangle.Y, "Species"); screenBuffer.Draw(ClientRectangle.X + 10, ClientRectangle.Y, "Name"); screenBuffer.Draw(ClientRectangle.X + 30, ClientRectangle.Y, "Age"); int index = 0; int y = ClientRectangle.Y + 2; foreach (var animal in _database.Animals) { var line = $"{animal.Species.PadRight(10)}{animal.Name.Clip(19).PadRight(20)}{animal.Age.ToBirthdayFormat()}"; var foreground = ConsoleColor.Gray; var background = ConsoleColor.Black; if (index == _selectedIndex) { background = ConsoleColor.Blue; } screenBuffer.Draw(ClientRectangle.X, y, line, foreground, background); if (++y >= ClientRectangle.Bottom) { break; } ++index; } }
internal int NotifyOfScreenResize(IScreenBuffer sb) { WindowRect = new Rect(WindowRect.xMin, WindowRect.yMin, sb.ColumnCount*sb.CharacterPixelWidth + 65, sb.RowCount*sb.CharacterPixelHeight + 100); foreach (TelnetSingletonServer telnet in telnets) { ResizeAndRepaintTelnet(telnet, sb.ColumnCount, sb.RowCount, false); } return 0; }
/// <summary> /// The default behavior is to resize the subbuffer's width to match the parent /// screenbuffer's width, but to leave the height alone as-is. All the subbuffers /// in kOS as of this writing need that behavior (they're used to edit the command line). /// The way is being left open for other subclasses of subbuffer to override this /// method later. (i.e. you might want a subbuffer of fixed size that won't change /// when the parent resizes. If we start using subbuffers to enable curses-like /// overlay zones in script displays we'd want that.) /// </summary> /// <param name="sb">the parent screen buffer that is being resized</param> /// <returns>number of lines the parent should probably be shifted down because the subbuffer is now more lines.</returns> public virtual int NotifyOfParentResize(IScreenBuffer sb) { ColumnCount = sb.ColumnCount; return ResizeBuffer(); }