| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342 |
- using Microsoft.Xna.Framework;
- using Microsoft.Xna.Framework.Graphics;
- using OpenVIII.Encoding.Tags;
- using System.Collections.Generic;
- using System.Linq;
- namespace OpenVIII
- {
- /// <summary>
- /// Font Module
- /// </summary>
- /// <remarks>
- /// 21x10 characters; char is always 24x24; 2 files side by side; sysfnt00 is same as sysfld00,
- /// but sysfnt00 is missing sysfnt01
- /// </remarks>
- public class Font
- {
- #region Fields
- public static Dictionary<ColorID, Color> ColorID2Blink = new Dictionary<ColorID, Color>
- {
- { ColorID.Dark_Grey, new Color(12,15,12,255) },
- { ColorID.Grey, new Color(41,49,41,255) },
- { ColorID.Yellow, new Color(222,222,8,255) },
- { ColorID.Red, new Color(128,24,24,255) },
- { ColorID.Green, new Color(0,128,0,255) },
- { ColorID.Blue, new Color(53,90,128,255) },
- { ColorID.Purple, new Color(128,0,128,255) },
- { ColorID.White, new Color(148,148,164,255) }
- };
- public static Dictionary<ColorID, Color> ColorID2Color = new Dictionary<ColorID, Color>
- {
- { ColorID.Dark_Grey, new Color(41,49,41,255) },
- { ColorID.Grey, new Color(148,148,164,255) },
- { ColorID.Yellow, new Color(222,222,8,255) },
- { ColorID.Red, new Color(255,24,24,255) },
- { ColorID.Green, new Color(0,255,0,255) },
- { ColorID.Blue, new Color(106,180,238,255) },
- { ColorID.Purple, new Color(255,0,255,255) },
- { ColorID.White, Color.White },
- };
- private byte[] charWidths;
- private Texture2D menuFont;
- private Texture2D sysfnt; //21x10 characters; char is always 12x12
- private TextureHandler sysfntbig;
- #endregion Fields
- #region Constructors
- public Font() => LoadFonts();
- #endregion Constructors
- #region Enums
- public enum ColorID
- {
- Dark_Grey, Grey, Yellow, Red, Green, Blue, Purple, White,
- //these are darker versions that are faded to when blinking
- }
- public enum Type
- {
- sysFntBig,
- sysfnt,
- menuFont,
- }
- #endregion Enums
- #region Methods
- public void LoadFonts()
- {
- Memory.Log.WriteLine($"{nameof(Font)} :: {nameof(LoadFonts)} ");
- var aw = ArchiveWorker.Load(Memory.Archives.A_MENU);
- var bufferTex = aw.GetBinaryFile("sysfnt.tex");
- var tex = new TEX(bufferTex);
- sysfnt = tex.GetTexture((int)ColorID.White);
- sysfntbig = TextureHandler.Create("sysfld{0:00}.tex", tex, 2, 1, (int)ColorID.White);
- var bufferTDW = aw.GetBinaryFile("sysfnt.tdw");
- var tim = new TDW(bufferTDW);
- charWidths = tim.CharWidths;
- menuFont = tim.GetTexture((ushort)ColorID.White);
-
- }
- public Rectangle RenderBasicText(FF8String buffer, Vector2 pos, Vector2 zoom, Type whichFont = 0, float Fade = 1.0f, int lineSpacing = 0, bool skipdraw = false, ColorID color_ = ColorID.White, bool blink = false)
- {
- var colorbak = color_;
- var color = ColorID2Color[color_];
- var faded_color = ColorID2Blink[color_];
- if (buffer == null) return new Rectangle();
- var ret = new Rectangle(pos.RoundedPoint(), new Point(0));
- var destRect = Rectangle.Empty;
- var real = pos.RoundedPoint();
- var charCountWidth = 21;
- var charSize = 12; //pixelhandler does the 2x scaling on the fly.
- var size = (new Vector2(0, charSize) * zoom).RoundedPoint();
- var baksize = size;
- var width = 0;
- var skipletter = false;
- for (var i = 0; i < buffer.Length; i++)
- {
- size = baksize;
- var c = buffer[i];
- if (c == 0) continue;
- else if (c == (byte)FF8TextTagCode.Dialog)
- {
- if (++i < buffer.Length - 1)
- {
- c = buffer[i];
- switch ((FF8TextTagDialog)c)
- {
- // Most of these should be replaced before it gets here becuase they have
- // values set by other objects.
- case FF8TextTagDialog.CustomICON:
- DrawIcon(buffer, zoom, Fade, skipdraw, real, ref size, ref skipletter, ref i, ref c);
- break;
- }
- //if (!skipletter)
- SetRetRec(pos, ref ret, ref real, size);
- continue;
- }
- }
- else if (c == (byte)FF8TextTagCode.Key)
- {
- if (++i < buffer.Length - 1)
- {
- var k = (FF8TextTagKey)buffer[i];
- var str = Input2.ButtonString(k);
- var retpos = RenderBasicText(str, real, zoom, whichFont, Fade, lineSpacing, skipdraw, ColorID.Green);
- size.X = retpos.Width;
- //size.Y = retpos.Height;
- //real.X += retpos.Width;
- //TODO add key/controller input icons/text here.
- //if (!skipletter)
- SetRetRec(pos, ref ret, ref real, size);
- continue;
- }
- }
- else if (c == (byte)FF8TextTagCode.Color)
- {
- if (++i < buffer.Length - 1)
- {
- c = buffer[i];
- blink = c >= (byte)FF8TextTagColor.Dark_GrayBlink ? true : false;
- GetColorFromTag(c, out var nc, out var fc);
- color = nc ?? ColorID2Color[colorbak];
- faded_color = fc ?? ColorID2Blink[colorbak];
- SetRetRec(pos, ref ret, ref real, size);
- continue;
- }
- }
- else if (c == (byte)FF8TextTagCode.Line && NewLine(pos, lineSpacing, ref real, size))
- {
- SetRetRec(pos, ref ret, ref real, size);
- continue;
- }
- if (!skipletter)
- {
- var deltaChar = GetDeltaChar(c);
- if (deltaChar >= 0 && charWidths != null && deltaChar < charWidths.Length)
- {
- width = charWidths[deltaChar];
- size.X = (int)(charWidths[deltaChar] * zoom.X);
- }
- else
- {
- width = charSize;
- size.X = (int)(charSize * zoom.X);
- }
- var curSize = size;
- var verticalPosition = deltaChar / charCountWidth;
- //i.e. 1280 is 100%, 640 is 50% and therefore 2560 is 200% which means multiply by 0.5f or 2.0f
- destRect = new Rectangle(real, size);
- if (!skipdraw)
- {
- var sourceRect = new Rectangle((deltaChar - (verticalPosition * charCountWidth)) * charSize,
- verticalPosition * charSize,
- width,
- charSize);
- DrawLetter(whichFont, Fade, blink ? Color.Lerp(color, faded_color, Menu.Blink_Amount) : color, destRect, sourceRect);
- }
- }
- skipletter = false;
- SetRetRec(pos, ref ret, ref real, size);
- }
- ret.Height = size.Y + (real.Y - (int)pos.Y);
- return ret;
- }
- private static void SetRetRec(Vector2 pos, ref Rectangle ret, ref Point real, Point size)
- {
- real.X += size.X;
- var curWidth = real.X - (int)pos.X;
- if (curWidth > ret.Width)
- ret.Width = curWidth;
- }
- private static void DrawIcon(FF8String buffer, Vector2 zoom, float Fade, bool skipdraw, Point real, ref Point size, ref bool skipletter, ref int i, ref byte c)
- {
- if (i + 3 < buffer.Length)
- {
- c = buffer[++i];
- short ic = c;
- c = buffer[++i];
- ic |= (short)(c << 8);
- var pal = buffer[++i];
- Memory.Icons.Trim((Icons.ID)ic, pal);
- var icon = Memory.Icons[(Icons.ID)ic];
- //Vector2 scale = Memory.Icons.GetTexture((Icons.ID)ic).ScaleFactor;
- if (icon != null)
- {
- var adj = (12 / (float)(icon.Height));
- var scale = new Vector2(adj * zoom.X);
- size.X = (int)(icon.Width * scale.X);
- size.Y = (int)(icon.Height * scale.X);
- var destRect = new Rectangle(real, size);
- //real.X += size.X;
- //skipletter = true;
- if (!skipdraw)
- Memory.Icons.Draw((Icons.ID)ic, pal, destRect, Vector2.Zero, Fade);
- }
- }
- }
- public Rectangle RenderBasicText(FF8String buffer, Point pos, Vector2 zoom, Type whichFont = 0, float Fade = 1.0f, int lineSpacing = 0, bool skipdraw = false, ColorID color = ColorID.White, bool blink = false)
- => RenderBasicText(buffer, pos.ToVector2(), zoom, whichFont, Fade, lineSpacing, skipdraw, color, blink);
- public Rectangle RenderBasicText(FF8String buffer, int x, int y, float zoomWidth = 2.545455f, float zoomHeight = 3.0375f, Type whichFont = 0, float Fade = 1.0f, int lineSpacing = 0, bool skipdraw = false, ColorID color = ColorID.White, bool blink = false)
- => RenderBasicText(buffer, new Vector2(x, y), new Vector2(zoomWidth, zoomHeight), whichFont, Fade, lineSpacing, skipdraw, color,blink);
- private static void GetColorFromTag(byte c, out Color? color, out Color? faded_color)
- {
- color = null;
- faded_color = null;
- ColorID? cid = null;
- switch ((FF8TextTagColor)c)
- {
- case FF8TextTagColor.Blue:
- case FF8TextTagColor.BlueBlink:
- cid = ColorID.Blue;
- break;
- case FF8TextTagColor.Green:
- case FF8TextTagColor.GreenBlink:
- cid = ColorID.Green;
- break;
- case FF8TextTagColor.Grey:
- case FF8TextTagColor.GreyBlink:
- cid = ColorID.Grey;
- break;
- case FF8TextTagColor.Purple:
- case FF8TextTagColor.PurpleBlink:
- cid = ColorID.Purple;
- break;
- case FF8TextTagColor.Red:
- case FF8TextTagColor.RedBlink:
- cid = ColorID.Red;
- break;
- case FF8TextTagColor.White:
- case FF8TextTagColor.WhiteBlink:
- // since ending cid change reverts cid to white. if you have a custom cid set
- // this will allow reverting to that.
- break;
- case FF8TextTagColor.Yellow:
- case FF8TextTagColor.YellowBlink:
- cid = ColorID.Yellow;
- break;
- case FF8TextTagColor.Dark_Gray:
- case FF8TextTagColor.Dark_GrayBlink:
- cid = ColorID.Dark_Grey;
- break;
- }
- if (cid.HasValue)
- {
- color = ColorID2Color[cid.Value];
- faded_color = ColorID2Blink[cid.Value];
- }
- }
- private static int GetDeltaChar(byte c) => (c - 32);
- private static bool NewLine(Vector2 pos, int lineSpacing, ref Point real, Point size)
- {
- bool gonext;
- real.X = (int)pos.X;
- real.Y += size.Y + lineSpacing;
- gonext = true;
- return gonext;
- }
- private void DrawLetter(Type whichFont, float Fade, Color color, Rectangle destRect, Rectangle sourceRect)
- {
- switch (whichFont)
- {
- case Type.menuFont:
- case Type.sysfnt:
- // if you use Memory.SpriteBatchStartAlpha(SamplerState.PointClamp); you won't need
- // to trim last pixel. but it doesn't look good on low res fonts.
- //trim pixels to remove texture filtering artifacts.
- //sourceRect.Width -= 1;
- //sourceRect.Height -= 1;
- Memory.SpriteBatch.Draw(whichFont == Type.menuFont ? menuFont : sysfnt,
- destRect,
- sourceRect,
- color * Fade);
- break;
- case Type.sysFntBig:
- if (sysfntbig != null)
- {
- if (!sysfntbig.Modded)
- {
- var ShadowdestRect = new Rectangle(destRect.Location, destRect.Size);
- ShadowdestRect.Offset(2, 2);
- sysfntbig.Draw(ShadowdestRect, sourceRect, Color.Black * Fade * .5f);
- }
- sysfntbig.Draw(destRect, sourceRect, color * Fade);
- }
- break;
- }
- }
- #endregion Methods
- }
- }
|