/// <summary> /// Creates a <see cref="ColoredString"/> object from an existing string with the specified foreground and background, setting the ignore properties if needed. /// </summary> /// <param name="value">The current string.</param> /// <param name="foreground">The foreground color. If null, <see cref="ColoredString.IgnoreForeground"/> will be set.</param> /// <param name="background">The background color. If null, <see cref="ColoredString.IgnoreBackground"/> will be set.</param> /// <param name="spriteEffect">The background color. If null, <see cref="ColoredString.IgnoreEffect"/> will be set.</param> /// <returns>A <see cref="ColoredString"/> object instace.</returns> public static ColoredString CreateColored(this string value, Color?foreground = null, Color?background = null) { var stacks = new ParseCommandStacks(); if (foreground.HasValue) { stacks.AddSafe(new ParseCommandRecolor() { R = foreground.Value.R, G = foreground.Value.G, B = foreground.Value.B, A = foreground.Value.A, CommandType = CommandTypes.Foreground }); } if (background.HasValue) { stacks.AddSafe(new ParseCommandRecolor() { R = background.Value.R, G = background.Value.G, B = background.Value.B, A = background.Value.A, CommandType = CommandTypes.Background }); } ColoredString newString = ColoredString.Parse(value, initialBehaviors: stacks); if (!foreground.HasValue) { newString.IgnoreForeground = true; } if (!background.HasValue) { newString.IgnoreBackground = true; } return(newString); }
/// <summary> /// Draws the string on the console at the specified location with the specified settings. /// </summary> /// <param name="x">X location of the text.</param> /// <param name="y">Y location of the text.</param> /// <param name="text">The string to display.</param> /// <param name="foreground">Sets the foreground of all characters in the text.</param> /// <param name="background">Sets the background of all characters in the text.</param> /// <param name="spriteEffect">The sprite effect to set on the cell.</param> public void Print(int x, int y, string text, Color?foreground = null, Color?background = null) { if (String.IsNullOrEmpty(text)) { return; } if (x >= textSurface.Width || x < 0 || y >= textSurface.Height || y < 0) { throw new Exception("X,Y is out of range for Print"); } int index = y * textSurface.Width + x; if (!UsePrintProcessor) { int total = index + text.Length > textSurface.Cells.Length ? textSurface.Cells.Length - index : index + text.Length; int charIndex = 0; for (; index < total; index++) { textSurface.Cells[index].GlyphIndex = text[charIndex]; if (background.HasValue) { textSurface.Cells[index].Background = background.Value; } if (foreground.HasValue) { textSurface.Cells[index].Foreground = foreground.Value; } charIndex++; } } else { var stacks = new ParseCommandStacks(); if (foreground.HasValue) { stacks.AddSafe(new ParseCommandRecolor() { R = foreground.Value.R, G = foreground.Value.G, B = foreground.Value.B, A = foreground.Value.A, CommandType = CommandTypes.Foreground }); } if (background.HasValue) { stacks.AddSafe(new ParseCommandRecolor() { R = background.Value.R, G = background.Value.G, B = background.Value.B, A = background.Value.A, CommandType = CommandTypes.Background }); } PrintNoCheck(index, ColoredString.Parse(text, index, textSurface, this, stacks)); } }
/// <summary> /// Creates a new instance of the ColoredString class with the specified string value, foreground and background colors, and a cell effect. /// </summary> /// <param name="value">The backing string.</param> /// <param name="foreground">The foreground color for each character.</param> /// <param name="background">The background color for each character.</param> /// <param name="spriteEffect">The sprite effects for each character.</param> public ColoredString(string value, Color foreground, Color background) { var stacks = new ParseCommandStacks(); stacks.AddSafe(new ParseCommandRecolor() { R = foreground.R, G = foreground.G, B = foreground.B, A = foreground.A, CommandType = CommandTypes.Foreground }); stacks.AddSafe(new ParseCommandRecolor() { R = background.R, G = background.G, B = background.B, A = background.A, CommandType = CommandTypes.Background }); _characters = ColoredString.Parse(value, initialBehaviors: stacks)._characters; }
/// <summary> /// Draws the string on the console at the specified location with the specified foreground and background color, wrapping if needed. /// </summary> /// <param name="x">X location of the text.</param> /// <param name="y">Y location of the text.</param> /// <param name="text">The string to display.</param> /// <param name="foreground">Sets the foreground of all characters in the text.</param> /// <param name="background">Sets the background of all characters in the text.</param> public void Print(int x, int y, string text, Color foreground, Color background) { if (String.IsNullOrEmpty(text)) { return; } if (x >= textSurface.Width || x < 0 || y >= textSurface.Height || y < 0) { throw new Exception("X,Y is out of range for Print"); } int index = y * textSurface.Width + x; if (!UsePrintProcessor) { int total = index + text.Length > textSurface.Cells.Length ? textSurface.Cells.Length - index : index + text.Length; int charIndex = 0; for (; index < total; index++) { textSurface.Cells[index].Glyph = text[charIndex]; textSurface.Cells[index].Background = background; textSurface.Cells[index].Foreground = foreground; charIndex++; } } else { var behaviorFore = new ParseCommandRecolor() { R = foreground.R, G = foreground.G, B = foreground.B, A = foreground.A, CommandType = CommandTypes.Foreground }; var behaviorBack = new ParseCommandRecolor() { R = background.R, G = background.G, B = background.B, A = background.A, CommandType = CommandTypes.Background }; var stacks = new ParseCommandStacks(); stacks.AddSafe(behaviorFore); stacks.AddSafe(behaviorBack); PrintNoCheck(index, ColoredString.Parse(text, index, textSurface, this, stacks)); } textSurface.IsDirty = true; }
/// <summary> /// Creates a colored string by parsing commands embedded in the string. /// </summary> /// <param name="value">The string to parse.</param> /// <param name="surfaceIndex">Index of where this string will be printed.</param> /// <param name="surface">The surface the string will be printed to.</param> /// <param name="initialBehaviors">Any initial defaults.</param> /// <returns></returns> public static ColoredString Parse(string value, int surfaceIndex = -1, CellSurface surface = null, ParseCommandStacks initialBehaviors = null) { ParseCommandStacks commandStacks = initialBehaviors ?? new ParseCommandStacks(); List <ColoredGlyph> glyphs = new List <ColoredGlyph>(value.Length); for (int i = 0; i < value.Length; i++) { ColoredGlyph[] existingGlyphs = glyphs.ToArray(); if (value[i] == '`' && i + 1 < value.Length && value[i + 1] == '[') { continue; } if (value[i] == '[' && (i == 0 || value[i - 1] != '`')) { try { if (i + 4 < value.Length && value[i + 1] == 'c' && value[i + 2] == ':' && value.IndexOf(']', i + 2) != -1) { int commandExitIndex = value.IndexOf(']', i + 2); string command = value.Substring(i + 3, commandExitIndex - (i + 3)); string commandParams = ""; if (command.Contains(" ")) { string[] commandSections = command.Split(new char[] { ' ' }, 2); command = commandSections[0].ToLower(); commandParams = commandSections[1]; } // Check for custom command ParseCommandBase commandObject = CustomProcessor?.Invoke(command, commandParams, existingGlyphs, surface, commandStacks); // No custom command found, run build in ones if (commandObject == null) { switch (command) { case "recolor": case "r": commandObject = new ParseCommandRecolor(commandParams); break; case "mirror": case "m": commandObject = new ParseCommandMirror(commandParams); break; case "undo": case "u": commandObject = new ParseCommandUndo(commandParams, commandStacks); break; case "grad": case "g": commandObject = new ParseCommandGradient(commandParams); break; case "blink": case "b": commandObject = new ParseCommandBlink(commandParams, existingGlyphs, commandStacks, surface); break; case "sglyph": case "sg": commandObject = new ParseCommandSetGlyph(commandParams); break; case "ceffect": case "ce": commandObject = new ParseCommandClearEffect(commandParams, commandStacks); break; default: break; } } if (commandObject != null && commandObject.CommandType != CommandTypes.Invalid) { commandStacks.AddSafe(commandObject); i = commandExitIndex; continue; } } } catch (Exception e1) { #if DEBUG throw e1; #endif } } int fixedSurfaceIndex; if (surfaceIndex == -1 || surface == null) { fixedSurfaceIndex = -1; } else { fixedSurfaceIndex = i + surfaceIndex < surface.Cells.Length ? i + surfaceIndex : -1; } ColoredGlyph newGlyph; if (fixedSurfaceIndex != -1) { newGlyph = new ColoredGlyph(surface[i + surfaceIndex]) { Glyph = value[i] }; } else { newGlyph = new ColoredGlyph(new Cell()) { Glyph = value[i] }; } // Foreground if (commandStacks.Foreground.Count != 0) { commandStacks.Foreground.Peek().Build(ref newGlyph, existingGlyphs, fixedSurfaceIndex, surface, ref i, value, commandStacks); } // Background if (commandStacks.Background.Count != 0) { commandStacks.Background.Peek().Build(ref newGlyph, existingGlyphs, fixedSurfaceIndex, surface, ref i, value, commandStacks); } if (commandStacks.Glyph.Count != 0) { commandStacks.Glyph.Peek().Build(ref newGlyph, existingGlyphs, fixedSurfaceIndex, surface, ref i, value, commandStacks); } // SpriteEffect if (commandStacks.Mirror.Count != 0) { commandStacks.Mirror.Peek().Build(ref newGlyph, existingGlyphs, fixedSurfaceIndex, surface, ref i, value, commandStacks); } // Effect if (commandStacks.Effect.Count != 0) { commandStacks.Effect.Peek().Build(ref newGlyph, existingGlyphs, fixedSurfaceIndex, surface, ref i, value, commandStacks); } glyphs.Add(newGlyph); } return(new ColoredString(glyphs.ToArray()) { IgnoreEffect = !commandStacks.TurnOnEffects }); }