Show fallback glyph if its not present in the font, add Japanese font to TestGame.
This commit is contained in:
@@ -244,6 +244,12 @@ namespace Voile.Rendering
|
||||
LoadFont(font);
|
||||
}
|
||||
|
||||
if (font.Dirty && font.Handle != -1)
|
||||
{
|
||||
UnloadFont(font);
|
||||
LoadFont(font);
|
||||
}
|
||||
|
||||
var rayFont = _fontPool[font.Handle];
|
||||
|
||||
Raylib.DrawTextPro(rayFont, text, transformPosition, transformPivot, transformRotation, font.Size, 0.0f, VoileColorToRaylibColor(color));
|
||||
@@ -268,10 +274,10 @@ namespace Voile.Rendering
|
||||
{
|
||||
Raylib_cs.Font fontRay;
|
||||
|
||||
string ext = ".ttf"; // TODO: don't use a hardcoded extension.
|
||||
int fontChars = 250; // TODO: control this dynamically to not load the entire font.
|
||||
string ext = ".ttf";
|
||||
int fontChars = font.Codepoints.Count;
|
||||
|
||||
fontRay = Raylib.LoadFontFromMemory(ext, font.Buffer, font.Size, null, fontChars);
|
||||
fontRay = Raylib.LoadFontFromMemory(ext, font.Buffer, font.Size, font.Codepoints.ToArray(), fontChars);
|
||||
|
||||
Raylib.GenTextureMipmaps(ref fontRay.Texture);
|
||||
Raylib.SetTextureFilter(fontRay.Texture, TextureFilter.Bilinear);
|
||||
@@ -281,6 +287,14 @@ namespace Voile.Rendering
|
||||
font.Handle = _fontPool.Count - 1;
|
||||
}
|
||||
|
||||
private void UnloadFont(Font font)
|
||||
{
|
||||
var fontRay = _fontPool[font.Handle];
|
||||
Raylib.UnloadFont(fontRay);
|
||||
|
||||
_fontPool.RemoveAt(font.Handle);
|
||||
}
|
||||
|
||||
private void LoadTexture(Texture2d texture)
|
||||
{
|
||||
Image image = new();
|
||||
|
||||
@@ -20,7 +20,7 @@ public struct Glyph
|
||||
/// <summary>
|
||||
/// Represents font data.
|
||||
/// </summary>
|
||||
public class Font : Resource, IDisposable
|
||||
public class Font : Resource, IUpdatableResource, IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Internal handle for the font. If it got successfully loaded into the GPU, the value will be other than -1.
|
||||
@@ -31,6 +31,8 @@ public class Font : Resource, IDisposable
|
||||
public byte[]? Buffer { get; private set; }
|
||||
public long BufferSize { get; set; }
|
||||
|
||||
public bool Dirty => _dirty;
|
||||
|
||||
internal float UnitsPerEm;
|
||||
|
||||
internal nint FacePtr;
|
||||
@@ -131,14 +133,31 @@ public class Font : Resource, IDisposable
|
||||
|
||||
public Glyph GetGlyph(char character)
|
||||
{
|
||||
if (!HasGlyph(character))
|
||||
{
|
||||
_glyphs.TryGetValue('?', out var defGlyph);
|
||||
return defGlyph;
|
||||
}
|
||||
if (_glyphs.TryGetValue(character, out var glyph))
|
||||
return glyph;
|
||||
|
||||
var loaded = LoadGlyph(character);
|
||||
_glyphs[character] = loaded;
|
||||
|
||||
_dirty = true;
|
||||
|
||||
return loaded;
|
||||
}
|
||||
|
||||
public bool HasGlyph(char character)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
var face = (FT_FaceRec_*)FacePtr;
|
||||
return FT_Get_Char_Index(face, character) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe Glyph LoadGlyph(char character)
|
||||
{
|
||||
var face = (FT_FaceRec_*)FacePtr;
|
||||
@@ -163,5 +182,11 @@ public class Font : Resource, IDisposable
|
||||
};
|
||||
}
|
||||
|
||||
public void MarkUpdated()
|
||||
{
|
||||
_dirty = false;
|
||||
}
|
||||
|
||||
private bool _dirty;
|
||||
private Dictionary<int, Glyph> _glyphs = new();
|
||||
}
|
||||
@@ -69,4 +69,20 @@ namespace Voile
|
||||
Path = path;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a Resource that requires systems to react to its changes.
|
||||
/// </summary>
|
||||
public interface IUpdatableResource
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this resource's state has changed and needs to be reloaded.
|
||||
/// </summary>
|
||||
bool Dirty { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Marks this resource as updated.
|
||||
/// </summary>
|
||||
void MarkUpdated();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user