Add ANSI charset to term

This commit is contained in:
Alessandro Proto 2023-02-20 22:18:42 +01:00
parent aee3434b44
commit af6b885751
6 changed files with 129 additions and 30 deletions

BIN
Capy64/Assets/charset.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View file

@ -13,6 +13,9 @@
<PackageLicenseFile>LICENSE</PackageLicenseFile>
</PropertyGroup>
<ItemGroup>
<Content Include="Assets\charset.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\default.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@ -58,4 +61,7 @@
<ItemGroup>
<EditorConfigFiles Remove="C:\Users\Alex\source\repos\Capy64\Capy64\Capy64\.editorconfig" />
</ItemGroup>
<ItemGroup>
<None Remove="Assets\charset.png" />
</ItemGroup>
</Project>

79
Capy64/Core/Charset.cs Normal file
View file

@ -0,0 +1,79 @@
// This file is part of Capy64 - https://github.com/Ale32bit/Capy64
// Copyright 2023 Alessandro "AlexDevs" Proto
//
// Licensed under the Apache License', Version 2.0 (the "License").
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing', software
// distributed under the License is distributed on an "AS IS" BASIS',
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND', either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using Capy64.API;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Collections.Generic;
namespace Capy64.Core;
public class Charset : IComponent
{
public static int CharWidth => 6;
public static int CharHeight => 12;
public static readonly char[] Codepoints = new char[]
{
'\u0000', '\u263A', '\u263B', '\u2665', '\u2666', '\u2663', '\u2660', '\u2022', '\u25D8', '\u25CB', '\u25D9', '\u2642', '\u2640', '\u266A', '\u266B', '\u263C',
'\u25BA', '\u25C4', '\u2195', '\u203C', '\u00B6', '\u00A7', '\u25AC', '\u21A8', '\u2191', '\u2193', '\u2192', '\u2190', '\u221F', '\u2194', '\u25B2', '\u25BC',
'\u0020', '\u0021', '\u0022', '\u0023', '\u0024', '\u0025', '\u0026', '\u0027', '\u0028', '\u0029', '\u002A', '\u002B', '\u002C', '\u002D', '\u002E', '\u002F',
'\u0030', '\u0031', '\u0032', '\u0033', '\u0034', '\u0035', '\u0036', '\u0037', '\u0038', '\u0039', '\u003A', '\u003B', '\u003C', '\u003D', '\u003E', '\u003F',
'\u0040', '\u0041', '\u0042', '\u0043', '\u0044', '\u0045', '\u0046', '\u0047', '\u0048', '\u0049', '\u004A', '\u004B', '\u004C', '\u004D', '\u004E', '\u004F',
'\u0050', '\u0051', '\u0052', '\u0053', '\u0054', '\u0055', '\u0056', '\u0057', '\u0058', '\u0059', '\u005A', '\u005B', '\u005C', '\u005D', '\u005E', '\u005F',
'\u0060', '\u0061', '\u0062', '\u0063', '\u0064', '\u0065', '\u0066', '\u0067', '\u0068', '\u0069', '\u006A', '\u006B', '\u006C', '\u006D', '\u006E', '\u006F',
'\u0070', '\u0071', '\u0072', '\u0073', '\u0074', '\u0075', '\u0076', '\u0077', '\u0078', '\u0079', '\u007A', '\u007B', '\u007C', '\u007D', '\u007E', '\u2302',
'\u00C7', '\u00FC', '\u00E9', '\u00E2', '\u00E4', '\u00E0', '\u00E5', '\u00E7', '\u00EA', '\u00EB', '\u00E8', '\u00EF', '\u00EE', '\u00EC', '\u00C4', '\u00C5',
'\u00C9', '\u00E6', '\u00C6', '\u00F4', '\u00F6', '\u00F2', '\u00FB', '\u00F9', '\u00FF', '\u00D6', '\u00DC', '\u00A2', '\u00A3', '\u00A5', '\u20A7', '\u0192',
'\u00E1', '\u00ED', '\u00F3', '\u00FA', '\u00F1', '\u00D1', '\u00AA', '\u00BA', '\u00BF', '\u2310', '\u00AC', '\u00BD', '\u00BC', '\u00A1', '\u00AB', '\u00BB',
'\u2591', '\u2592', '\u2593', '\u2502', '\u2524', '\u2561', '\u2562', '\u2556', '\u2555', '\u2563', '\u2551', '\u2557', '\u255D', '\u255C', '\u255B', '\u2510',
'\u2514', '\u2534', '\u252C', '\u251C', '\u2500', '\u253C', '\u255E', '\u255F', '\u255A', '\u2554', '\u2569', '\u2566', '\u2560', '\u2550', '\u256C', '\u2567',
'\u2568', '\u2564', '\u2565', '\u2559', '\u2558', '\u2552', '\u2553', '\u256B', '\u256A', '\u2518', '\u250C', '\u2588', '\u2584', '\u258C', '\u2590', '\u2580',
'\u03B1', '\u00DF', '\u0393', '\u03C0', '\u03A3', '\u03C3', '\u00B5', '\u03C4', '\u03A6', '\u0398', '\u03A9', '\u03B4', '\u221E', '\u03C6', '\u03B5', '\u2229',
'\u2261', '\u00B1', '\u2265', '\u2264', '\u2320', '\u2321', '\u00F7', '\u2248', '\u00B0', '\u2219', '\u00B7', '\u221A', '\u207F', '\u00B2', '\u25A0', '\u00A0',
};
public static Dictionary<char, int> CharDict => _charMap;
public static Texture2D Source => _source;
public static Rectangle[] Coords => _coords;
private static Dictionary<char, int> _charMap = new();
private static Texture2D _source;
private static Rectangle[] _coords = new Rectangle[Codepoints.Length];
public Charset()
{
_source = Texture2D.FromFile(Capy64.Instance.GraphicsDevice, "Assets/charset.png");
for (int i = 0; i < Codepoints.Length; i++)
{
_coords[i] = new Rectangle
{
X = CharWidth * (i % 16),
Y = CharHeight * (i / 16),
Width = CharWidth,
Height = CharHeight,
};
_charMap[Codepoints[i]] = i;
}
}
public static int GetIndex(char c)
{
if (_charMap.TryGetValue(c, out var index))
return index;
return _charMap['?'];
}
}

