mirror of
https://github.com/AxioDL/metaforce.git
synced 2025-07-09 12:45:51 +00:00
Initial tooltip implementation
This commit is contained in:
parent
21e671e36f
commit
fc50272ea1
@ -35,6 +35,7 @@ list(APPEND SPECTER_HEADERS
|
||||
include/Specter/DeferredWindowEvents.hpp
|
||||
include/Specter/View.hpp
|
||||
include/Specter/RootView.hpp
|
||||
include/Specter/Tooltip.hpp
|
||||
include/Specter/SplitView.hpp
|
||||
include/Specter/ScrollView.hpp
|
||||
include/Specter/TextView.hpp
|
||||
@ -61,6 +62,7 @@ list(APPEND SPECTER_SOURCES
|
||||
lib/ViewResources.cpp
|
||||
lib/View.cpp
|
||||
lib/RootView.cpp
|
||||
lib/Tooltip.cpp
|
||||
lib/SplitView.cpp
|
||||
lib/ScrollView.cpp
|
||||
lib/TextView.cpp
|
||||
|
@ -174,6 +174,7 @@ class FontCache
|
||||
} m_fontLib;
|
||||
FreeTypeGZipMemFace m_regFace;
|
||||
FreeTypeGZipMemFace m_monoFace;
|
||||
FreeTypeGZipMemFace m_curvesFace;
|
||||
|
||||
std::unordered_map<FontTag, std::unique_ptr<FontAtlas>> m_cachedAtlases;
|
||||
public:
|
||||
@ -193,7 +194,11 @@ public:
|
||||
bool subpixel=false, float points=10.0, uint32_t dpi=72)
|
||||
{return prepCustomFont(gf, "bmonofont", m_monoFace, filter, subpixel, points, dpi);}
|
||||
|
||||
void closeBuiltinFonts() {m_regFace.close(); m_monoFace.close();}
|
||||
FontTag prepCurvesFont(boo::IGraphicsDataFactory* gf, FCharFilter filter=AllCharFilter,
|
||||
bool subpixel=false, float points=10.0, uint32_t dpi=72)
|
||||
{return prepCustomFont(gf, "spectercurves", m_curvesFace, filter, subpixel, points, dpi);}
|
||||
|
||||
void closeBuiltinFonts() {m_regFace.close(); m_monoFace.close(); m_curvesFace.close();}
|
||||
|
||||
const FontAtlas& lookupAtlas(FontTag tag) const;
|
||||
};
|
||||
|
@ -15,17 +15,25 @@ class MultiLineTextView : public View
|
||||
const FontAtlas& m_fontAtlas;
|
||||
size_t m_lineCapacity;
|
||||
float m_lineHeight;
|
||||
int m_width;
|
||||
std::string LineWrap(const std::string& str, int wrap);
|
||||
std::wstring LineWrap(const std::wstring& str, int wrap);
|
||||
public:
|
||||
MultiLineTextView(ViewResources& res, View& parentView, const FontAtlas& font, size_t lineCapacity=256, float lineHeight=1.0);
|
||||
MultiLineTextView(ViewResources& res, View& parentView, FontTag font, size_t lineCapacity=256, float lineHeight=1.0);
|
||||
|
||||
void typesetGlyphs(const std::string& str,
|
||||
const Zeus::CColor& defaultColor=Zeus::CColor::skWhite);
|
||||
const Zeus::CColor& defaultColor=Zeus::CColor::skWhite,
|
||||
unsigned wrap=0);
|
||||
void typesetGlyphs(const std::wstring& str,
|
||||
const Zeus::CColor& defaultColor=Zeus::CColor::skWhite);
|
||||
const Zeus::CColor& defaultColor=Zeus::CColor::skWhite,
|
||||
unsigned wrap=0);
|
||||
|
||||
void resized(const boo::SWindowRect& rootView, const boo::SWindowRect& sub);
|
||||
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub);
|
||||
void draw(boo::IGraphicsCommandQueue* gfxQ);
|
||||
|
||||
int nominalWidth() const {return m_width;}
|
||||
int nominalHeight() const {return (int(m_lineHeight * m_fontAtlas.FT_LineHeight()) >> 6) * m_lines.size();}
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "ViewResources.hpp"
|
||||
#include "MultiLineTextView.hpp"
|
||||
#include "SplitView.hpp"
|
||||
#include "Tooltip.hpp"
|
||||
#include "FontCache.hpp"
|
||||
#include "DeferredWindowEvents.hpp"
|
||||
#include <boo/boo.hpp>
|
||||
@ -69,6 +70,7 @@ public:
|
||||
|
||||
private:
|
||||
std::unique_ptr<View> m_view;
|
||||
std::unique_ptr<Tooltip> m_tooltip;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -22,6 +22,9 @@ class TextView : public View
|
||||
bool m_valid = false;
|
||||
int m_width = 0;
|
||||
|
||||
friend class MultiLineTextView;
|
||||
static int DoKern(FT_Pos val, const FontAtlas& atlas);
|
||||
|
||||
public:
|
||||
class Resources
|
||||
{
|
||||
|
@ -2,7 +2,6 @@
|
||||
#define SPECTER_TOOLBAR_HPP
|
||||
|
||||
#include "Specter/View.hpp"
|
||||
#include <bitset>
|
||||
|
||||
namespace Specter
|
||||
{
|
||||
|
44
specter/include/Specter/Tooltip.hpp
Normal file
44
specter/include/Specter/Tooltip.hpp
Normal file
@ -0,0 +1,44 @@
|
||||
#ifndef SPECTER_TOOLTIP_HPP
|
||||
#define SPECTER_TOOLTIP_HPP
|
||||
|
||||
#include "Specter/View.hpp"
|
||||
#include "Specter/MultiLineTextView.hpp"
|
||||
|
||||
namespace Specter
|
||||
{
|
||||
|
||||
class Tooltip : public View
|
||||
{
|
||||
ViewBlock m_ttBlock;
|
||||
boo::IGraphicsBufferD* m_ttBlockBuf;
|
||||
SolidShaderVert m_ttVerts[16];
|
||||
int m_nomWidth = 25;
|
||||
int m_nomHeight = 25;
|
||||
|
||||
void setVerts(int width, int height, float pf);
|
||||
|
||||
boo::IGraphicsBufferD* m_ttVertsBuf;
|
||||
boo::IVertexFormat* m_ttVtxFmt; /* OpenGL only */
|
||||
boo::IShaderDataBinding* m_ttShaderBinding;
|
||||
|
||||
std::string m_titleStr;
|
||||
std::unique_ptr<TextView> m_title;
|
||||
std::string m_messageStr;
|
||||
std::unique_ptr<MultiLineTextView> m_message;
|
||||
|
||||
std::unique_ptr<TextView> m_cornersOutline[4];
|
||||
std::unique_ptr<TextView> m_cornersFilled[4];
|
||||
public:
|
||||
Tooltip(ViewResources& res, View& parentView, const std::string& title,
|
||||
const std::string& message);
|
||||
void resized(const boo::SWindowRect& rootView, const boo::SWindowRect& sub);
|
||||
void resetResources(ViewResources& res);
|
||||
void draw(boo::IGraphicsCommandQueue* gfxQ);
|
||||
|
||||
int nominalWidth() const {return m_nomWidth;}
|
||||
int nominalHeight() const {return m_nomHeight;}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // SPECTER_TOOLTIP_HPP
|
@ -124,7 +124,7 @@ public:
|
||||
virtual void mouseMove(const boo::SWindowCoord&) {}
|
||||
virtual void mouseEnter(const boo::SWindowCoord&) {}
|
||||
virtual void mouseLeave(const boo::SWindowCoord&) {}
|
||||
virtual void resized(const boo::SWindowRect &rootView, const boo::SWindowRect& sub);
|
||||
virtual void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub);
|
||||
virtual void resetResources(ViewResources& res) {}
|
||||
virtual void draw(boo::IGraphicsCommandQueue* gfxQ);
|
||||
};
|
||||
|
@ -21,6 +21,7 @@ class ThemeData
|
||||
Zeus::CColor m_button2Press = {0.2823, 0.2823, 0.2823, 1.0};
|
||||
Zeus::CColor m_button1Disabled = {0.2823, 0.2823, 0.2823, 0.5};
|
||||
Zeus::CColor m_button2Disabled = {0.1725, 0.1725, 0.1725, 0.5};
|
||||
Zeus::CColor m_tooltipBg = {0.0, 0.0, 0.0, 0.5};
|
||||
public:
|
||||
virtual const Zeus::CColor& viewportBackground() const {return m_vpBg;}
|
||||
virtual const Zeus::CColor& toolbarBackground() const {return m_tbBg;}
|
||||
@ -33,6 +34,7 @@ public:
|
||||
virtual const Zeus::CColor& button2Press() const {return m_button2Press;}
|
||||
virtual const Zeus::CColor& button1Disabled() const {return m_button1Disabled;}
|
||||
virtual const Zeus::CColor& button2Disabled() const {return m_button2Disabled;}
|
||||
virtual const Zeus::CColor& tooltipBackground() const {return m_tooltipBg;}
|
||||
};
|
||||
|
||||
class ViewResources
|
||||
@ -64,6 +66,8 @@ public:
|
||||
Specter::FontTag m_heading14;
|
||||
Specter::FontTag m_heading18;
|
||||
|
||||
Specter::FontTag m_curveFont;
|
||||
|
||||
ViewResources() = default;
|
||||
ViewResources(const ViewResources& other) = delete;
|
||||
ViewResources(ViewResources&& other) = default;
|
||||
|
@ -21,6 +21,9 @@ extern "C" size_t DROIDSANS_PERMISSIVE_SZ;
|
||||
extern "C" const uint8_t BMONOFONT[];
|
||||
extern "C" size_t BMONOFONT_SZ;
|
||||
|
||||
extern "C" const uint8_t SPECTERCURVES[];
|
||||
extern "C" size_t SPECTERCURVES_SZ;
|
||||
|
||||
extern "C" const FT_Driver_ClassRec tt_driver_class;
|
||||
|
||||
namespace Specter
|
||||
@ -284,6 +287,8 @@ FontAtlas::FontAtlas(boo::IGraphicsDataFactory* gf, FT_Face face, uint32_t dpi,
|
||||
curLineWidth += width + 1;
|
||||
charcode = FT_Get_Next_Char(face, charcode, &gindex);
|
||||
}
|
||||
if (curLineHeight)
|
||||
totalHeight += curLineHeight + 1;
|
||||
m_glyphs.reserve(glyphCount);
|
||||
m_glyphLookup.reserve(glyphCount);
|
||||
|
||||
@ -672,7 +677,8 @@ FontCache::FontCache(const HECL::Runtime::FileStoreManager& fileMgr)
|
||||
: m_fileMgr(fileMgr),
|
||||
m_cacheRoot(m_fileMgr.getStoreRoot() + _S("/fontcache")),
|
||||
m_regFace(m_fontLib, DROIDSANS_PERMISSIVE, DROIDSANS_PERMISSIVE_SZ),
|
||||
m_monoFace(m_fontLib, BMONOFONT, BMONOFONT_SZ)
|
||||
m_monoFace(m_fontLib, BMONOFONT, BMONOFONT_SZ),
|
||||
m_curvesFace(m_fontLib, SPECTERCURVES, SPECTERCURVES_SZ)
|
||||
{HECL::MakeDir(m_cacheRoot.c_str());}
|
||||
|
||||
FontTag FontCache::prepCustomFont(boo::IGraphicsDataFactory* gf, const std::string& name, FT_Face face,
|
||||
|
@ -5,6 +5,127 @@ namespace Specter
|
||||
{
|
||||
static LogVisor::LogModule Log("Specter::MultiLineTextView");
|
||||
|
||||
std::string MultiLineTextView::LineWrap(const std::string& str, int wrap)
|
||||
{
|
||||
size_t rem = str.size();
|
||||
const utf8proc_uint8_t* it = reinterpret_cast<const utf8proc_uint8_t*>(str.data());
|
||||
uint32_t lCh = -1;
|
||||
int adv = 0;
|
||||
|
||||
std::string ret;
|
||||
ret.reserve(str.size());
|
||||
size_t lastSpaceRem;
|
||||
const utf8proc_uint8_t* lastSpaceIt = nullptr;
|
||||
size_t rollbackPos;
|
||||
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')
|
||||
{
|
||||
ret += '\n';
|
||||
lCh = -1;
|
||||
rem -= sz;
|
||||
it += sz;
|
||||
lastSpaceIt = nullptr;
|
||||
adv = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
const FontAtlas::Glyph* glyph = m_fontAtlas.lookupGlyph(ch);
|
||||
if (!glyph)
|
||||
{
|
||||
rem -= sz;
|
||||
it += sz;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lCh != -1)
|
||||
adv += TextView::DoKern(m_fontAtlas.lookupKern(lCh, glyph->m_glyphIdx), m_fontAtlas);
|
||||
adv += glyph->m_advance;
|
||||
|
||||
if (adv > wrap && lastSpaceIt)
|
||||
{
|
||||
ret.assign(ret.cbegin(), ret.cbegin() + rollbackPos);
|
||||
ret += '\n';
|
||||
lCh = -1;
|
||||
rem = lastSpaceRem;
|
||||
it = lastSpaceIt;
|
||||
lastSpaceIt = nullptr;
|
||||
adv = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sz == 1 && (it[0] == ' ' || it[0] == '-'))
|
||||
{
|
||||
lastSpaceIt = it + 1;
|
||||
lastSpaceRem = rem - 1;
|
||||
rollbackPos = ret.size() + 1;
|
||||
}
|
||||
for (size_t i=0 ; i<sz ; ++i)
|
||||
ret += it[i];
|
||||
lCh = glyph->m_glyphIdx;
|
||||
rem -= sz;
|
||||
it += sz;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::wstring MultiLineTextView::LineWrap(const std::wstring& str, int wrap)
|
||||
{
|
||||
uint32_t lCh = -1;
|
||||
int adv = 0;
|
||||
|
||||
std::wstring ret;
|
||||
ret.reserve(str.size());
|
||||
std::wstring::const_iterator lastSpaceIt = str.cend();
|
||||
size_t rollbackPos;
|
||||
for (std::wstring::const_iterator it = str.cbegin() ; it != str.cend() ; ++it)
|
||||
{
|
||||
wchar_t ch = *it;
|
||||
if (ch == L'\n')
|
||||
{
|
||||
ret += L'\n';
|
||||
lCh = -1;
|
||||
lastSpaceIt = str.cend();
|
||||
adv = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
const FontAtlas::Glyph* glyph = m_fontAtlas.lookupGlyph(ch);
|
||||
if (!glyph)
|
||||
continue;
|
||||
|
||||
if (lCh != -1)
|
||||
adv += TextView::DoKern(m_fontAtlas.lookupKern(lCh, glyph->m_glyphIdx), m_fontAtlas);
|
||||
adv += glyph->m_advance;
|
||||
|
||||
if (adv > wrap && lastSpaceIt != str.cend())
|
||||
{
|
||||
ret.assign(ret.cbegin(), ret.cbegin() + rollbackPos);
|
||||
ret += L'\n';
|
||||
lCh = -1;
|
||||
it = lastSpaceIt;
|
||||
lastSpaceIt = str.cend();
|
||||
adv = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ch == L' ' || ch == L'-')
|
||||
{
|
||||
lastSpaceIt = it + 1;
|
||||
rollbackPos = ret.size() + 1;
|
||||
}
|
||||
ret += ch;
|
||||
lCh = glyph->m_glyphIdx;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
MultiLineTextView::MultiLineTextView(ViewResources& res,
|
||||
View& parentView,
|
||||
const FontAtlas& font,
|
||||
@ -31,8 +152,16 @@ MultiLineTextView::MultiLineTextView(ViewResources& res,
|
||||
lineHeight) {}
|
||||
|
||||
void MultiLineTextView::typesetGlyphs(const std::string& str,
|
||||
const Zeus::CColor& defaultColor)
|
||||
const Zeus::CColor& defaultColor,
|
||||
unsigned wrap)
|
||||
{
|
||||
if (wrap)
|
||||
{
|
||||
typesetGlyphs(LineWrap(str, wrap), defaultColor);
|
||||
return;
|
||||
}
|
||||
|
||||
m_width = 0;
|
||||
m_lines.clear();
|
||||
size_t rem = str.size() + 1;
|
||||
const utf8proc_uint8_t* it = reinterpret_cast<const utf8proc_uint8_t*>(str.data());
|
||||
@ -63,6 +192,7 @@ void MultiLineTextView::typesetGlyphs(const std::string& str,
|
||||
{
|
||||
m_lines.emplace_back(new TextView(m_viewSystem, *this, m_fontAtlas, m_lineCapacity));
|
||||
m_lines.back()->typesetGlyphs(std::string((char*)beginIt, it - beginIt), defaultColor);
|
||||
m_width = std::max(m_width, m_lines.back()->nominalWidth());
|
||||
beginIt = it + 1;
|
||||
}
|
||||
rem -= sz;
|
||||
@ -73,8 +203,16 @@ void MultiLineTextView::typesetGlyphs(const std::string& str,
|
||||
}
|
||||
|
||||
void MultiLineTextView::typesetGlyphs(const std::wstring& str,
|
||||
const Zeus::CColor& defaultColor)
|
||||
const Zeus::CColor& defaultColor,
|
||||
unsigned wrap)
|
||||
{
|
||||
if (wrap)
|
||||
{
|
||||
typesetGlyphs(LineWrap(str, wrap), defaultColor);
|
||||
return;
|
||||
}
|
||||
|
||||
m_width = 0;
|
||||
m_lines.clear();
|
||||
size_t rem = str.size() + 1;
|
||||
auto it = str.cbegin();
|
||||
@ -99,6 +237,7 @@ void MultiLineTextView::typesetGlyphs(const std::wstring& str,
|
||||
{
|
||||
m_lines.emplace_back(new TextView(m_viewSystem, *this, m_fontAtlas, m_lineCapacity));
|
||||
m_lines.back()->typesetGlyphs(std::wstring(beginIt, it), defaultColor);
|
||||
m_width = std::max(m_width, m_lines.back()->nominalWidth());
|
||||
beginIt = it + 1;
|
||||
}
|
||||
--rem;
|
||||
|
@ -14,6 +14,8 @@ RootView::RootView(IViewManager& viewMan, ViewResources& res, boo::IWindow* wind
|
||||
m_renderTex = res.m_factory->newRenderTexture(rect.size[0], rect.size[1], 1);
|
||||
commitResources(res);
|
||||
resized(rect, rect);
|
||||
|
||||
m_tooltip.reset(new Tooltip(res, *this, "Test", "Testing"));
|
||||
}
|
||||
|
||||
void RootView::destroyed()
|
||||
@ -30,6 +32,8 @@ void RootView::resized(const boo::SWindowRect& root, const boo::SWindowRect&)
|
||||
View::resized(m_rootRect, m_rootRect);
|
||||
if (m_view)
|
||||
m_view->resized(m_rootRect, m_rootRect);
|
||||
if (m_tooltip)
|
||||
m_tooltip->resized(m_rootRect, m_rootRect);
|
||||
if (old != m_rootRect)
|
||||
m_resizeRTDirty = true;
|
||||
}
|
||||
@ -50,6 +54,18 @@ void RootView::mouseMove(const boo::SWindowCoord& coord)
|
||||
{
|
||||
if (m_view)
|
||||
m_view->mouseMove(coord);
|
||||
|
||||
boo::SWindowRect ttrect = m_rootRect;
|
||||
ttrect.location[0] = coord.pixel[0];
|
||||
ttrect.location[1] = coord.pixel[1];
|
||||
if (m_tooltip)
|
||||
{
|
||||
if (coord.pixel[0] + m_tooltip->nominalWidth() > m_rootRect.size[0])
|
||||
ttrect.location[0] -= m_tooltip->nominalWidth();
|
||||
if (coord.pixel[1] + m_tooltip->nominalHeight() > m_rootRect.size[1])
|
||||
ttrect.location[1] -= m_tooltip->nominalHeight();
|
||||
m_tooltip->resized(m_rootRect, ttrect);
|
||||
}
|
||||
}
|
||||
|
||||
void RootView::mouseEnter(const boo::SWindowCoord& coord)
|
||||
@ -111,6 +127,8 @@ void RootView::resetResources(ViewResources& res)
|
||||
m_viewRes = &res;
|
||||
if (m_view)
|
||||
m_view->resetResources(res);
|
||||
if (m_tooltip)
|
||||
m_tooltip->resetResources(res);
|
||||
}
|
||||
|
||||
void RootView::setContentView(std::unique_ptr<View>&& view)
|
||||
@ -136,6 +154,8 @@ void RootView::draw(boo::IGraphicsCommandQueue* gfxQ)
|
||||
View::draw(gfxQ);
|
||||
if (m_view)
|
||||
m_view->draw(gfxQ);
|
||||
if (m_tooltip)
|
||||
m_tooltip->draw(gfxQ);
|
||||
gfxQ->resolveDisplay(m_renderTex);
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,7 @@ void TextView::Resources::init(boo::GLDataFactory* factory, FontCache* fcache)
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" colorOut = vtf.color;\n"
|
||||
" colorOut.a = texture(fontTex, vtf.uv).r;\n"
|
||||
" colorOut.a *= texture(fontTex, vtf.uv).r;\n"
|
||||
"}\n";
|
||||
|
||||
static const char* FSSubpixel =
|
||||
@ -63,7 +63,7 @@ void TextView::Resources::init(boo::GLDataFactory* factory, FontCache* fcache)
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" colorOut = vtf.color;\n"
|
||||
" blendOut = texture(fontTex, vtf.uv);\n"
|
||||
" blendOut = colorOut.a * texture(fontTex, vtf.uv);\n"
|
||||
"}\n";
|
||||
|
||||
static const char* BlockNames[] = {"SpecterViewBlock"};
|
||||
@ -121,7 +121,7 @@ void TextView::Resources::init(boo::ID3DDataFactory* factory, FontCache* fcache)
|
||||
"float4 main(in VertToFrag vtf) : SV_Target0\n"
|
||||
"{\n"
|
||||
" float4 colorOut = vtf.color;\n"
|
||||
" colorOut.a = fontTex.Sample(samp, vtf.uv).r;\n"
|
||||
" colorOut.a *= fontTex.Sample(samp, vtf.uv).r;\n"
|
||||
" return colorOut;\n"
|
||||
"}\n";
|
||||
|
||||
@ -143,7 +143,7 @@ void TextView::Resources::init(boo::ID3DDataFactory* factory, FontCache* fcache)
|
||||
"{\n"
|
||||
" BlendOut ret;\n"
|
||||
" ret.colorOut = vtf.color;\n"
|
||||
" ret.blendOut = fontTex.Sample(samp, vtf.uv);\n"
|
||||
" ret.blendOut = ret.colorOut.a * fontTex.Sample(samp, vtf.uv);\n"
|
||||
" return ret;\n"
|
||||
"}\n";
|
||||
|
||||
@ -229,7 +229,7 @@ void TextView::Resources::init(boo::MetalDataFactory* factory, FontCache* fcache
|
||||
"fragment float4 fmain(VertToFrag vtf [[ stage_in ]], texture2d_array<float> fontTex [[ texture(0) ]])\n"
|
||||
"{\n"
|
||||
" float4 colorOut = vtf.color;\n"
|
||||
" colorOut.a = fontTex.sample(samp, vtf.uv.xy, vtf.uv.z).r;\n"
|
||||
" colorOut.a *= fontTex.sample(samp, vtf.uv.xy, vtf.uv.z).r;\n"
|
||||
" return colorOut;\n"
|
||||
"}\n";
|
||||
|
||||
@ -329,7 +329,7 @@ TextView::RenderGlyph::RenderGlyph(int& adv, const FontAtlas::Glyph& glyph, cons
|
||||
adv += glyph.m_advance;
|
||||
}
|
||||
|
||||
static int DoKern(FT_Pos val, const FontAtlas& atlas)
|
||||
int TextView::DoKern(FT_Pos val, const FontAtlas& atlas)
|
||||
{
|
||||
if (!val) return 0;
|
||||
val = FT_MulFix(val, atlas.FT_Xscale());
|
||||
@ -387,6 +387,7 @@ void TextView::typesetGlyphs(const std::string& str, const Zeus::CColor& default
|
||||
m_valid = false;
|
||||
updateSize();
|
||||
}
|
||||
|
||||
void TextView::typesetGlyphs(const std::wstring& str, const Zeus::CColor& defaultColor)
|
||||
{
|
||||
uint32_t lCh = -1;
|
||||
|
147
specter/lib/Tooltip.cpp
Normal file
147
specter/lib/Tooltip.cpp
Normal file
@ -0,0 +1,147 @@
|
||||
#include "Specter/Tooltip.hpp"
|
||||
#include "Specter/ViewResources.hpp"
|
||||
#include "Specter/RootView.hpp"
|
||||
|
||||
namespace Specter
|
||||
{
|
||||
|
||||
#define TOOLTIP_MAX_WIDTH 316
|
||||
#define TOOLTIP_MARGIN 8
|
||||
|
||||
Tooltip::Tooltip(ViewResources& res, View& parentView, const std::string& title,
|
||||
const std::string& message)
|
||||
: View(res, parentView), m_titleStr(title), m_messageStr(message)
|
||||
{
|
||||
m_ttBlockBuf = res.m_factory->newDynamicBuffer(boo::BufferUse::Uniform, sizeof(ViewBlock), 1);
|
||||
m_ttVertsBuf = res.m_factory->newDynamicBuffer(boo::BufferUse::Vertex, sizeof(SolidShaderVert), 16);
|
||||
|
||||
if (!res.m_viewRes.m_solidVtxFmt)
|
||||
{
|
||||
boo::VertexElementDescriptor vdescs[] =
|
||||
{
|
||||
{m_ttVertsBuf, nullptr, boo::VertexSemantic::Position4},
|
||||
{m_ttVertsBuf, nullptr, boo::VertexSemantic::Color}
|
||||
};
|
||||
m_ttVtxFmt = res.m_factory->newVertexFormat(2, vdescs);
|
||||
boo::IGraphicsBuffer* bufs[] = {m_ttBlockBuf};
|
||||
m_ttShaderBinding = res.m_factory->newShaderDataBinding(res.m_viewRes.m_solidShader,
|
||||
m_ttVtxFmt, m_ttVertsBuf, nullptr,
|
||||
nullptr, 1, bufs, 0, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
boo::IGraphicsBuffer* bufs[] = {m_ttBlockBuf};
|
||||
m_ttShaderBinding = res.m_factory->newShaderDataBinding(res.m_viewRes.m_solidShader,
|
||||
res.m_viewRes.m_solidVtxFmt,
|
||||
m_ttVertsBuf, nullptr,
|
||||
nullptr, 1, bufs, 0, nullptr);
|
||||
}
|
||||
|
||||
for (int i=0 ; i<16 ; ++i)
|
||||
m_ttVerts[i].m_color = res.themeData().tooltipBackground();
|
||||
|
||||
commitResources(res);
|
||||
resetResources(res);
|
||||
}
|
||||
|
||||
void Tooltip::setVerts(int width, int height, float pf)
|
||||
{
|
||||
int margin = TOOLTIP_MARGIN * pf;
|
||||
width = std::max(width, margin*2);
|
||||
height = std::max(height, margin*2);
|
||||
|
||||
m_ttVerts[0].m_pos.assign(0, height-margin, 0);
|
||||
m_ttVerts[1].m_pos.assign(0, margin, 0);
|
||||
m_ttVerts[2].m_pos.assign(width, height-margin, 0);
|
||||
m_ttVerts[3].m_pos.assign(width, margin, 0);
|
||||
m_ttVerts[4].m_pos.assign(width, margin, 0);
|
||||
|
||||
m_ttVerts[5].m_pos.assign(margin, height, 0);
|
||||
m_ttVerts[6].m_pos.assign(margin, height, 0);
|
||||
m_ttVerts[7].m_pos.assign(margin, height-margin, 0);
|
||||
m_ttVerts[8].m_pos.assign(width-margin, height, 0);
|
||||
m_ttVerts[9].m_pos.assign(width-margin, height-margin, 0);
|
||||
m_ttVerts[10].m_pos.assign(width-margin, height-margin, 0);
|
||||
|
||||
m_ttVerts[11].m_pos.assign(margin, margin, 0);
|
||||
m_ttVerts[12].m_pos.assign(margin, margin, 0);
|
||||
m_ttVerts[13].m_pos.assign(margin, 0, 0);
|
||||
m_ttVerts[14].m_pos.assign(width-margin, margin, 0);
|
||||
m_ttVerts[15].m_pos.assign(width-margin, 0, 0);
|
||||
|
||||
m_ttVertsBuf->load(m_ttVerts, sizeof(SolidShaderVert) * 16);
|
||||
}
|
||||
|
||||
void Tooltip::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub)
|
||||
{
|
||||
View::resized(root, sub);
|
||||
float pf = rootView().viewRes().pixelFactor();
|
||||
setVerts(m_nomWidth, m_nomHeight, pf);
|
||||
m_ttBlock.setViewRect(root, sub);
|
||||
m_ttBlockBuf->load(&m_ttBlock, sizeof(ViewBlock));
|
||||
|
||||
boo::SWindowRect textRect = sub;
|
||||
textRect.location[0] += TOOLTIP_MARGIN * pf;
|
||||
textRect.location[1] += TOOLTIP_MARGIN * 1.5 * pf;
|
||||
m_message->resized(root, textRect);
|
||||
|
||||
textRect.location[1] += m_message->nominalHeight() + TOOLTIP_MARGIN * pf;
|
||||
m_title->resized(root, textRect);
|
||||
|
||||
boo::SWindowRect cornerRect = sub;
|
||||
cornerRect.location[1] += m_nomHeight - TOOLTIP_MARGIN * pf;
|
||||
m_cornersOutline[0]->resized(root, cornerRect);
|
||||
m_cornersFilled[0]->resized(root, cornerRect);
|
||||
cornerRect.location[0] += m_nomWidth - TOOLTIP_MARGIN * pf;
|
||||
m_cornersOutline[1]->resized(root, cornerRect);
|
||||
m_cornersFilled[1]->resized(root, cornerRect);
|
||||
cornerRect.location[1] = sub.location[1];
|
||||
m_cornersOutline[2]->resized(root, cornerRect);
|
||||
m_cornersFilled[2]->resized(root, cornerRect);
|
||||
cornerRect.location[0] = sub.location[0];
|
||||
m_cornersOutline[3]->resized(root, cornerRect);
|
||||
m_cornersFilled[3]->resized(root, cornerRect);
|
||||
}
|
||||
|
||||
void Tooltip::resetResources(ViewResources& res)
|
||||
{
|
||||
for (int i=0 ; i<4 ; ++i)
|
||||
{
|
||||
m_cornersOutline[i].reset(new TextView(res, *this, res.m_curveFont, 1));
|
||||
m_cornersFilled[i].reset(new TextView(res, *this, res.m_curveFont, 1));
|
||||
}
|
||||
m_cornersOutline[0]->typesetGlyphs(L"\xF4F0");
|
||||
m_cornersFilled[0]->typesetGlyphs(L"\xF4F1", res.themeData().tooltipBackground());
|
||||
m_cornersOutline[1]->typesetGlyphs(L"\xF4F2");
|
||||
m_cornersFilled[1]->typesetGlyphs(L"\xF4F3", res.themeData().tooltipBackground());
|
||||
m_cornersOutline[2]->typesetGlyphs(L"\xF4F4");
|
||||
m_cornersFilled[2]->typesetGlyphs(L"\xF4F5", res.themeData().tooltipBackground());
|
||||
m_cornersOutline[3]->typesetGlyphs(L"\xF4F6");
|
||||
m_cornersFilled[3]->typesetGlyphs(L"\xF4F7", res.themeData().tooltipBackground());
|
||||
|
||||
m_title.reset(new TextView(res, *this, res.m_heading14));
|
||||
m_title->typesetGlyphs(m_titleStr);
|
||||
m_message.reset(new MultiLineTextView(res, *this, res.m_mainFont));
|
||||
m_message->typesetGlyphs(m_messageStr, Zeus::CColor::skWhite,
|
||||
int(TOOLTIP_MAX_WIDTH * rootView().viewRes().pixelFactor()));
|
||||
|
||||
float pf = res.pixelFactor();
|
||||
m_nomWidth = std::min(int(TOOLTIP_MAX_WIDTH * pf),
|
||||
int(std::max(m_title->nominalWidth(), m_message->nominalWidth()) + TOOLTIP_MARGIN * 2 * pf));
|
||||
m_nomHeight = m_title->nominalHeight() + m_message->nominalHeight() + TOOLTIP_MARGIN * 3 * pf;
|
||||
}
|
||||
|
||||
void Tooltip::draw(boo::IGraphicsCommandQueue* gfxQ)
|
||||
{
|
||||
gfxQ->setShaderDataBinding(m_ttShaderBinding);
|
||||
gfxQ->setDrawPrimitive(boo::Primitive::TriStrips);
|
||||
gfxQ->draw(0, 16);
|
||||
|
||||
for (int i=0 ; i<4 ; ++i)
|
||||
m_cornersFilled[i]->draw(gfxQ);
|
||||
|
||||
m_title->draw(gfxQ);
|
||||
m_message->draw(gfxQ);
|
||||
}
|
||||
|
||||
}
|
@ -15,6 +15,7 @@ void ViewResources::init(boo::IGraphicsDataFactory* factory, FontCache* fcache,
|
||||
m_monoFont = fcache->prepMonoFont(factory, AllCharFilter, false, 10.f, dpi);
|
||||
m_heading14 = fcache->prepMainFont(factory, LatinAndJapaneseCharFilter, false, 14.f, dpi);
|
||||
m_heading18 = fcache->prepMainFont(factory, LatinAndJapaneseCharFilter, false, 18.f, dpi);
|
||||
m_curveFont = fcache->prepCurvesFont(factory, AllCharFilter, false, 11.f, dpi);
|
||||
m_fontData = factory->commit();
|
||||
switch (factory->platform())
|
||||
{
|
||||
@ -45,6 +46,7 @@ void ViewResources::resetDPI(unsigned dpi)
|
||||
m_monoFont = m_fcache->prepMonoFont(m_factory, AllCharFilter, false, 10.f, dpi);
|
||||
m_heading14 = m_fcache->prepMainFont(m_factory, LatinAndJapaneseCharFilter, false, 14.f, dpi);
|
||||
m_heading18 = m_fcache->prepMainFont(m_factory, LatinAndJapaneseCharFilter, false, 18.f, dpi);
|
||||
m_curveFont = m_fcache->prepCurvesFont(m_factory, AllCharFilter, false, 11.f, dpi);
|
||||
m_fontData = m_factory->commit();
|
||||
m_fcache->closeBuiltinFonts();
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
bintoc(droidsans-permissive.c droidsans-permissive.ttf.gz DROIDSANS_PERMISSIVE)
|
||||
bintoc(bmonofont-i18n.c bmonofont-i18n.ttf.gz BMONOFONT)
|
||||
add_library(SpecterFonts droidsans-permissive.c bmonofont-i18n.c)
|
||||
bintoc(SpecterCurveGlyphs.c SpecterCurveGlyphs.ttf.gz SPECTERCURVES)
|
||||
add_library(SpecterFonts droidsans-permissive.c bmonofont-i18n.c SpecterCurveGlyphs.c)
|
||||
|
BIN
specter/resources/fonts/SpecterCurveGlyphs.ttf.gz
Normal file
BIN
specter/resources/fonts/SpecterCurveGlyphs.ttf.gz
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user