diff --git a/MS Sans Serif Bold.ttf b/MS Sans Serif Bold.ttf new file mode 100644 index 000000000..b91b8faf8 Binary files /dev/null and b/MS Sans Serif Bold.ttf differ diff --git a/MS Sans Serif.ttf b/MS Sans Serif.ttf new file mode 100644 index 000000000..fa521b239 Binary files /dev/null and b/MS Sans Serif.ttf differ diff --git a/imconfig.h b/imconfig.h index d556cbaf1..13e5d7a5f 100644 --- a/imconfig.h +++ b/imconfig.h @@ -14,6 +14,8 @@ #pragma once +#define WIN98 + //---- Define assertion handler. Defaults to calling assert(). // If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement. //#define IM_ASSERT(_EXPR) MyAssert(_EXPR) diff --git a/imgui.cpp b/imgui.cpp index 76da8c68d..5b9c5f7da 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3523,8 +3523,12 @@ void ImGui::RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border, const float border_size = g.Style.FrameBorderSize; if (border && border_size > 0.0f) { +#ifdef WIN98 + WinAddRect(p_min, p_max, true); +#else window->DrawList->AddRect(p_min + ImVec2(1, 1), p_max + ImVec2(1, 1), GetColorU32(ImGuiCol_BorderShadow), rounding, 0, border_size); window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, 0, border_size); +#endif } } @@ -6193,7 +6197,48 @@ static inline void ClampWindowPos(ImGuiWindow* window, const ImRect& visibility_ window->Pos = ImClamp(window->Pos, visibility_rect.Min - size_for_clamping, visibility_rect.Max); } -static void RenderWindowOuterSingleBorder(ImGuiWindow* window, int border_n, ImU32 border_col, float border_size) +void ImGui::WinAddRect(const ImVec2& min, const ImVec2& max, bool inset) +{ + ImU32 top_left = IM_COL32(255,255,255,255); + ImU32 bottom_right = IM_COL32(0,0,0,255); + ImU32 top_left_inner = IM_COL32(223,223,223,255); + ImU32 bottom_right_inner = IM_COL32(128,128,128,255); + + if (inset) { + ImU32 tmp = top_left; top_left = bottom_right; bottom_right = tmp; + tmp = top_left_inner; top_left_inner = bottom_right_inner; bottom_right_inner = tmp; + } + + // ImU32 fill_col = IM_COL32(192,192,192,255); + + ImDrawList* draw_list = ImGui::GetWindowDrawList(); + ImVec2 a = min + ImVec2(0.5f, 0.5f); + ImVec2 b = max - ImVec2(0.5f, 0.5f); + + draw_list->PathLineTo(ImVec2(a.x, b.y)); + draw_list->PathLineTo(a); + draw_list->PathLineTo(ImVec2(b.x, a.y)); + draw_list->PathStroke(top_left, false, 1.0f); + + draw_list->PathLineTo(ImVec2(a.x, b.y)); + draw_list->PathLineTo(b); + draw_list->PathLineTo(ImVec2(b.x, a.y)); + draw_list->PathStroke(bottom_right, false, 1.0f); + + + draw_list->PathLineTo(ImVec2(a.x, b.y) + ImVec2(1, -1)); + draw_list->PathLineTo(a + ImVec2(1, 1)); + draw_list->PathLineTo(ImVec2(b.x, a.y) + ImVec2(-1, 1)); + draw_list->PathStroke(top_left_inner, false, 1.0f); + + draw_list->PathLineTo(ImVec2(a.x, b.y) + ImVec2(1, -1)); + draw_list->PathLineTo(b + ImVec2(-1, -1)); + draw_list->PathLineTo(ImVec2(b.x, a.y) + ImVec2(-1, 1)); + draw_list->PathStroke(bottom_right_inner, false, 1.0f); +} + +#ifndef WIN98 +static void RenderWindowOuterSingleBorder(ImGuiWindow * window, int border_n, ImU32 border_col, float border_size) { const ImGuiResizeBorderDef& def = resize_border_def[border_n]; const float rounding = window->WindowRounding; @@ -6202,12 +6247,19 @@ static void RenderWindowOuterSingleBorder(ImGuiWindow* window, int border_n, ImU window->DrawList->PathArcTo(ImLerp(border_r.Min, border_r.Max, def.SegmentN2) + ImVec2(0.5f, 0.5f) + def.InnerDir * rounding, rounding, def.OuterAngle, def.OuterAngle + IM_PI * 0.25f); window->DrawList->PathStroke(border_col, ImDrawFlags_None, border_size); } +#endif -static void ImGui::RenderWindowOuterBorders(ImGuiWindow* window) +static void ImGui::RenderWindowOuterBorders(ImGuiWindow * window) { ImGuiContext& g = *GImGui; const float border_size = window->WindowBorderSize; const ImU32 border_col = GetColorU32(ImGuiCol_Border); + +#ifdef WIN98 // window borders + IM_UNUSED(g); + if (border_size > 0.0f && !(window->Flags & ImGuiWindowFlags_NoBackground)) + WinAddRect(window->Pos, window->Pos + window->Size, false); +#else if (border_size > 0.0f && (window->Flags & ImGuiWindowFlags_NoBackground) == 0) window->DrawList->AddRect(window->Pos, window->Pos + window->Size, border_col, window->WindowRounding, 0, window->WindowBorderSize); else if (border_size > 0.0f) @@ -6228,6 +6280,7 @@ static void ImGui::RenderWindowOuterBorders(ImGuiWindow* window) float y = window->Pos.y + window->TitleBarHeight - 1; window->DrawList->AddLine(ImVec2(window->Pos.x + border_size, y), ImVec2(window->Pos.x + window->Size.x - border_size, y), border_col, g.Style.FrameBorderSize); } +#endif } // Draw background and borders @@ -6340,6 +6393,11 @@ void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& titl float pad_l = style.FramePadding.x; float pad_r = style.FramePadding.x; float button_sz = g.FontSize; +#ifdef WIN98 // draw title bar + button_sz = 16.0f; + // pad_l = 0.0f; + pad_r = 0.0f; +#endif ImVec2 close_button_pos; ImVec2 collapse_button_pos; if (has_close_button) @@ -6358,6 +6416,38 @@ void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& titl pad_l += button_sz + style.ItemInnerSpacing.x; } +#ifdef WIN98 // windows style title bar + + close_button_pos += ImVec2(0.0f, 2.0f); + collapse_button_pos += ImVec2(0.0f, 2.0f); + + ImU32 col_left = IM_COL32(128,128,128,255); + ImU32 col_right = IM_COL32(181,181,181,255); + + bool focused = IsWindowFocused(ImGuiFocusedFlags_ChildWindows); + if (focused) { + + // Windows98 colors are (0,0,128), (16,132,208) + // This code generates the secondary color from the primary while + // keeping the original windows colors + col_left = GetColorU32(ImGuiCol_TitleBgActive); + + ImVec4 secondary = GetStyleColorVec4(ImGuiCol_TitleBgActive); + ImVec4 secondary_hsv; + ColorConvertRGBtoHSV(secondary.x, secondary.y, secondary.z, secondary_hsv.x, secondary_hsv.y, secondary_hsv.z); + secondary_hsv.x -= 0.1f; + if (secondary_hsv.x < 0.0f) secondary_hsv.x += 1.0f; + secondary_hsv.y *= 0.92f; + secondary_hsv.z *= 1.625f; + ColorConvertHSVtoRGB(secondary_hsv.x, secondary_hsv.y, secondary_hsv.z, secondary.x, secondary.y, secondary.z); + + col_right = ColorConvertFloat4ToU32(secondary); + } + + + window->DrawList->AddRectFilledMultiColor(title_bar_rect.Min, title_bar_rect.Max, col_left, col_right, col_right, col_left); +#endif + // Collapse button (submitting first so it gets priority when choosing a navigation init fallback) if (has_collapse_button) if (CollapseButton(window->GetID("#COLLAPSE"), collapse_button_pos)) @@ -6390,6 +6480,14 @@ void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& titl pad_r = ImMax(pad_r, pad_extend * centerness); } +#ifdef WIN98 // windows title font + if (focused) PushStyleColor(ImGuiCol_Text, IM_COL32(255,255,255,255)); + else PushStyleColor(ImGuiCol_Text, IM_COL32(192,192,192,255)); + ImGuiIO& io = ImGui::GetIO(); + ImFont* font = io.Fonts->Fonts[1]; // Assume the icon font is here. pretty bad + PushFont(font); +#endif + ImRect layout_r(title_bar_rect.Min.x + pad_l, title_bar_rect.Min.y, title_bar_rect.Max.x - pad_r, title_bar_rect.Max.y); ImRect clip_r(layout_r.Min.x, layout_r.Min.y, ImMin(layout_r.Max.x + g.Style.ItemInnerSpacing.x, title_bar_rect.Max.x), layout_r.Max.y); if (flags & ImGuiWindowFlags_UnsavedDocument) @@ -6406,6 +6504,11 @@ void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& titl //if (g.IO.KeyShift) window->DrawList->AddRect(layout_r.Min, layout_r.Max, IM_COL32(255, 128, 0, 255)); // [DEBUG] //if (g.IO.KeyCtrl) window->DrawList->AddRect(clip_r.Min, clip_r.Max, IM_COL32(255, 128, 0, 255)); // [DEBUG] RenderTextClipped(layout_r.Min, layout_r.Max, name, NULL, &text_size, style.WindowTitleAlign, &clip_r); + +#ifdef WIN98 + PopFont(); + PopStyleColor(); +#endif } void ImGui::UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags flags, ImGuiWindow* parent_window) @@ -7119,7 +7222,16 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Title bar if (!(flags & ImGuiWindowFlags_NoTitleBar)) + { +#ifdef WIN98 // title bar sizing + ImRect inset_title_rect = title_bar_rect; + inset_title_rect.Min += ImVec2(2.0f, 2.0f); + inset_title_rect.Max -= ImVec2(2.0f, 0.0f); + RenderWindowTitleBarContents(window, inset_title_rect, name, p_open); +#else RenderWindowTitleBarContents(window, ImRect(title_bar_rect.Min.x + window->WindowBorderSize, title_bar_rect.Min.y, title_bar_rect.Max.x - window->WindowBorderSize, title_bar_rect.Max.y), name, p_open); +#endif + } // Clear hit test shape every frame window->HitTestHoleSize.x = window->HitTestHoleSize.y = 0; diff --git a/imgui.h b/imgui.h index d3a74704a..61f06341d 100644 --- a/imgui.h +++ b/imgui.h @@ -1008,6 +1008,11 @@ namespace ImGui IMGUI_API void* MemAlloc(size_t size); IMGUI_API void MemFree(void* ptr); + // Windows98 functions + IMGUI_API void WinAddRect(const ImVec2& min, const ImVec2& max, bool inset); + IMGUI_API void StyleWin98(ImGuiStyle* dst = NULL); + + } // namespace ImGui //----------------------------------------------------------------------------- diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 171889f2c..1f1afa12b 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -175,6 +175,12 @@ using namespace IMGUI_STB_NAMESPACE; void ImGui::StyleColorsDark(ImGuiStyle* dst) { +#ifdef WIN98 + // These colors don't make sense with win98 so just call this anyway + // also means I don't have to change all the examples + StyleWin98(dst); + return; +#else ImGuiStyle* style = dst ? dst : &ImGui::GetStyle(); ImVec4* colors = style->Colors; @@ -231,10 +237,17 @@ void ImGui::StyleColorsDark(ImGuiStyle* dst) colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f); colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f); colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f); +#endif } void ImGui::StyleColorsClassic(ImGuiStyle* dst) { +#ifdef WIN98 + // These colors don't make sense with win98 so just call this anyway + // also means I don't have to change all the examples + StyleWin98(dst); + return; +#else ImGuiStyle* style = dst ? dst : &ImGui::GetStyle(); ImVec4* colors = style->Colors; @@ -291,11 +304,19 @@ void ImGui::StyleColorsClassic(ImGuiStyle* dst) colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f); colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f); colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f); +#endif } // Those light colors are better suited with a thicker font than the default one + FrameBorder void ImGui::StyleColorsLight(ImGuiStyle* dst) { +#ifdef WIN98 + // These colors don't make sense with win98 so just call this anyway + // also means I don't have to change all the examples + StyleWin98(dst); + return; +#else + ImGuiStyle* style = dst ? dst : &ImGui::GetStyle(); ImVec4* colors = style->Colors; @@ -352,8 +373,131 @@ void ImGui::StyleColorsLight(ImGuiStyle* dst) colors[ImGuiCol_NavWindowingHighlight] = ImVec4(0.70f, 0.70f, 0.70f, 0.70f); colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.20f); colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f); +#endif } +// Windows style config +#ifdef WIN98 +void ImGui::StyleWin98(ImGuiStyle* dst) +{ + ImGuiStyle* style = dst ? dst : &ImGui::GetStyle(); + style->FrameBorderSize = 1.0f; + style->FramePadding = ImVec2(4.0f, 4.0f); + style->WindowMenuButtonPosition = ImGuiDir_Right; + style->ScrollbarSize = 16.0f; + + ImVec4* colors = style->Colors; + + colors[ImGuiCol_Text] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f); + colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f); + colors[ImGuiCol_WindowBg] = ImVec4(0.75f, 0.75f, 0.75f, 1.00f); + colors[ImGuiCol_ChildBg] = ImVec4(0.75f, 0.75f, 0.75f, 1.00f); + colors[ImGuiCol_PopupBg] = ImVec4(0.75f, 0.75f, 0.75f, 1.00f); + colors[ImGuiCol_Border] = ImVec4(0.00f, 0.00f, 0.00f, 0.30f); + colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); + colors[ImGuiCol_FrameBg] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); + colors[ImGuiCol_FrameBgHovered] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); + colors[ImGuiCol_FrameBgActive] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); + colors[ImGuiCol_TitleBg] = ImVec4(0.96f, 0.96f, 0.96f, 1.00f); + colors[ImGuiCol_TitleBgActive] = ImVec4(0.00f, 0.00f, 0.50f, 1.00f); + colors[ImGuiCol_TitleBgCollapsed] = ImVec4(1.00f, 1.00f, 1.00f, 0.51f); + colors[ImGuiCol_MenuBarBg] = ImVec4(0.86f, 0.86f, 0.86f, 1.00f); + colors[ImGuiCol_ScrollbarBg] = ImVec4(0.98f, 0.98f, 0.98f, 0.53f); + colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.69f, 0.69f, 0.69f, 0.80f); + colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.49f, 0.49f, 0.49f, 0.80f); + colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.49f, 0.49f, 0.49f, 1.00f); + colors[ImGuiCol_CheckMark] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); + colors[ImGuiCol_SliderGrab] = ImVec4(0.26f, 0.59f, 0.98f, 0.78f); + colors[ImGuiCol_SliderGrabActive] = ImVec4(0.46f, 0.54f, 0.80f, 0.60f); + colors[ImGuiCol_Button] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f); + colors[ImGuiCol_ButtonHovered] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); + colors[ImGuiCol_ButtonActive] = ImVec4(0.06f, 0.53f, 0.98f, 1.00f); + colors[ImGuiCol_Header] = ImVec4(0.26f, 0.59f, 0.98f, 0.31f); + colors[ImGuiCol_HeaderHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.80f); + colors[ImGuiCol_HeaderActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); + colors[ImGuiCol_Separator] = ImVec4(0.39f, 0.39f, 0.39f, 0.62f); + colors[ImGuiCol_SeparatorHovered] = ImVec4(0.14f, 0.44f, 0.80f, 0.78f); + colors[ImGuiCol_SeparatorActive] = ImVec4(0.14f, 0.44f, 0.80f, 1.00f); + colors[ImGuiCol_ResizeGrip] = ImVec4(0.80f, 0.80f, 0.80f, 0.56f); + colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f); + colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f); + colors[ImGuiCol_Tab] = ImVec4(0.76f, 0.80f, 0.84f, 0.95f); + colors[ImGuiCol_TabHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f); + colors[ImGuiCol_TabActive] = ImVec4(0.60f, 0.73f, 0.88f, 0.95f); + colors[ImGuiCol_TabUnfocused] = ImVec4(0.92f, 0.92f, 0.94f, 0.95f); + colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.74f, 0.82f, 0.91f, 1.00f); + colors[ImGuiCol_PlotLines] = ImVec4(0.39f, 0.39f, 0.39f, 1.00f); + colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f); + colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); + colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.45f, 0.00f, 1.00f); + colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f); + colors[ImGuiCol_DragDropTarget] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f); + colors[ImGuiCol_NavHighlight] = colors[ImGuiCol_HeaderHovered]; + colors[ImGuiCol_NavWindowingHighlight] = ImVec4(0.70f, 0.70f, 0.70f, 0.70f); + colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.20f); + colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f); + + + if (dst != NULL) return; + + // Fonts + Icons + ImGuiIO& io = ImGui::GetIO(); + for (int i = 0; i < io.Fonts->ConfigData.size(); i++) { + if (strcmp(io.Fonts->ConfigData[i].Name, "MS Sans Serif")) { + return; + } + } + ImFont *font = io.Fonts->AddFontFromFileTTF("../../MS Sans Serif.ttf", 12.0f, NULL, io.Fonts->GetGlyphRangesDefault()); + io.Fonts->AddFontFromFileTTF("../../MS Sans Serif Bold.ttf", 12.0f, NULL, io.Fonts->GetGlyphRangesDefault()); + + // Run-length encoding of some icons + // In retrorespect I should have used an icon map like FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS + unsigned char minimize[] = {86,6,6,6,0}; + unsigned char close[] = {14,2,4,2,5,2,2,2,7,4,9,2,9,4,7,2,2,2,5,2,4,2,0}; + unsigned char *run_length[] = {minimize, close}; + + int rect_ids[IM_ARRAYSIZE(run_length)]; + for (int i = 0; i < IM_ARRAYSIZE(run_length); i++) { + rect_ids[i] = io.Fonts->AddCustomRectFontGlyph(font, (ImWchar)(214 + i), 12, 9, 13+1); + } + + io.Fonts->Build(); + + unsigned char* tex_pixels = NULL; + int tex_width, tex_height; + io.Fonts->GetTexDataAsRGBA32(&tex_pixels, &tex_width, &tex_height); + + for (int i = 0; i < IM_ARRAYSIZE(run_length); i++) { + + int rect_id = rect_ids[i]; + if (const ImFontAtlasCustomRect* rect = io.Fonts->GetCustomRectByIndex(rect_id)) { + bool black = false; + unsigned char* run = run_length[i]; + int run_size = 0; + + for (int y = 0; y < rect->Height; y++) + { + ImU32* p = (ImU32*)tex_pixels + (rect->Y + y) * tex_width + (rect->X); + for (int x = rect->Width; x > 0; x--) { + if (black) *p = IM_COL32(255, 0, 0, 255); + p ++; + run_size ++; + if (run_size == *run) { + run_size = 0; + run ++; + black = !black; + if (*run == 0) goto done; + } + } + } + done:; + } + } + + +} +#endif + //----------------------------------------------------------------------------- // [SECTION] ImDrawList //----------------------------------------------------------------------------- diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 4c3b1c046..10224e666 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -719,12 +719,22 @@ bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags // Render const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); +#ifdef WIN98 + const ImU32 fill_col = GetColorU32(ImGuiCol_WindowBg); + window->DrawList->AddRectFilled(bb.Min, bb.Max, fill_col, 0.0f); + + WinAddRect(bb.Min, bb.Max, (held && hovered)); + PushStyleColor(ImGuiCol_Text, ImVec4(0.0f, 0.0f, 0.0f, 1.0f)); + RenderTextClipped(bb.Min + style.FramePadding, bb.Max - style.FramePadding, label, NULL, &label_size, style.ButtonTextAlign, &bb); + PopStyleColor(); +#else RenderNavHighlight(bb, id); RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding); if (g.LogEnabled) LogSetNextTextDecoration("[", "]"); RenderTextClipped(bb.Min + style.FramePadding, bb.Max - style.FramePadding, label, NULL, &label_size, style.ButtonTextAlign, &bb); +#endif // Automatically close popups //if (pressed && !(flags & ImGuiButtonFlags_DontClosePopups) && (window->Flags & ImGuiWindowFlags_Popup)) @@ -818,7 +828,11 @@ bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos) // Tweak 1: Shrink hit-testing area if button covers an abnormally large proportion of the visible region. That's in order to facilitate moving the window away. (#3825) // This may better be applied as a general hit-rect reduction mechanism for all widgets to ensure the area to move window is always accessible? +#ifdef WIN98 // close button size + const ImRect bb(pos, pos + ImVec2(16.0f, 14.0f)); +#else const ImRect bb(pos, pos + ImVec2(g.FontSize, g.FontSize)); +#endif ImRect bb_interact = bb; const float area_to_visible_ratio = window->OuterRectClipped.GetArea() / bb.GetArea(); if (area_to_visible_ratio < 1.5f) @@ -837,14 +851,28 @@ bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos) // FIXME: Clarify this mess ImU32 col = GetColorU32(held ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered); ImVec2 center = bb.GetCenter(); + +#ifdef WIN98 // close button + IM_UNUSED(col); + const ImU32 fill_col = GetColorU32(ImGuiCol_WindowBg); + window->DrawList->AddRectFilled(bb.Min, bb.Max, fill_col, 0.0f); + WinAddRect(bb.Min, bb.Max, hovered && held); +#else if (hovered) window->DrawList->AddCircleFilled(center, ImMax(2.0f, g.FontSize * 0.5f + 1.0f), col); +#endif float cross_extent = g.FontSize * 0.5f * 0.7071f - 1.0f; ImU32 cross_col = GetColorU32(ImGuiCol_Text); center -= ImVec2(0.5f, 0.5f); +#ifdef WIN98 // close button icon + IM_UNUSED(cross_col); + IM_UNUSED(cross_extent); + RenderText(bb.Min + ImVec2(2.0f, 2.0f), "\u00D7"); +#else window->DrawList->AddLine(center + ImVec2(+cross_extent, +cross_extent), center + ImVec2(-cross_extent, -cross_extent), cross_col, 1.0f); window->DrawList->AddLine(center + ImVec2(+cross_extent, -cross_extent), center + ImVec2(-cross_extent, +cross_extent), cross_col, 1.0f); +#endif return pressed; } @@ -854,7 +882,11 @@ bool ImGui::CollapseButton(ImGuiID id, const ImVec2& pos) ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; +#ifdef WIN98 // collapse button size + ImRect bb(pos, pos + ImVec2(16.0f, 14.0f)); +#else ImRect bb(pos, pos + ImVec2(g.FontSize, g.FontSize)); +#endif bool is_clipped = !ItemAdd(bb, id); bool hovered, held; bool pressed = ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_None); @@ -864,9 +896,20 @@ bool ImGui::CollapseButton(ImGuiID id, const ImVec2& pos) // Render ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); ImU32 text_col = GetColorU32(ImGuiCol_Text); +#ifdef WIN98 // collapse button + IM_UNUSED(bg_col); + IM_UNUSED(text_col); + const ImU32 fill_col = GetColorU32(ImGuiCol_WindowBg); + window->DrawList->AddRectFilled(bb.Min, bb.Max, fill_col, 0.0f); + WinAddRect(bb.Min, bb.Max, hovered && held); + + // collapse icon + RenderText(bb.Min + ImVec2(2.0f, 2.0f), "\u00D6"); +#else if (hovered || held) window->DrawList->AddCircleFilled(bb.GetCenter() + ImVec2(0.0f, -0.5f), g.FontSize * 0.5f + 1.0f, bg_col); RenderArrow(window->DrawList, bb.Min, text_col, window->Collapsed ? ImGuiDir_Right : ImGuiDir_Down, 1.0f); +#endif // Switch to moving the window after mouse is moved beyond the initial drag threshold if (IsItemActive() && IsMouseDragging(0)) @@ -951,8 +994,19 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, ImS6 const ImGuiStyle& style = g.Style; const bool allow_interaction = (alpha >= 1.0f); +#ifdef WIN98 + IM_UNUSED(flags); + ImRect bb = bb_frame; + float button_size = (axis == ImGuiAxis_X) ? bb.GetHeight() : bb.GetWidth(); + ImVec2 button_size_rect(button_size, button_size); + ImVec2 main_axis((axis == ImGuiAxis_X) ? 1.0f : 0.0f, (axis == ImGuiAxis_X) ? 0.0f : 1.0f); + ImVec2 main_axis_button_size = main_axis * button_size; + + bb.Expand(main_axis * -button_size); +#else ImRect bb = bb_frame; bb.Expand(ImVec2(-ImClamp(IM_TRUNC((bb_frame_width - 2.0f) * 0.5f), 0.0f, 3.0f), -ImClamp(IM_TRUNC((bb_frame_height - 2.0f) * 0.5f), 0.0f, 3.0f))); +#endif // V denote the main, longer axis of the scrollbar (= height for a vertical scrollbar) const float scrollbar_size_v = (axis == ImGuiAxis_X) ? bb.GetWidth() : bb.GetHeight(); @@ -1017,6 +1071,33 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, ImS6 } // Render +#ifdef WIN98 // scrollbar + + ImRect grab_rect; + if (axis == ImGuiAxis_X) { + grab_rect = ImRect(ImLerp(bb.Min.x, bb.Max.x, grab_v_norm), bb.Min.y, ImLerp(bb.Min.x, bb.Max.x, grab_v_norm) + grab_h_pixels, bb.Max.y); + } else { + grab_rect = ImRect(bb.Min.x, ImLerp(bb.Min.y, bb.Max.y, grab_v_norm), bb.Max.x, ImLerp(bb.Min.y, bb.Max.y, grab_v_norm) + grab_h_pixels); + } + WinAddRect(grab_rect.Min, grab_rect.Max, false); + { + const ImGuiID up_id = window->GetID("##scrollup"); + ImRect button_bounds(bb_frame.Min, bb_frame.Min + button_size_rect); + bool held_up = false; + bool hovered_up = false; + /*bool pressed_up = */ ButtonBehavior(button_bounds, up_id, &hovered_up, &held_up, 0); + WinAddRect(button_bounds.Min, button_bounds.Max, (held_up && hovered_up)); + } + { + const ImGuiID down_id = window->GetID("##scrolldown"); + ImVec2 pos = bb_frame.Min + main_axis * (((axis == ImGuiAxis_X) ? bb_frame.GetWidth() : bb_frame.GetHeight()) - button_size); + ImRect button_bounds(pos, pos + button_size_rect); + bool held_down = false; + bool hovered_down = false; + /*bool pressed_down =*/ ButtonBehavior(button_bounds, down_id, &hovered_down, &held_down, 0); + WinAddRect(button_bounds.Min, button_bounds.Max, (held_down && hovered_down)); + } +#else const ImU32 bg_col = GetColorU32(ImGuiCol_ScrollbarBg); const ImU32 grab_col = GetColorU32(held ? ImGuiCol_ScrollbarGrabActive : hovered ? ImGuiCol_ScrollbarGrabHovered : ImGuiCol_ScrollbarGrab, alpha); window->DrawList->AddRectFilled(bb_frame.Min, bb_frame.Max, bg_col, window->WindowRounding, flags); @@ -1026,6 +1107,7 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, ImS6 else grab_rect = ImRect(bb.Min.x, ImLerp(bb.Min.y, bb.Max.y, grab_v_norm), bb.Max.x, ImLerp(bb.Min.y, bb.Max.y, grab_v_norm) + grab_h_pixels); window->DrawList->AddRectFilled(grab_rect.Min, grab_rect.Max, grab_col, style.ScrollbarRounding); +#endif return held; }