View file

@ -25,7 +25,7 @@ namespace Capy64.Core;
public class Drawing : IDisposable
{
private SpriteBatch _spriteBatch;
public SpriteBatch SpriteBatch;
private GraphicsDevice _graphicsDevice;
private readonly FontSystem _fontSystem;
private Texture2D _whitePixel;
@ -41,10 +41,10 @@ public class Drawing : IDisposable
if (isDrawing)
End();
_canvas = value;
_spriteBatch = new SpriteBatch(_canvas.GraphicsDevice);
SpriteBatch = new SpriteBatch(_canvas.GraphicsDevice);
_graphicsDevice = _canvas.GraphicsDevice;
_whitePixel = new Texture2D(_spriteBatch.GraphicsDevice, 1, 1, mipmap: false, SurfaceFormat.Color);
_whitePixel = new Texture2D(SpriteBatch.GraphicsDevice, 1, 1, mipmap: false, SurfaceFormat.Color);
_whitePixel.SetData(new Color[1] { Color.White });
if (isDrawing)
Begin();
@ -65,7 +65,7 @@ public class Drawing : IDisposable
_isDrawing = true;
_graphicsDevice.SetRenderTarget(_canvas);
_graphicsDevice.DepthStencilState = new DepthStencilState() { DepthBufferEnable = true, };
_spriteBatch.Begin();
SpriteBatch.Begin();
}
public void End()
@ -73,7 +73,7 @@ public class Drawing : IDisposable
if (!_isDrawing)
return;
_spriteBatch.End();
SpriteBatch.End();
_graphicsDevice.SetRenderTarget(null);
foreach (var t in _disposeTextures)
@ -86,7 +86,7 @@ public class Drawing : IDisposable
public void DrawString(Vector2 pos, string text, Color color, int size = 13)
{
var font = _fontSystem.GetFont(size);
_spriteBatch.DrawString(font, text, pos, color, layerDepth: 0);
SpriteBatch.DrawString(font, text, pos, color, layerDepth: 0);
}
public Vector2 MeasureString(string text, int size = 13)
@ -151,18 +151,18 @@ public class Drawing : IDisposable
public void DrawPoint(Vector2 point, Color color, int size = 1)
{
_spriteBatch.DrawPoint(point, color, size);
SpriteBatch.DrawPoint(point, color, size);
}
public void DrawCircle(Vector2 pos, int radius, Color color, int thickness = 1, int sides = -1)
{
sides = sides < 0 ? radius * 4 : sides;
_spriteBatch.DrawCircle(pos, radius, sides, color, thickness);
SpriteBatch.DrawCircle(pos, radius, sides, color, thickness);
}
public void DrawLine(Vector2 start, Vector2 end, Color color, float thickness = 1)
{
_spriteBatch.DrawLine(start, end, color, thickness);
SpriteBatch.DrawLine(start, end, color, thickness);
}
public void DrawRectangle(Vector2 pos, Size2 size, Color color, int thickness = 1, float rotation = 0f)
@ -172,13 +172,13 @@ public class Drawing : IDisposable
public void DrawPolygon(Vector2 pos, Vector2[] points, Color color, int thickness = 1)
{
_spriteBatch.DrawPolygon(pos, points, color, thickness);
SpriteBatch.DrawPolygon(pos, points, color, thickness);
}
public void DrawEllipse(Vector2 pos, Vector2 radius, Color color, int thickness = 1)
{
var sides = (int)Math.Max(radius.X, radius.Y) * 4;
_spriteBatch.DrawEllipse(pos, radius, sides, color, thickness);
SpriteBatch.DrawEllipse(pos, radius, sides, color, thickness);
}
public void Clear(Color? color = default)
@ -194,10 +194,10 @@ public class Drawing : IDisposable
Vector2 position3 = new(rectangle.X, rectangle.Bottom - thickness);
Vector2 scale = new(rectangle.Width, thickness);
Vector2 scale2 = new(thickness, rectangle.Height);
_spriteBatch.Draw(_whitePixel, position, null, color, rotation, Vector2.Zero, scale, SpriteEffects.None, layerDepth);
_spriteBatch.Draw(_whitePixel, position, null, color, rotation, Vector2.Zero, scale2, SpriteEffects.None, layerDepth);
_spriteBatch.Draw(_whitePixel, position2, null, color, rotation, Vector2.Zero, scale2, SpriteEffects.None, layerDepth);
_spriteBatch.Draw(_whitePixel, position3, null, color, rotation, Vector2.Zero, scale, SpriteEffects.None, layerDepth);
SpriteBatch.Draw(_whitePixel, position, null, color, rotation, Vector2.Zero, scale, SpriteEffects.None, layerDepth);
SpriteBatch.Draw(_whitePixel, position, null, color, rotation, Vector2.Zero, scale2, SpriteEffects.None, layerDepth);
SpriteBatch.Draw(_whitePixel, position2, null, color, rotation, Vector2.Zero, scale2, SpriteEffects.None, layerDepth);
SpriteBatch.Draw(_whitePixel, position3, null, color, rotation, Vector2.Zero, scale, SpriteEffects.None, layerDepth);
}
public void DrawBuffer(uint[] buffer, Rectangle rect, Rectangle? source = null, Color? color = null, float rotation = 0f, Vector2? origin = null, float scale = 1f, SpriteEffects spriteEffects = 0)
@ -205,7 +205,7 @@ public class Drawing : IDisposable
var texture = new Texture2D(_graphicsDevice, rect.Width, rect.Height, false, SurfaceFormat.Color);
texture.SetData(buffer);
_spriteBatch.Draw(
SpriteBatch.Draw(
texture, // Texture
rect.Location.ToVector2(), // Position
source, // source
@ -222,7 +222,7 @@ public class Drawing : IDisposable
public void Dispose()
{
GC.SuppressFinalize(this);
_spriteBatch.Dispose();
SpriteBatch.Dispose();
_whitePixel.Dispose();
}
}

View file

@ -185,9 +185,10 @@ internal class EventEmitter
private void OnChar(object sender, CharEvent e)
{
var i = (byte)Charset.GetIndex(e.Character);
_runtime.QueueEvent("char", LK =>
{
LK.PushString(e.Character.ToString());
LK.PushBuffer(new byte[] { i });
return 1;
});

View file

@ -14,6 +14,7 @@
// limitations under the License.
using Capy64.API;
using Capy64.Core;
using Capy64.Eventing.Events;
using KeraLua;
using Microsoft.Xna.Framework;
@ -25,7 +26,7 @@ namespace Capy64.Runtime.Libraries;
internal class Term : IComponent
{
private struct Char
private struct TermChar
{
public char Character;
public Color Foreground;
@ -47,7 +48,7 @@ internal class Term : IComponent
private static Vector2 _cursorPosition { get; set; }
public static Color ForegroundColor { get; set; }
public static Color BackgroundColor { get; set; }
private static Char?[] CharGrid;
private static TermChar?[] CharGrid;
private static IGame _game;
private static bool cursorState = false;
@ -204,7 +205,7 @@ internal class Term : IComponent
_game.Drawing.DrawRectangle(realpos, new(CharWidth, CharHeight), bg, Math.Min(CharWidth, CharHeight));
//_game.Drawing.DrawRectangle(realpos, new(CharWidth, CharHeight), Color.Red, 1);
try
/*try
{
_game.Drawing.DrawString(charpos, ch.ToString(), fg);
@ -212,7 +213,10 @@ internal class Term : IComponent
catch (ArgumentException ex) // UTF-16 fuckery
{
_game.Drawing.DrawString(charpos, "\xFFFD", fg);
}
}*/
var rect = Charset.Coords[(int)ch];
_game.Drawing.SpriteBatch.Draw(Charset.Source, charpos, rect, fg);
if(underline)
{
@ -222,7 +226,7 @@ internal class Term : IComponent
if (!save)
return;
CharGrid[(int)pos.X + ((int)pos.Y * Width)] = new Char
CharGrid[(int)pos.X + ((int)pos.Y * Width)] = new TermChar
{
Character = ch,
Foreground = ForegroundColor,
@ -237,7 +241,7 @@ internal class Term : IComponent
return;
var ch = CharGrid[(int)pos.X + ((int)pos.Y * Width)] ??
new Char
new TermChar
{
Character = ' ',
Foreground = ForegroundColor,
@ -312,7 +316,7 @@ internal class Term : IComponent
private static void ClearGrid()
{
CharGrid = new Char?[CharGrid.Length];
CharGrid = new TermChar?[CharGrid.Length];
_game.Drawing.Clear(BackgroundColor);
}
@ -320,7 +324,16 @@ internal class Term : IComponent
{
foreach (var ch in text)
{
PlotChar(_cursorPosition, ch);
PlotChar(_cursorPosition, (char)ch);
_cursorPosition = new(_cursorPosition.X + 1, _cursorPosition.Y);
}
}
public static void Write(byte[] buffer)
{
foreach (var b in buffer)
{
PlotChar(_cursorPosition, (char)b);
_cursorPosition = new(_cursorPosition.X + 1, _cursorPosition.Y);
}
}
@ -328,9 +341,9 @@ internal class Term : IComponent
private static int L_Write(IntPtr state)
{
var L = Lua.FromIntPtr(state);
string str = "";
byte[] str = new byte[0];
if (!L.IsNone(1))
str = L.ToString(1);
str = L.ToBuffer(1);
Write(str);
@ -553,7 +566,7 @@ internal class Term : IComponent
}
var lineLength = Math.Abs(lines) * Width;
var newGrid = new Char?[CharGrid.Length];
var newGrid = new TermChar?[CharGrid.Length];
if (lines < 0)
{
Array.Copy(CharGrid, lineLength, newGrid, 0, CharGrid.Length - lineLength);
@ -614,7 +627,7 @@ internal class Term : IComponent
{
var L = Lua.FromIntPtr(state);
var text = L.CheckString(1);
var text = L.CheckBuffer(1);
L.CheckType(2, LuaType.Table);
L.CheckType(3, LuaType.Table);