StudioCherno / Walnut

Walnut is a simple application framework for Vulkan and Dear ImGui apps
MIT License
2.11k stars 391 forks source link

Custom logo on the custom titlebar #75

Open AdamAlNajar opened 6 months ago

AdamAlNajar commented 6 months ago

Hi, i want to put a custom logo of mine on the custom titlebar, if you didnt understand : i want to change the Walnut logo on the custom titlebar for my logo :

image

i also have a few questions : how do i need to format my image? do i need to make custom images for each size? what do i need to change in my code? what else do i need?

lknknm commented 4 months ago

Hello @AdamAlNajar , I don't know if your issue was already solved, but after experimenting a bit with the WalnutApp, I was able to find a solution for placing a custom logo on the custom titlebar. I am not a project maintainer, however, but I will describe here my process so you can replicate and I will leave here to help other users.

Firstly, it is important that you fork the repository, even if you are using it as a submodule for any application you might build upon Walnut. I wasn't able to expose the GUI settings to the application itself, so changing the code from the Walnut submodule was a more practical solution to me.

The GUI is controlled by the Application class, found specifically in the ApplicationGUI.h and ApplicationGUI.cpp files. In the cpp file, you will find the void Application::UI_DrawTitlebar(float& outTitlebarHeight) function, that will specify how the titlebar is being drawn. Inside this function, you'll find the following:

// Logo
{
    const int logoWidth = 30;// m_LogoTex->GetWidth();
    const int logoHeight = 30;// m_LogoTex->GetHeight();
    const ImVec2 logoOffset(16.0f + windowPadding.x, 12.0f + windowPadding.y + titlebarVerticalOffset);
    const ImVec2 logoRectStart = { ImGui::GetItemRectMin().x + logoOffset.x, ImGui::GetItemRectMin().y + logoOffset.y };
    const ImVec2 logoRectMax = { logoRectStart.x + logoWidth, logoRectStart.y + logoHeight };
    fgDrawList->AddImage(m_AppHeaderIcon->GetDescriptorSet(), logoRectStart, logoRectMax);
}

As you can see, this part of the code will stablish the logoWidth and logoHeight, padding and other parameters, as well as use the fgDrawList->AddImage(); function to load the image file into memory (See Image Loading and Displaying Examples for more info).

The m_AppHeaderIcon is being loaded inside the function void Application::Init() (still in the ApplicationGUI.cpp file):

// Load images
{
    uint32_t w, h;
    void* data = Image::Decode(g_WalnutIcon, sizeof(g_WalnutIcon), w, h);
    m_AppHeaderIcon = std::make_shared<Walnut::Image>(w, h, ImageFormat::RGBA, data);
    free(data);
}

This means the Image::Decode() is decoding the g_WalnutIcon file, included as #include "Walnut/Embed/Walnut-Icon.embed". and loading it into memory from the hexadecimal array g_WalnutIcon. You can convert a PNG bin file to a Hexadecimal array using xxd in Linux, but I've used FileToC Tool.

My application logo to the converted HEX array in the Walnut-Icon.embed file looks like this (I just left it named g_WalnutIcon[] for now):

const uint8_t g_WalnutIcon[] =
{
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 
0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x0a, 0x08, 0x06, 0x00, 0x00, 0x00, 0x5b, 0x97, 0x15, 
0xd8, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 
0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 
0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 
0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0xbc, 0x49, 0x44, 0x41, 0x54, 0x78, 0x01, 0x95, 0x52, 0x81, 
0x0d, 0xc3, 0x20, 0x0c, 0x83, 0x5d, 0xd0, 0x0f, 0xc6, 0x09, 0x3d, 0x65, 0x1f, 0xd0, 0x4f, 0x60, 
0x17, 0x75, 0x1f, 0xd0, 0x0f, 0xd8, 0x07, 0x3d, 0xa1, 0xfb, 0x20, 0x0b, 0x92, 0x51, 0x53, 0x46, 
0x56, 0xd5, 0x52, 0x44, 0x12, 0x39, 0x4e, 0x02, 0x18, 0x03, 0x10, 0xd1, 0xc4, 0x96, 0x68, 0x47, 
0xf1, 0xbd, 0xe9, 0xa0, 0xc3, 0xcd, 0x3f, 0x5c, 0x4e, 0x44, 0xd2, 0x51, 0x0a, 0x1c, 0x78, 0xae, 
0x11, 0x6b, 0x11, 0x65, 0xd7, 0x8a, 0xc0, 0x76, 0x67, 0x1b, 0x91, 0x5f, 0x91, 0x5f, 0x21, 0x58, 
0xe3, 0xad, 0xe1, 0x06, 0xa1, 0xe1, 0x8d, 0xe8, 0x1c, 0x3a, 0x6b, 0x4a, 0x21, 0x92, 0x0d, 0x3a, 
0xdc, 0x2a, 0x9c, 0x8c, 0x20, 0x3b, 0xe5, 0xfe, 0x46, 0x4c, 0x76, 0xc6, 0x73, 0x95, 0x70, 0x93, 
0xf9, 0x1e, 0xd9, 0x5a, 0xfb, 0xe6, 0xe3, 0x89, 0xf0, 0xc3, 0x36, 0x98, 0x13, 0x14, 0xd1, 0x05, 
0xfe, 0xa4, 0x74, 0x9f, 0x11, 0xbe, 0x20, 0x38, 0x2b, 0xd3, 0xd6, 0xfa, 0xa5, 0x14, 0x3e, 0xc4, 
0x6a, 0x11, 0xeb, 0x3a, 0xf8, 0x9b, 0xb8, 0xc7, 0x81, 0x8e, 0x0f, 0xe5, 0x1b, 0xee, 0xfe, 0x50, 
0x98, 0x28, 0x90, 0x8e, 0x44, 0xc7, 0x2f, 0x95, 0xff, 0x70, 0x43, 0xbb, 0xea, 0xd5, 0xcf, 0x9f, 
0x35, 0xee, 0x17, 0x54, 0x7d, 0xe2, 0xb2, 0xed, 0x76, 0xab, 0x73, 0x00, 0x00, 0x00, 0x00, 0x49, 
0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};

After some tweaking in the logoWidth and logoHeight, padding and other minor adjustments, I was able to produce the following result:

image

TL;DR/In-a-Hurry: Basically you just have to convert your PNG binary to a hexadecimal array, place it into the g_WalnutIcon array in the Walnut-Icon.embed file and tweak it inside ApplicationGUI.cpp

Hope this helps!

AdamAlNajar commented 1 month ago

thx u