Alignment

    I used alignment earlier, and, I used additional rectangle - build rect on creation time. I thought maybe I can do alignment in other way, but not. Other idea is to use build rect old. I think ` build rect on creation time` is better. All what I need now (add 1 more slVec4f and) is to set position and size of element in class constructor.

    
    //In slGUICommon
    slVec4f m_buildRectOnCreation;
    

    Now I need to create window and button, and save position and size into this rectangle.

    Change SummonWindow

    
    slGUIWindow* slFramework::SummonGUIWindow(const slVec2f& position, const slVec2f& size)
    {
    	slGUIWindow* newWindow = slCreate(position, size);
    	newWindow->SetStyle(slFramework::GetGUIStyle(slGUIStyleTheme::Light));
    	g_framework->m_GUIWindows.push_back(newWindow);
    	return newWindow;
    }
    

    Change Window Constructor

    
    slGUIWindow::slGUIWindow(const slVec2f& position, const slVec2f& size)
    	:
    	slGUICommon(position, size)
    {
    	m_rootElement = dynamic_cast(slCreate(this, position, size));
    }
    

    Change root element constructor

    
    slGUIRootElement::slGUIRootElement(slGUIWindow* w, const slVec2f& position, const slVec2f& size) :
    	slGUIElement::slGUIElement(w, position, size)
    {}
    

    Change button constructor

    
    slGUIButton::slGUIButton(slGUIWindow* w, const slVec2f& position, const slVec2f& size)
    	: 
    	slGUIElement::slGUIElement(w, position, size) 
    {
    	SetParent(w->GetRootElement());
    }
    

    Change gui element constructor

    
    slGUIElement::slGUIElement(slGUIWindow* w, const slVec2f& position, const slVec2f& size):
    	slGUICommon(position, size)
    {
    	SL_ASSERT_ST(w);
    	m_window = w;
    	SetStyle(slFramework::GetGUIStyle(slGUIStyleTheme::Light));
    }
    

    And change slGUICommon constructor

    
    slGUICommon::slGUICommon(const slVec2f& position, const slVec2f& size)
    {
    	m_buildRectOnCreation.x = position.x;
    	m_buildRectOnCreation.y = position.y;
    	m_buildRectOnCreation.z = position.x + size.x;
    	m_buildRectOnCreation.w = position.y + size.y;
    }
    

    And it's not enough. How I can set m_buildRectOnCreation if use m_margin?

    
    auto btn = slCreate(guiWindow);
    btn->m_margin.set(10.f);
    

    Move m_margin in `protected` and add method? And same with m_size?

    Or remove m_margin? If remove, then, if user want that rescale he just need to do it in window callback.

    Really easy to remove margin, because, it gives chaos.

    REMOVED

    How alignment works. For example, Aligment::Top. If button located in left top corner, then if window changed its size (width), it will be bigger, then button must be moved little bit closer to window center (x axis).

    Code

    
    slVec2f parentSize(parent->m_buildRect.z - parent->m_buildRect.x, parent->m_buildRect.w - parent->m_buildRect.y);
    if (parentSize.x && parentSize.y)
    {
    	float parentRectSizeX_1 = 1.f / parentSize.x;
    	float parentRectSizeY_1 = 1.f / parentSize.y;
    
    	slVec2f parentCreationCenter;
    	parentCreationCenter.x = parent->m_buildRectOnCreation.x + ((parent->m_buildRectOnCreation.z - parent->m_buildRectOnCreation.x) * 0.5f);
    	parentCreationCenter.y = parent->m_buildRectOnCreation.y + ((parent->m_buildRectOnCreation.w - parent->m_buildRectOnCreation.y) * 0.5f);
    
    	slVec2f parentCurrentCenter;
    	parentCurrentCenter.x = parent->m_buildRect.x + ((parent->m_buildRect.z - parent->m_buildRect.x) * 0.5f);
    	parentCurrentCenter.y = parent->m_buildRect.y + ((parent->m_buildRect.w - parent->m_buildRect.y) * 0.5f);
    
    	float parentRectSizeDiff_X = parentCurrentCenter.x - parentCreationCenter.x;
    	float parentRectSizeDiff_Y = parentCurrentCenter.y - parentCreationCenter.y;
    
    	// alignment
    	switch (m_alignment)
    	{
    	case slGUIElement::Left:
    		m_buildRect.y += (int)parentRectSizeDiff_Y;
    		m_buildRect.w += (int)parentRectSizeDiff_Y;
    		break;
    	case slGUIElement::Top:
    		m_buildRect.x += (int)parentRectSizeDiff_X;
    		m_buildRect.z += (int)parentRectSizeDiff_X;
    		break;
    	case slGUIElement::Center:
    		m_buildRect.y += (int)parentRectSizeDiff_Y;
    		m_buildRect.w += (int)parentRectSizeDiff_Y;
    		m_buildRect.x += (int)parentRectSizeDiff_X;
    		m_buildRect.z += (int)parentRectSizeDiff_X;
    		break;
    	case slGUIElement::Right:
    		m_buildRect.y += (int)parentRectSizeDiff_Y;
    		m_buildRect.w += (int)parentRectSizeDiff_Y;
    		
    		m_buildRect.x = parent->m_buildRect.z -
    			(parent->m_buildRectOnCreation.z - m_buildRectOnCreation.x) + parent->m_buildRectOnCreation.x;
    
    		m_buildRect.z = parent->m_buildRect.z -
    			(parent->m_buildRectOnCreation.z - m_buildRectOnCreation.z) + parent->m_buildRectOnCreation.x;
    		break;
    	case slGUIElement::Bottom:
    		m_buildRect.x += (int)parentRectSizeDiff_X;
    		m_buildRect.z += (int)parentRectSizeDiff_X;
    
    		m_buildRect.y = parent->m_buildRect.w -
    			(parent->m_buildRectOnCreation.w - m_buildRectOnCreation.y) + parent->m_buildRectOnCreation.y;
    
    		m_buildRect.w = parent->m_buildRect.w -
    			(parent->m_buildRectOnCreation.w - m_buildRectOnCreation.w) + parent->m_buildRectOnCreation.y;
    		break;
    	case slGUIElement::LeftTop:
    		break;
    	case slGUIElement::RightTop:
    		m_buildRect.x = parent->m_buildRect.z -
    			(parent->m_buildRectOnCreation.z - m_buildRectOnCreation.x) + parent->m_buildRectOnCreation.x;
    
    		m_buildRect.z = parent->m_buildRect.z -
    			(parent->m_buildRectOnCreation.z - m_buildRectOnCreation.z) + parent->m_buildRectOnCreation.x;
    		break;
    	case slGUIElement::LeftBottom:
    		m_buildRect.y = parent->m_buildRect.w -
    			(parent->m_buildRectOnCreation.w - m_buildRectOnCreation.y) + parent->m_buildRectOnCreation.y;
    
    		m_buildRect.w = parent->m_buildRect.w -
    			(parent->m_buildRectOnCreation.w - m_buildRectOnCreation.w) + parent->m_buildRectOnCreation.y;
    		break;
    	case slGUIElement::RightBottom:
    		m_buildRect.x = parent->m_buildRect.z -
    			(parent->m_buildRectOnCreation.z - m_buildRectOnCreation.x) + parent->m_buildRectOnCreation.x;
    
    		m_buildRect.z = parent->m_buildRect.z -
    			(parent->m_buildRectOnCreation.z - m_buildRectOnCreation.z) + parent->m_buildRectOnCreation.x;
    		m_buildRect.y = parent->m_buildRect.w -
    			(parent->m_buildRectOnCreation.w - m_buildRectOnCreation.y) + parent->m_buildRectOnCreation.y;
    
    		m_buildRect.w = parent->m_buildRect.w -
    			(parent->m_buildRectOnCreation.w - m_buildRectOnCreation.w) + parent->m_buildRectOnCreation.y;
    		break;
    	default:
    		break;
    	}
    }
    

    Text for button

    Add text position into button

    
    slVec2f m_textPosition;
    

    Add In draw method

    
    if (IsDrawBG())
    {
    	if (IsEnabled())
    	{
    		if (IsClickedLMB())
    		{
    			gs->DrawGUIRectangle(m_buildRect, m_style->m_buttonMousePressBGColor1, m_style->m_buttonMousePressBGColor2, 0, 0);
    			if (m_textDrawCallback)
    				gs->DrawGUIText(m_text.c_str(), m_text.size(), m_textPosition, m_textDrawCallback);
    		}
    		else
    		{
    			if (IsCursorInRect())
    			{
    				gs->DrawGUIRectangle(m_buildRect, m_style->m_buttonMouseHoverBGColor1, m_style->m_buttonMouseHoverBGColor2, 0, 0);
    				if (m_textDrawCallback)
    					gs->DrawGUIText(m_text.c_str(), m_text.size(), m_textPosition, m_textDrawCallback);
    			}
    			else
    			{
    				gs->DrawGUIRectangle(m_buildRect, m_style->m_buttonBGColor1, m_style->m_buttonBGColor2, 0, 0);
    				if (m_textDrawCallback)
    					gs->DrawGUIText(m_text.c_str(), m_text.size(), m_textPosition, m_textDrawCallback);
    			}
    		}
    	}
    	else
    	{
    		gs->DrawGUIRectangle(m_buildRect, m_style->m_buttonDisabledBGColor1, m_style->m_buttonDisabledBGColor2, 0, 0);
    		if (m_textDrawCallback)
    			gs->DrawGUIText(m_text.c_str(), m_text.size(), m_textPosition, m_textDrawCallback);
    	}
    }
    

    I need to set text color. And font. I need to add default font, and default m_textDrawCallback.

    I add new project - tools/resconv. It will put file data into .inl (.h) file.

    
    #include "slowlib.h"
    #include 
    #include "slowlib.base/archive/slArchive.h"
    #include "slowlib.base/gs/slImage.h"
    
    SL_LINK_LIBRARY("slowlib.base")
    
    void to_h(const char* inFile, const char* outFile)
    {
    	FILE* inF = 0;
    	fopen_s(&inF, inFile, "rb");
    	if (inF)
    	{
    		FILE* outF = 0;
    		fopen_s(&outF, outFile, "wb");
    		if (outF)
    		{
    			std::uintmax_t inFileSz = std::filesystem::file_size(inFile);
    			if (inFileSz)
    			{
    				uint8_t* fileData = (uint8_t*)malloc((size_t)inFileSz);
    				if (fileData)
    				{
    					fread(fileData, (size_t)inFileSz, 1, inF);
    
    					int byte_counter = 0;
    					for (uint32_t i = 0; i < inFileSz; ++i)
    					{
    						if (!byte_counter)
    							fprintf(outF, "\t");
    
    						fprintf(outF, "0x%02X, ", ((uint8_t*)fileData)[i]);
    
    						++byte_counter;
    						if (byte_counter == 8)
    						{
    							fprintf(outF, "\r\n");
    							byte_counter = 0;
    						}
    					}
    				}
    			}
    			fclose(outF);
    		}
    
    		fclose(inF);
    	}
    }
    
    class FrameworkCallback : public slFrameworkCallback
    {
    public:
    	FrameworkCallback() {}
    	virtual ~FrameworkCallback() {}
    	virtual void OnMessage() {};
    };
    
    int main()
    {
    	std::filesystem::create_directory("../src/data/");
    	FrameworkCallback fcb;
    	slFramework::Start(&fcb);
    	
    	to_h("../data/fonts/font.png", "../src/data/font.inl");
    	
    	slFramework::Stop();
    
    	return 0;
    }
    

    I don't want to add arg commands right now.

    Create default font. I need to call method, after GS creation, because, I need to create GPU texture

    Add new method in framework

    
    static void InitDefaultFonts(slGS*);
    static slGUIFont* GetDefaultFont(uint32_t);
    ...
    static uint8_t g_defaultFontPNG[] = {
    	#include "../data/font.inl"
    };
    ...
    slGUIFont* slFramework::GetDefaultFont(uint32_t i)
    {
    	return g_framework->m_GUIFontDefault;
    }
    
    void slFramework::InitDefaultFonts(slGS* gs)
    {
    	if (!g_framework->m_GUIFontDefault)
    	{
    		slImage* img = 0;
    
    		for (uint32_t i = 0; i < slFramework::GetImageLoadersNum(); ++i)
    		{
    			auto il = slFramework::GetImageLoader(i);
    			for (uint32_t o = 0; o < il->GetSupportedFilesCount(); ++o)
    			{
    				auto str = il->GetSupportedFileExtension(o);
    				if (str == U"png")
    				{
    					img = il->Load("something/file.png", g_defaultFontPNG, 9065);
    					goto outFromLoops;
    				}
    			}
    		}
    	outFromLoops:;
    		if (!img)
    			return;
    
    		slTextureInfo ti;
    		slTexture* myFontTexture = gs->SummonTexture(img, ti);
    		SLSAFE_DESTROY(img);
    
    		if (!myFontTexture)
    			return;
    
    		g_framework->m_texturesForDestroy.push_back(myFontTexture);
    
    		slGUIFont* myFont = slFramework::SummonFont();
    		myFont->AddTexture(myFontTexture);
    		myFont->AddGlyph(U'A', slVec2f(0, 0), slPoint(11, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'B', slVec2f(10, 0), slPoint(9, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'C', slVec2f(19, 0), slPoint(9, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'D', slVec2f(27, 0), slPoint(11, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'E', slVec2f(37, 0), slPoint(8, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'F', slVec2f(45, 0), slPoint(8, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'G', slVec2f(52, 0), slPoint(11, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'H', slVec2f(62, 0), slPoint(10, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'I', slVec2f(72, 0), slPoint(4, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'J', slVec2f(76, 0), slPoint(6, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'K', slVec2f(82, 0), slPoint(8, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'L', slVec2f(90, 0), slPoint(8, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'M', slVec2f(97, 0), slPoint(13, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'N', slVec2f(110, 0), slPoint(10, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'O', slVec2f(120, 0), slPoint(11, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'P', slVec2f(131, 0), slPoint(8, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'Q', slVec2f(139, 0), slPoint(12, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'R', slVec2f(151, 0), slPoint(8, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'S', slVec2f(159, 0), slPoint(7, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'T', slVec2f(166, 0), slPoint(8, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'U', slVec2f(175, 0), slPoint(8, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'V', slVec2f(184, 0), slPoint(9, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'W', slVec2f(193, 0), slPoint(14, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'X', slVec2f(207, 0), slPoint(9, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'Y', slVec2f(216, 0), slPoint(7, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'Z', slVec2f(224, 0), slPoint(7, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'0', slVec2f(231, 0), slPoint(8, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'1', slVec2f(239, 0), slPoint(7, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'2', slVec2f(247, 0), slPoint(7, 15), 0, slPoint(256, 256));
    
    		myFont->AddGlyph(U'3', slVec2f(1, 20), slPoint(7, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'4', slVec2f(9, 20), slPoint(8, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'5', slVec2f(17, 20), slPoint(8, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'6', slVec2f(25, 20), slPoint(8, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'7', slVec2f(33, 20), slPoint(8, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'8', slVec2f(41, 20), slPoint(8, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'9', slVec2f(49, 20), slPoint(8, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'a', slVec2f(57, 20), slPoint(8, 16), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'b', slVec2f(65, 20), slPoint(8, 16), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'c', slVec2f(73, 20), slPoint(8, 16), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'd', slVec2f(80, 20), slPoint(8, 16), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'e', slVec2f(89, 20), slPoint(8, 16), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'f', slVec2f(96, 20), slPoint(6, 16), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'g', slVec2f(102, 20), slPoint(6, 16), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'h', slVec2f(109, 20), slPoint(7, 16), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'i', slVec2f(117, 20), slPoint(3, 16), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'j', slVec2f(120, 20), slPoint(4, 16), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'k', slVec2f(125, 20), slPoint(7, 16), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'l', slVec2f(132, 20), slPoint(3, 16), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'm', slVec2f(136, 20), slPoint(12, 16), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'n', slVec2f(148, 20), slPoint(8, 16), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'o', slVec2f(157, 20), slPoint(8, 16), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'p', slVec2f(165, 20), slPoint(8, 16), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'q', slVec2f(173, 20), slPoint(8, 16), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'r', slVec2f(182, 20), slPoint(6, 16), 0, slPoint(256, 256));
    		myFont->AddGlyph(U's', slVec2f(188, 20), slPoint(5, 16), 0, slPoint(256, 256));
    		myFont->AddGlyph(U't', slVec2f(194, 20), slPoint(5, 16), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'u', slVec2f(199, 20), slPoint(7, 16), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'v', slVec2f(207, 20), slPoint(7, 16), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'w', slVec2f(214, 20), slPoint(12, 16), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'x', slVec2f(226, 20), slPoint(7, 16), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'y', slVec2f(233, 20), slPoint(7, 16), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'z', slVec2f(240, 20), slPoint(7, 16), 0, slPoint(256, 256));
    
    		myFont->AddGlyph(U'~', slVec2f(1, 39), slPoint(8, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'`', slVec2f(9, 39), slPoint(4, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'!', slVec2f(14, 39), slPoint(4, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'?', slVec2f(19, 39), slPoint(7, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'\'', slVec2f(26, 39), slPoint(4, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'\"', slVec2f(30, 39), slPoint(5, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'@', slVec2f(37, 39), slPoint(13, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'#', slVec2f(50, 39), slPoint(9, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'№', slVec2f(59, 39), slPoint(15, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U';', slVec2f(75, 39), slPoint(3, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U':', slVec2f(80, 39), slPoint(3, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'%', slVec2f(84, 39), slPoint(11, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'&', slVec2f(95, 39), slPoint(10, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'^', slVec2f(106, 39), slPoint(8, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'<', slVec2f(114, 39), slPoint(8, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'>', slVec2f(121, 39), slPoint(8, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'(', slVec2f(130, 39), slPoint(5, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U')', slVec2f(134, 39), slPoint(5, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'[', slVec2f(140, 39), slPoint(5, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U']', slVec2f(144, 39), slPoint(5, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'{', slVec2f(150, 39), slPoint(5, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'}', slVec2f(154, 39), slPoint(5, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'*', slVec2f(160, 39), slPoint(6, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'.', slVec2f(167, 39), slPoint(3, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U',', slVec2f(171, 39), slPoint(3, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'/', slVec2f(174, 39), slPoint(8, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'\\', slVec2f(181, 39), slPoint(8, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'|', slVec2f(189, 39), slPoint(4, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'+', slVec2f(195, 39), slPoint(8, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'-', slVec2f(203, 39), slPoint(5, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'=', slVec2f(208, 39), slPoint(7, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'_', slVec2f(216, 39), slPoint(8, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U'$', slVec2f(233, 39), slPoint(8, 15), 0, slPoint(256, 256));
    		myFont->AddGlyph(U' ', slVec2f(225, 39), slPoint(8, 15), 0, slPoint(256, 256));
    
    		g_framework->m_GUIFontDefault = myFont;
    	}
    }
    

    Default m_textDrawCallback.

    
    // slFramework
    static slGUIDrawTextCallback* GetDefaultDrawTextCallback();
    ...
    slGUIDrawTextCallback* slFramework::GetDefaultDrawTextCallback()
    {
    	return &g_framework->m_defaultDrawTextCallback;
    }
    // callback
    class DefaultGUIDrawTextCallback : public slGUIDrawTextCallback
    {
    public:
    	DefaultGUIDrawTextCallback() {}
    	virtual ~DefaultGUIDrawTextCallback() {}
    
    	virtual slGUIFont* OnFont(char32_t) final;
    	virtual slColor* OnColor(char32_t) final;
    };
    ...
    slGUIFont* DefaultGUIDrawTextCallback::OnFont(char32_t i) {
    	return g_framework->m_GUIFontDefault;
    }
    
    slColor* DefaultGUIDrawTextCallback::OnColor(char32_t i) {
    	return &g_framework->m_colorWhite;
    }
    

    But, I still have problem. I need to change text color in button, when mouse cursor above button.

    I need to create default drawtextcallback inside button?

    I think, I need to create special class for button, and in future, special classes for all GUI elements.

    OR. Just like this:

    Modify slGUIDrawTextCallback

    
    enum {
    	Reason_default,
    	Reason_mouseEnter,
    	Reason_mouseLeave,
    	Reason_mouseAbove,
    	Reason_pressed,
    	Reason_active,
    	Reason_disabled,
    	/*Reason_, // others
    	Reason_,*/
    };
    
    uint32_t m_reason = Reason_default;
    virtual slGUIFont* OnFont(uint32_t, char32_t) = 0;
    virtual slColor* OnColor(uint32_t, char32_t) = 0;
    

    Modify slGUIButton::Draw

    
    if (IsEnabled())
    {
    	if (IsClickedLMB())
    	{
    		gs->DrawGUIRectangle(m_buildRect, m_style->m_buttonMousePressBGColor1, m_style->m_buttonMousePressBGColor2, 0, 0);
    		m_textDrawCallback->m_reason = slGUIDrawTextCallback::Reason_pressed;
    		gs->DrawGUIText(m_text.c_str(), m_text.size(), m_textPosition, m_textDrawCallback);
    	}
    	else
    	{
    		if (IsCursorInRect())
    		{
    			gs->DrawGUIRectangle(m_buildRect, m_style->m_buttonMouseHoverBGColor1, m_style->m_buttonMouseHoverBGColor2, 0, 0);
    			m_textDrawCallback->m_reason = slGUIDrawTextCallback::Reason_mouseAbove;
    			gs->DrawGUIText(m_text.c_str(), m_text.size(), m_textPosition, m_textDrawCallback);
    		}
    		else
    		{
    			gs->DrawGUIRectangle(m_buildRect, m_style->m_buttonBGColor1, m_style->m_buttonBGColor2, 0, 0);
    			m_textDrawCallback->m_reason = slGUIDrawTextCallback::Reason_default;
    			gs->DrawGUIText(m_text.c_str(), m_text.size(), m_textPosition, m_textDrawCallback);
    		}
    	}
    }
    else
    {
    	gs->DrawGUIRectangle(m_buildRect, m_style->m_buttonDisabledBGColor1, m_style->m_buttonDisabledBGColor2, 0, 0);
    	m_textDrawCallback->m_reason = slGUIDrawTextCallback::Reason_disabled;
    	gs->DrawGUIText(m_text.c_str(), m_text.size(), m_textPosition, m_textDrawCallback);
    }
    

    But I still need to add default callback class for button...

    
    class slGUIButtonTextDrawCallback : public slGUIDrawTextCallback
    {
    public:
    	slGUIButtonTextDrawCallback() {}
    	virtual ~slGUIButtonTextDrawCallback() {}
    
    	virtual slGUIFont* OnFont(uint32_t r, char32_t) override;
    	virtual slColor* OnColor(uint32_t r, char32_t) override;
    };
    
    class slGUIButton : public slGUIElement
    {
    	slString m_text;
    	slVec2f m_textPosition;
    	slGUIButtonTextDrawCallback m_defaultTextDrawCallback; // new
    ...
    slGUIFont* slGUIButtonTextDrawCallback::OnFont(uint32_t r, char32_t)
    {
    	return slFramework::GetDefaultFont(0);
    }
    
    slColor* slGUIButtonTextDrawCallback::OnColor(uint32_t r, char32_t)
    {
    	switch (r)
    	{
    	case slGUIDrawTextCallback::Reason_pressed:
    		return &m_button->GetStyle()->m_buttonMousePressTextColor;
    	case slGUIDrawTextCallback::Reason_mouseAbove:
    		return &m_button->GetStyle()->m_buttonMouseHoverTextColor;
    	case slGUIDrawTextCallback::Reason_disabled:
    		return &m_button->GetStyle()->m_buttonDisabledTextColor;
    	}
    	return &m_button->GetStyle()->m_buttonTextColor;
    }
    
    slGUIButton::slGUIButton(slGUIWindow* w, const slVec2f& position, const slVec2f& size)
    	: 
    	slGUIElement::slGUIElement(w, position, size) 
    {
    	SetParent(w->GetRootElement());
    	m_defaultTextDrawCallback.m_button = this;
    	m_textDrawCallback = dynamic_cast(&m_defaultTextDrawCallback);
    }
    

    Now it works. I not very much like it, but I WANT to be able to set color and font to each symbol.

    Another thing - I need to get text size. In pixels. Because I need to move text in left top corner of buildRect, and I need to know height. Get whole size, not just height.

    
    // slGUIDrawTextCallback
    virtual slVec2f GetTextSize(const char32_t* text)
    {
    	slVec2f sz, position;
    	slVec4f rct;
    	if (text)
    	{
    		if (text[0] != 0)
    		{
    			const char32_t* p = &text[0u];
    			while ((size_t)*p++)
    			{
    				auto font = OnFont(Reason_default, *p);
    				slGUIFontGlyph* g = font->GetGlyphMap()[*p];
    
    				rct.x = position.x;
    				rct.y = position.y;
    
    				rct.z = rct.x + g->m_width;
    				rct.w = rct.y + g->m_height;
    
    				position.x += g->m_width + g->m_overhang + g->m_underhang + font->m_characterSpacing;
    
    				switch (*p)
    				{
    				case U' ':
    					position.x += font->m_spaceSize;
    					break;
    				case U'\t':
    					position.x += font->m_tabSize;
    					break;
    				case U'\n':
    					position.y += font->m_lineSpacing + font->GetMaxSize().y;
    					position.x = 0.f;
    					break;
    				}
    
    				if (position.x > sz.x) sz.x = position.x;
    				if (position.y > sz.y) sz.y = position.y;
    				if (g->m_height > sz.y) sz.y = (float)g->m_height;
    			}
    		}
    	}
    	return sz;
    }
    

    In button

    
    void slGUIButton::UpdateTextPosition()
    {
    	m_textPosition.x = m_buildRect.x;
    	m_textPosition.y = m_buildRect.y + m_textDrawCallback->GetTextSize(m_text.c_str()).y;
    }
    
    void slGUIButton::SetText(const slString& s)
    {
    	m_text = s;
    	UpdateTextPosition();
    }
    

    Move text in center

    
    void slGUIButton::UpdateTextPosition()
    {
    	m_textPosition.x = m_buildRect.x;
    	m_textPosition.y = m_buildRect.y;
    	
    	auto tsz = m_textDrawCallback->GetTextSize(m_text.c_str());
    	m_textPosition.y = m_buildRect.y + tsz.y;
    
    	slVec2f buttonCenter;
    	buttonCenter.x = (m_buildRect.z - m_buildRect.x) * 0.5f;
    	buttonCenter.y = (m_buildRect.w - m_buildRect.y) * 0.5f;
    
    	slVec2f textHalfLen;
    	textHalfLen.x = tsz.x * 0.5f;
    	textHalfLen.y = tsz.y * 0.5f;
    
    	m_textPosition.x = m_buildRect.x + buttonCenter.x - textHalfLen.x;
    	m_textPosition.y = m_buildRect.y + buttonCenter.y - textHalfLen.y;
    }
    

    Download