feat: learn page polish

This commit is contained in:
Hyblocker committed 2026-08-17 22:52:07 +02:00
1 parent 9ae08a9ff3
commit af18a4ec31
8 files changed
+121 -60

No files matched your search

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

+81 -8
View File
@@ -10,8 +10,7 @@ namespace ImGui::fonts {
static ImVector<ImRect> s_GroupPanelLabelStack;
void ImGui::BeginGroupPanel(const char* name, const ImVec2& size)
{
void ImGui::BeginGroupPanel(const char* name, const ImVec2& size) {
ImGui::BeginGroup();
auto cursorPos = ImGui::GetCursorScreenPos();
@@ -60,8 +59,7 @@ void ImGui::BeginGroupPanel(const char* name, const ImVec2& size)
s_GroupPanelLabelStack.push_back(ImRect(labelMin, labelMax));
}
void ImGui::EndGroupPanel()
{
void ImGui::EndGroupPanel() {
ImGui::PopItemWidth();
auto itemSpacing = ImGui::GetStyle().ItemSpacing;
@@ -137,14 +135,14 @@ bool ImGui::CheckboxWithDescription(const char* title, bool* v, const char* desc
ImVec2 startPos = ImGui::GetCursorPos();
float contentWidth = ImGui::GetContentRegionAvail().x;
bool changed = ImGui::Checkbox(fmt::format("##{}", title).c_str(), v);
ImGui::SameLine();
float yOffsetToTop = ImGui::GetStyle().FramePadding.y +
(ImGui::GetFrameHeight() - (ImGui::GetStyle().FramePadding.y * 2.0f) - ImGui::GetTextLineHeight()) * 0.5f;
ImGui::SetCursorPosY(ImGui::GetCursorPosY() - yOffsetToTop);
ImGui::BeginGroup();
ImGui::TextUnformatted(title);
ImGui::SetCursorPosY(ImGui::GetCursorPosY() - ImGui::GetStyle().ItemSpacing.y + 2.0f);
@@ -160,7 +158,7 @@ bool ImGui::CheckboxWithDescription(const char* title, bool* v, const char* desc
*v = !(*v);
changed = true;
}
ImGui::SetCursorPos(endPos);
ImGui::Spacing();
return changed;
@@ -219,4 +217,79 @@ void ImGui::PillText(const char* text, const ImVec4& bgColor, const ImVec4& text
const ImVec2 textPos = ImVec2(bb.Min.x + padding.x, bb.Min.y + padding.y);
window->DrawList->AddText(textPos, ImGui::ColorConvertFloat4ToU32(textColor), text);
}
bool ImGui::InformationButton(const char* icon, const char* title, const char* desc, ImTextureID previewTex, ImVec2 previewSize) {
bool clicked = false;
ImGui::PushID(title);
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2(ImGui::GetStyle().ItemInnerSpacing.x, 0.0f));
bool open = ImGui::BeginCard("##card", ImVec2(0.0f, 0.0f), ImGuiChildFlags_Borders | ImGuiChildFlags_AutoResizeY);
if (open) {
ImVec2 startPos = ImGui::GetCursorPos();
bool isHovered = ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows);
bool isMouseDown = ImGui::IsMouseDown(ImGuiMouseButton_Left);
if (isHovered) {
ImU32 hoverCol = isMouseDown
? ImGui::GetColorU32(ImGuiCol_HeaderActive)
: ImGui::GetColorU32(ImGuiCol_HeaderHovered);
ImVec2 pMin = ImGui::GetWindowPos();
ImVec2 pMax = ImVec2(pMin.x + ImGui::GetWindowWidth(), pMin.y + ImGui::GetWindowHeight());
ImGui::GetWindowDrawList()->AddRectFilled(pMin, pMax, hoverCol, 6.0f);
}
int columns = previewTex ? 2 : 1;
if (ImGui::BeginTable("##layout", columns, ImGuiTableFlags_SizingStretchProp)) {
if (previewTex) {
ImGui::TableSetupColumn(nullptr, ImGuiTableColumnFlags_WidthFixed, previewSize.x);
}
ImGui::TableSetupColumn(nullptr, ImGuiTableColumnFlags_WidthStretch);
if (previewTex) {
ImGui::TableNextColumn();
float availX = ImGui::GetContentRegionAvail().x;
if (availX > previewSize.x) {
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + (availX - previewSize.x));
}
ImGui::Image(previewTex, previewSize);
}
ImGui::TableNextColumn();
if (icon && *icon) {
ImGui::TextHeading("%s %s", icon, title);
}
else {
ImGui::TextHeading("%s", title);
}
if (desc && *desc) {
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyle().Colors[ImGuiCol_TextDisabled]);
ImGui::TextWrapped("%s", desc);
ImGui::PopStyleColor();
}
ImGui::EndTable();
}
float contentHeight = ImGui::GetCursorPosY() - startPos.y - ImGui::GetStyle().ItemSpacing.y;
ImGui::SetCursorPos(startPos);
ImGui::SetNextItemAllowOverlap();
clicked = ImGui::InvisibleButton("##card_button", ImVec2(ImGui::GetContentRegionAvail().x, contentHeight));
ImGui::SetCursorPosY(startPos.y + contentHeight);
}
ImGui::EndCard();
ImGui::PopStyleVar();
ImGui::PopID();
return clicked;
}
+1 -40
View File
@@ -154,46 +154,7 @@ namespace ImGui
ImGui::PopStyleColor(5);
}
// @TODO: polish these cards
inline bool InformationButton(const char* icon, const char* title, const char* desc, ImTextureID previewTex, ImVec2 previewSize) {
bool clicked = false;
std::string id = fmt::format("id__{}", title);
if (BeginCard(id.c_str(), ImVec2(0.0f, 0.0f), ImGuiChildFlags_Borders | ImGuiChildFlags_AutoResizeY)) {
ImVec2 avail = ImGui::GetContentRegionAvail();
ImGui::SetNextItemAllowOverlap();
if (ImGui::Selectable(fmt::format("##sel_{}", id).c_str(), false, ImGuiSelectableFlags_SpanAllColumns, ImVec2(0, avail.y))) {
clicked = true;
}
ImGui::SetCursorPos(ImGui::GetStyle().WindowPadding);
if (ImGui::BeginTable(fmt::format("table_{}", id).c_str(), 2, ImGuiTableFlags_SizingStretchSame)) {
ImGui::TableNextColumn();
ImGui::TextHeading("%s %s", icon, title);
ImGui::Spacing();
ImGui::TextDisabled("%s", desc);
ImGui::TableNextColumn();
if (previewTex) {
float availX = ImGui::GetContentRegionAvail().x;
if (availX > previewSize.x) {
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + (availX - previewSize.x));
}
ImGui::Image(previewTex, previewSize);
}
ImGui::EndTable();
}
EndCard();
}
return clicked;
}
bool InformationButton(const char* icon, const char* title, const char* desc, ImTextureID previewTex, ImVec2 previewSize);
bool CheckboxWithDescription(const char* title, bool* v, const char* desc);
bool RadioButtonWithDescription(const char* title, bool v, const char* desc);
+35 -12
View File
@@ -735,6 +735,7 @@ namespace spacecal {
for (size_t i = 0; i < dwNumCalibrations; i++) {
spacecal::TrackingSystemCalibration& calibration = spacecal::CalibrationManager::getInstance()->getCalibration(i);
ImGui::PushID(fmt::format("calibration_id__{}", i).c_str());
std::string szCalibrationStatusIcon = "";
std::string szCalibrationStatusMessage = "";
@@ -885,6 +886,8 @@ namespace spacecal {
buildDeviceSelection(calibration);
buildCalibrationCommonControls(calibration);
}
ImGui::PopID();
}
}
}
@@ -1534,40 +1537,55 @@ namespace spacecal {
default:
case LearnPage_Home:
{
// @TODO: image loading
constexpr float k_PREVIEW_IMAGE_SIZE_PIXELS = 140.0f;
constexpr float k_CELL_PADDING = 4.0f;
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2(k_CELL_PADDING, k_CELL_PADDING));
ImGui::BeginTable("ui_learn_toc_cards", 2, ImGuiTableFlags_None);
ImGui::TableNextColumn();
if (ImGui::InformationButton(ICON_MS_TARGET,
LOCALE_GET("learn_card_standard_calibration").c_str(),
LOCALE_GET("learn_card_standard_calibration_description").c_str(),
ImTextureID_Invalid,
ImVec2(120.0f, 80.0f))
g_state.textures[EImageId_Learn_Preview_Standard].hTexture,
ImVec2(k_PREVIEW_IMAGE_SIZE_PIXELS, k_PREVIEW_IMAGE_SIZE_PIXELS))
) {
g_state.dwSelectedLearnPage = LearnPage_Standard;
}
if (ImGui::InformationButton(ICON_MS_TARGET,
ImGui::TableNextColumn();
if (ImGui::InformationButton(ICON_MS_CYCLE,
LOCALE_GET("learn_card_continuous_calibration").c_str(),
LOCALE_GET("learn_card_continuous_calibration_description").c_str(),
ImTextureID_Invalid,
ImVec2(120.0f, 80.0f))
g_state.textures[EImageId_Learn_Preview_Continuous].hTexture,
ImVec2(k_PREVIEW_IMAGE_SIZE_PIXELS, k_PREVIEW_IMAGE_SIZE_PIXELS))
) {
g_state.dwSelectedLearnPage = LearnPage_Continuous;
}
if (ImGui::InformationButton(ICON_MS_TARGET,
ImGui::TableNextColumn();
if (ImGui::InformationButton(ICON_MS_SENSORS,
LOCALE_GET("learn_card_base_station_management").c_str(),
LOCALE_GET("learn_card_base_station_management_description").c_str(),
ImTextureID_Invalid,
ImVec2(120.0f, 80.0f))
g_state.textures[EImageId_Learn_Preview_BaseStations].hTexture,
ImVec2(k_PREVIEW_IMAGE_SIZE_PIXELS, k_PREVIEW_IMAGE_SIZE_PIXELS))
) {
g_state.dwSelectedLearnPage = LearnPage_BaseStations;
}
if (ImGui::InformationButton(ICON_MS_TARGET,
ImGui::TableNextColumn();
if (ImGui::InformationButton(ICON_MS_HANDHELD_CONTROLLER,
LOCALE_GET("learn_card_ui_tour").c_str(),
LOCALE_GET("learn_card_ui_tour_description").c_str(),
ImTextureID_Invalid,
ImVec2(120.0f, 80.0f))
g_state.textures[EImageId_Learn_Preview_UITour].hTexture,
ImVec2(k_PREVIEW_IMAGE_SIZE_PIXELS, k_PREVIEW_IMAGE_SIZE_PIXELS))
) {
g_state.dwSelectedLearnPage = LearnPage_UITour;
}
ImGui::PopStyleVar();
ImGui::EndTable();
break;
}
case LearnPage_Standard:
@@ -1878,6 +1896,11 @@ namespace spacecal {
g_state.textures[EImageId_LearnUI_Unk0] = renderer::getRenderContext(renderer::GraphicsBackend::OpenGL)->loadTexture(util::getSpaceCalibratorImagesDir() / "img_learn_ui_0.png");
g_state.textures[EImageId_LearnUI_Unk1] = renderer::getRenderContext(renderer::GraphicsBackend::OpenGL)->loadTexture(util::getSpaceCalibratorImagesDir() / "img_learn_ui_1.png");
g_state.textures[EImageId_Learn_Preview_Standard] = renderer::getRenderContext(renderer::GraphicsBackend::OpenGL)->loadTexture(util::getSpaceCalibratorImagesDir() / "img_learn_preview_standard.png");
g_state.textures[EImageId_Learn_Preview_Continuous] = renderer::getRenderContext(renderer::GraphicsBackend::OpenGL)->loadTexture(util::getSpaceCalibratorImagesDir() / "img_learn_preview_continuous.png");
g_state.textures[EImageId_Learn_Preview_BaseStations] = renderer::getRenderContext(renderer::GraphicsBackend::OpenGL)->loadTexture(util::getSpaceCalibratorImagesDir() / "img_learn_preview_basestations.png");
g_state.textures[EImageId_Learn_Preview_UITour] = renderer::getRenderContext(renderer::GraphicsBackend::OpenGL)->loadTexture(util::getSpaceCalibratorImagesDir() / "img_learn_preview_uitour.png");
if (g_state.aBaseStations.capacity() == 0) {
g_state.aBaseStations.reserve(64);
}
+4
View File
@@ -42,6 +42,10 @@ namespace spacecal {
EImageId_LearnBaseStation_20,
EImageId_LearnUI_Unk0,
EImageId_LearnUI_Unk1,
EImageId_Learn_Preview_Standard,
EImageId_Learn_Preview_Continuous,
EImageId_Learn_Preview_BaseStations,
EImageId_Learn_Preview_UITour,
EImageId_Count,
};