mirror of
https://github.com/AxioDL/metaforce.git
synced 2025-12-09 18:27:42 +00:00
platform-sensitive system init
This commit is contained in:
@@ -1,18 +1,22 @@
|
||||
#include "Specter/TextView.hpp"
|
||||
#include "Specter/ViewSystem.hpp"
|
||||
#include "utf8proc.h"
|
||||
|
||||
namespace Specter
|
||||
{
|
||||
static LogVisor::LogModule Log("Specter::TextView");
|
||||
|
||||
TextView::System TextView::BuildTextSystem(boo::GLDataFactory* factory, FontCache& fcache)
|
||||
void TextView::System::init(boo::GLDataFactory* factory, FontCache* fcache)
|
||||
{
|
||||
m_fcache = fcache;
|
||||
|
||||
static const char* VS =
|
||||
"#version 330\n"
|
||||
"layout(location=0) in vec3 posIn;\n"
|
||||
"layout(location=1) in mat4 mvMtx;\n"
|
||||
"layout(location=5) in vec3 uvIn[4];\n"
|
||||
"layout(location=9) in vec4 colorIn;\n"
|
||||
"layout(location=0) in vec3 posIn[4];\n"
|
||||
"layout(location=4) in mat4 mvMtx;\n"
|
||||
"layout(location=8) in vec3 uvIn[4];\n"
|
||||
"layout(location=12) in vec4 colorIn;\n"
|
||||
SPECTER_VIEW_VERT_BLOCK_GLSL
|
||||
"struct VertToFrag\n"
|
||||
"{\n"
|
||||
" vec3 uv;\n"
|
||||
@@ -23,7 +27,7 @@ TextView::System TextView::BuildTextSystem(boo::GLDataFactory* factory, FontCach
|
||||
"{\n"
|
||||
" vtf.uv = uvIn[gl_VertexID];\n"
|
||||
" vtf.color = colorIn;\n"
|
||||
" gl_Position = mvMtx * vec4(posIn, 1.0);\n"
|
||||
" gl_Position = mv * mvMtx * vec4(posIn[gl_VertexID], 1.0);\n"
|
||||
"}\n";
|
||||
|
||||
static const char* FSReg =
|
||||
@@ -59,56 +63,35 @@ TextView::System TextView::BuildTextSystem(boo::GLDataFactory* factory, FontCach
|
||||
" blendOut = texture(fontTex, vtf.uv);\n"
|
||||
"}\n";
|
||||
|
||||
static float Quad[] =
|
||||
{
|
||||
0.0, 0.0, 0.0,
|
||||
0.0, 1.0, 0.0,
|
||||
1.0, 1.0, 0.0,
|
||||
1.0, 0.0, 0.0,
|
||||
};
|
||||
static const char* BlockNames[] = {"SpecterViewBlock"};
|
||||
|
||||
System ret(factory, fcache);
|
||||
|
||||
ret.m_regular =
|
||||
factory->newShaderPipeline(VS, FSReg, 1, "fontTex", 0, nullptr,
|
||||
m_regular =
|
||||
factory->newShaderPipeline(VS, FSReg, 1, "fontTex", 1, BlockNames,
|
||||
boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
|
||||
true, true, false);
|
||||
|
||||
ret.m_subpixel =
|
||||
factory->newShaderPipeline(VS, FSSubpixel, 1, "fontTex", 0, nullptr,
|
||||
m_subpixel =
|
||||
factory->newShaderPipeline(VS, FSSubpixel, 1, "fontTex", 1, BlockNames,
|
||||
boo::BlendFactor::SrcColor1, boo::BlendFactor::InvSrcColor1,
|
||||
true, true, false);
|
||||
|
||||
ret.m_quadVBO =
|
||||
factory->newStaticBuffer(boo::BufferUse::Vertex, Quad, sizeof(Quad), 1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if _WIN32
|
||||
TextView::Shaders TextView::BuildTextSystem(boo::ID3DDataFactory* factory, FontCache& fcache)
|
||||
{
|
||||
}
|
||||
|
||||
#elif BOO_HAS_METAL
|
||||
TextView::Shaders TextView::BuildTextSystem(boo::MetalDataFactory* factory, FontCache& fcache)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
TextView::TextView(System& system, FontTag font, size_t initGlyphCapacity)
|
||||
: m_curGlyphCapacity(initGlyphCapacity),
|
||||
m_fontAtlas(system.m_fcache.lookupAtlas(font))
|
||||
TextView::TextView(ViewSystem& system, FontTag font, size_t initGlyphCapacity)
|
||||
: View(system),
|
||||
m_fontAtlas(system.m_textSystem.m_fcache->lookupAtlas(font))
|
||||
{
|
||||
m_glyphBuf =
|
||||
system.m_factory->newDynamicBuffer(boo::BufferUse::Vertex,
|
||||
sizeof(RenderGlyph), initGlyphCapacity);
|
||||
|
||||
if (!system.m_vtxFmt)
|
||||
if (!system.m_textSystem.m_vtxFmt)
|
||||
{
|
||||
boo::VertexElementDescriptor vdescs[] =
|
||||
{
|
||||
{system.m_quadVBO, nullptr, boo::VertexSemantic::Position},
|
||||
{m_glyphBuf, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 0},
|
||||
{m_glyphBuf, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 1},
|
||||
{m_glyphBuf, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 2},
|
||||
{m_glyphBuf, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 3},
|
||||
{m_glyphBuf, nullptr, boo::VertexSemantic::ModelView | boo::VertexSemantic::Instanced, 0},
|
||||
{m_glyphBuf, nullptr, boo::VertexSemantic::ModelView | boo::VertexSemantic::Instanced, 1},
|
||||
{m_glyphBuf, nullptr, boo::VertexSemantic::ModelView | boo::VertexSemantic::Instanced, 2},
|
||||
@@ -119,31 +102,95 @@ TextView::TextView(System& system, FontTag font, size_t initGlyphCapacity)
|
||||
{m_glyphBuf, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 3},
|
||||
{m_glyphBuf, nullptr, boo::VertexSemantic::Color | boo::VertexSemantic::Instanced}
|
||||
};
|
||||
m_vtxFmt = system.m_factory->newVertexFormat(10, vdescs);
|
||||
m_bgVtxFmt = system.m_factory->newVertexFormat(13, vdescs);
|
||||
}
|
||||
|
||||
m_glyphs.reserve(initGlyphCapacity);
|
||||
}
|
||||
|
||||
TextView::RenderGlyph::RenderGlyph(int& adv, const FontAtlas::Glyph& glyph, Zeus::CColor defaultColor)
|
||||
{
|
||||
m_pos[0].assign(adv + glyph.m_leftPadding, glyph.m_verticalOffset + glyph.m_height, 0.f);
|
||||
m_pos[1].assign(adv + glyph.m_leftPadding, glyph.m_verticalOffset, 0.f);
|
||||
m_pos[2].assign(adv + glyph.m_leftPadding + glyph.m_width, glyph.m_verticalOffset + glyph.m_height, 0.f);
|
||||
m_pos[3].assign(adv + glyph.m_leftPadding + glyph.m_width, glyph.m_verticalOffset, 0.f);
|
||||
m_uv[0].assign(glyph.m_uv[0], glyph.m_uv[1], glyph.m_layerFloat);
|
||||
m_uv[1].assign(glyph.m_uv[0], glyph.m_uv[3], glyph.m_layerFloat);
|
||||
m_uv[2].assign(glyph.m_uv[2], glyph.m_uv[1], glyph.m_layerFloat);
|
||||
m_uv[3].assign(glyph.m_uv[2], glyph.m_uv[3], glyph.m_layerFloat);
|
||||
m_color = defaultColor;
|
||||
adv += glyph.m_advance;
|
||||
}
|
||||
|
||||
void TextView::typesetGlyphs(const std::string& str, Zeus::CColor defaultColor)
|
||||
{
|
||||
size_t rem = str.size();
|
||||
const utf8proc_uint8_t* it = str.data();
|
||||
const utf8proc_uint8_t* it = reinterpret_cast<const utf8proc_uint8_t*>(str.data());
|
||||
utf8proc_int32_t lCh = -1;
|
||||
m_glyphs.clear();
|
||||
m_glyphs.reserve(str.size());
|
||||
int adv = 0;
|
||||
|
||||
while (rem)
|
||||
{
|
||||
utf8proc_int32_t ch;
|
||||
utf8proc_ssize_t sz = utf8proc_iterate(it, -1, &ch);
|
||||
if (sz < 0)
|
||||
Log.report(LogVisor::FatalError, "invalid UTF-8 char");
|
||||
if (ch == '\n')
|
||||
break;
|
||||
|
||||
m_fontAtlas
|
||||
const FontAtlas::Glyph* glyph = m_fontAtlas.lookupGlyph(ch);
|
||||
if (!glyph)
|
||||
{
|
||||
rem -= sz;
|
||||
it += sz;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lCh != -1)
|
||||
{
|
||||
adv += m_fontAtlas.lookupKern(lCh, ch);
|
||||
m_glyphs.emplace_back(adv, *glyph, defaultColor);
|
||||
}
|
||||
else
|
||||
m_glyphs.emplace_back(adv, *glyph, defaultColor);
|
||||
|
||||
lCh = ch;
|
||||
rem -= sz;
|
||||
it += sz;
|
||||
}
|
||||
|
||||
m_validDynamicSlots = 0;
|
||||
}
|
||||
void TextView::typesetGlyphs(const std::wstring& str, Zeus::CColor defaultColor)
|
||||
{
|
||||
wchar_t lCh = -1;
|
||||
m_glyphs.clear();
|
||||
m_glyphs.reserve(str.size());
|
||||
int adv = 0;
|
||||
|
||||
for (wchar_t ch : str)
|
||||
{
|
||||
if (ch == L'\n')
|
||||
break;
|
||||
|
||||
const FontAtlas::Glyph* glyph = m_fontAtlas.lookupGlyph(ch);
|
||||
if (!glyph)
|
||||
continue;
|
||||
|
||||
if (lCh != -1)
|
||||
{
|
||||
adv += m_fontAtlas.lookupKern(lCh, ch);
|
||||
m_glyphs.emplace_back(adv, *glyph, defaultColor);
|
||||
}
|
||||
else
|
||||
m_glyphs.emplace_back(adv, *glyph, defaultColor);
|
||||
|
||||
lCh = ch;
|
||||
}
|
||||
|
||||
m_validDynamicSlots = 0;
|
||||
}
|
||||
|
||||
void TextView::colorGlyphs(Zeus::CColor newColor)
|
||||
@@ -158,6 +205,14 @@ void TextView::think()
|
||||
|
||||
void TextView::draw(boo::IGraphicsCommandQueue* gfxQ)
|
||||
{
|
||||
bindScissor(gfxQ);
|
||||
int pendingSlot = 1 << gfxQ->pendingDynamicSlot();
|
||||
if ((m_validDynamicSlots & pendingSlot) == 0)
|
||||
{
|
||||
m_glyphBuf->load(m_glyphs.data(), m_glyphs.size() * sizeof(RenderGlyph));
|
||||
m_validDynamicSlots |= pendingSlot;
|
||||
}
|
||||
gfxQ->drawInstances(0, 4, m_glyphs.size());
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user