-
Notifications
You must be signed in to change notification settings - Fork 55
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Rofli Sanches
committed
May 14, 2021
1 parent
21ee3c5
commit 4683b23
Showing
2 changed files
with
223 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,212 @@ | ||
using ImGuiNET; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Runtime.InteropServices; | ||
using UImGui.Assets; | ||
using Unity.Collections; | ||
using Unity.Collections.LowLevel.Unsafe; | ||
using UnityEngine; | ||
using UTexture = UnityEngine.Texture; | ||
|
||
namespace UImGui.Texture | ||
{ | ||
// TODO: Write documentation for methods | ||
internal class TextureManager | ||
{ | ||
private Texture2D _atlasTexture; | ||
private int _currentTextureId; | ||
|
||
private readonly Dictionary<int, UTexture> _textures = new Dictionary<int, UTexture>(); | ||
private readonly Dictionary<UTexture, int> _textureIds = new Dictionary<UTexture, int>(); | ||
private readonly Dictionary<Sprite, SpriteInfo> _spriteData = new Dictionary<Sprite, SpriteInfo>(); | ||
|
||
private readonly HashSet<IntPtr> _allocatedGlyphRangeArrays = new HashSet<IntPtr>(); // TODO: Check if yet IntPtr has boxing when comparing equality (see original version) | ||
|
||
public unsafe void Initialize(ImGuiIOPtr io) | ||
{ | ||
ImFontAtlasPtr atlasPtr = io.Fonts; | ||
atlasPtr.GetTexDataAsRGBA32(out byte* pixels, out int width, out int height, out int bytesPerPixel); | ||
|
||
_atlasTexture = new Texture2D(width, height, TextureFormat.RGBA32, false, false) | ||
{ | ||
filterMode = FilterMode.Point | ||
}; | ||
|
||
NativeArray<byte> srcData = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray<byte>(pixels, width * height * bytesPerPixel, Allocator.None); | ||
#if ENABLE_UNITY_COLLECTIONS_CHECKS | ||
NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref srcData, AtomicSafetyHandle.GetTempMemoryHandle()); | ||
#endif | ||
// Invert y while copying the atlas texture. | ||
NativeArray<byte> dstData = _atlasTexture.GetRawTextureData<byte>(); | ||
int stride = width * bytesPerPixel; | ||
for (int y = 0; y < height; ++y) | ||
{ | ||
NativeArray<byte>.Copy(srcData, y * stride, dstData, (height - y - 1) * stride, stride); | ||
} | ||
|
||
_atlasTexture.Apply(); | ||
} | ||
|
||
public void Shutdown() | ||
{ | ||
_currentTextureId = 0; | ||
_textures.Clear(); | ||
_textureIds.Clear(); | ||
_spriteData.Clear(); | ||
|
||
if (_atlasTexture != null) | ||
{ | ||
UnityEngine.Object.Destroy(_atlasTexture); | ||
_atlasTexture = null; | ||
} | ||
} | ||
|
||
public void PrepareFrame(ImGuiIOPtr io) | ||
{ | ||
_currentTextureId = 0; | ||
|
||
_textures.Clear(); | ||
_textureIds.Clear(); | ||
|
||
int id = RegisterTexture(_atlasTexture); | ||
io.Fonts.SetTexID((IntPtr)id); | ||
} | ||
|
||
public bool TryGetTexture(int id, out UTexture texture) | ||
{ | ||
return _textures.TryGetValue(id, out texture); | ||
} | ||
|
||
public int GetTextureId(UTexture texture) | ||
{ | ||
return _textureIds.TryGetValue(texture, out int id) ? id : RegisterTexture(texture); | ||
} | ||
|
||
public SpriteInfo GetSpriteInfo(Sprite sprite) | ||
{ | ||
if (!_spriteData.TryGetValue(sprite, out SpriteInfo spriteInfo)) | ||
{ | ||
_spriteData[sprite] = spriteInfo = new SpriteInfo | ||
{ | ||
Texture = sprite.texture, | ||
Size = sprite.rect.size, | ||
UV0 = sprite.uv[0], | ||
UV1 = sprite.uv[1], | ||
}; | ||
} | ||
|
||
return spriteInfo; | ||
} | ||
|
||
private int RegisterTexture(UTexture texture) | ||
{ | ||
_textures[++_currentTextureId] = texture; | ||
_textureIds[texture] = _currentTextureId; | ||
|
||
return _currentTextureId; | ||
} | ||
|
||
public void BuildFontAtlas(ImGuiIOPtr io, in FontAtlasConfigAsset settings) | ||
{ | ||
if (io.Fonts.IsBuilt()) | ||
{ | ||
DestroyFontAtlas(io); | ||
} | ||
|
||
if (!io.MouseDrawCursor) | ||
{ | ||
io.Fonts.Flags |= ImFontAtlasFlags.NoMouseCursors; | ||
} | ||
|
||
if (settings == null) | ||
{ | ||
io.Fonts.AddFontDefault(); | ||
io.Fonts.Build(); | ||
return; | ||
} | ||
|
||
// Ddd fonts from config asset. | ||
foreach (FontDefinition fontDefinition in settings.Fonts) | ||
{ | ||
string fontPath = System.IO.Path.Combine(Application.streamingAssetsPath, fontDefinition.Path); | ||
if (!System.IO.File.Exists(fontPath)) | ||
{ | ||
Debug.Log($"Font file not found: {fontPath}"); | ||
continue; | ||
} | ||
|
||
unsafe | ||
{ | ||
ImFontConfig fontConfig = default; | ||
ImFontConfigPtr fontConfigPtr = new ImFontConfigPtr(&fontConfig); | ||
|
||
fontDefinition.Config.ApplyTo(fontConfigPtr); | ||
fontConfigPtr.GlyphRanges = AllocateGlyphRangeArray(fontDefinition.Config); | ||
|
||
io.Fonts.AddFontFromFileTTF(fontPath, fontDefinition.Config.SizeInPixels, fontConfigPtr); | ||
} | ||
} | ||
|
||
if (io.Fonts.Fonts.Size == 0) | ||
{ | ||
io.Fonts.AddFontDefault(); | ||
} | ||
|
||
switch (settings.Rasterizer) | ||
{ | ||
case FontRasterizerType.StbTrueType: | ||
io.Fonts.Build(); | ||
break; | ||
// TODO: Test FreeType. | ||
#if IMGUI_FEATURE_FREETYPE | ||
//case FontRasterizerType.FreeType: | ||
// ImFreetype.BuildFontAtlas(io.Fonts, (ImFreetype.RasterizerFlags)settings.RasterizerFlags); | ||
// break; | ||
#endif | ||
default: | ||
Debug.LogWarning($"{settings.Rasterizer:G} rasterizer not available, using {default(FontRasterizerType):G}. Please report it."); | ||
io.Fonts.Build(); | ||
break; | ||
} | ||
} | ||
|
||
public unsafe void DestroyFontAtlas(ImGuiIOPtr io) | ||
{ | ||
FreeGlyphRangeArrays(); | ||
|
||
io.Fonts.Clear(); // Previous FontDefault reference no longer valid. | ||
io.NativePtr->FontDefault = default; // NULL uses Fonts[0]. | ||
} | ||
|
||
private unsafe IntPtr AllocateGlyphRangeArray(in FontConfig fontConfig) | ||
{ | ||
List<ushort> values = fontConfig.BuildRanges(); | ||
if (values.Count == 0) | ||
{ | ||
return IntPtr.Zero; | ||
} | ||
|
||
int byteCount = sizeof(ushort) * (values.Count + 1); // terminating zero. | ||
ushort* ranges = (ushort*)Marshal.AllocHGlobal(byteCount); | ||
_allocatedGlyphRangeArrays.Add((IntPtr)ranges); | ||
|
||
for (int i = 0; i < values.Count; ++i) | ||
{ | ||
ranges[i] = values[i]; | ||
} | ||
ranges[values.Count] = 0; | ||
|
||
return (IntPtr)ranges; | ||
} | ||
|
||
private unsafe void FreeGlyphRangeArrays() | ||
{ | ||
foreach (IntPtr range in _allocatedGlyphRangeArrays) | ||
{ | ||
Marshal.FreeHGlobal(range); | ||
} | ||
|
||
_allocatedGlyphRangeArrays.Clear(); | ||
} | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.