Skip to content

Commit a419ca8

Browse files
nmwsharpxarthurx
andauthored
refactor to support deeper ImGui customization (#145)
* refactor for custom GUIs * move gui helpers to public namespace * missing includes Co-authored-by: xarthur <[email protected]>
1 parent 49256eb commit a419ca8

File tree

8 files changed

+199
-121
lines changed

8 files changed

+199
-121
lines changed

include/polyscope/imgui_config.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright 2017-2019, Nicholas Sharp and the Polyscope contributors. http://polyscope.run.
2+
#pragma once
3+
4+
#include <tuple>
5+
6+
#include "imgui.h"
7+
8+
9+
namespace polyscope {
10+
11+
// Default implementations of callbacks to set ImGui style / fonts
12+
void configureImGuiStyle();
13+
std::tuple<ImFontAtlas*, ImFont*, ImFont*> prepareImGuiFonts();
14+
15+
} // namespace polyscope

include/polyscope/options.h

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
// Copyright 2017-2019, Nicholas Sharp and the Polyscope contributors. http://polyscope.run.
22
#pragma once
33

4+
#include <string>
5+
#include <functional>
6+
#include <tuple>
7+
8+
#include "imgui.h"
9+
410
#include "polyscope/scaled_value.h"
511
#include "polyscope/types.h"
612

7-
#include <string>
813

914
namespace polyscope {
10-
namespace options {
11-
12-
// A general name to use when referring to the program in window headings.
15+
namespace options { // A general name to use when referring to the program in window headings.
1316
extern std::string programName;
1417

1518
// How much should polyscope print to std::out?
@@ -43,14 +46,6 @@ extern bool autoscaleStructures;
4346
// bounding box and length scale manually. (default: true)
4447
extern bool automaticallyComputeSceneExtents;
4548

46-
// If false, Polyscope will not create any ImGui UIs at all, but will still set up ImGui and invoke its render steps
47-
// each frame. The allows advanced users to create their own UIs totally from scratch and circumvent the standard
48-
// Polyscope UIs. (default: true)
49-
extern bool buildGui;
50-
51-
// Should the user call back start out with an imgui window context open (default: true)
52-
extern bool openImGuiWindowForUserCallback;
53-
5449
// If true, the user callback will be invoked for nested calls to polyscope::show(), otherwise not (default: false)
5550
extern bool invokeUserCallbackForNestedShow;
5651

@@ -80,6 +75,28 @@ extern int ssaaFactor;
8075
extern TransparencyMode transparencyMode;
8176
extern int transparencyRenderPasses;
8277

78+
// === Advanced ImGui configuration
79+
80+
// If false, Polyscope will not create any ImGui UIs at all, but will still set up ImGui and invoke its render steps
81+
// each frame. The allows advanced users to create their own UIs totally from scratch and circumvent the standard
82+
// Polyscope UIs. (default: true)
83+
extern bool buildGui;
84+
85+
// Should the user call back start out with an imgui window context open (default: true)
86+
extern bool openImGuiWindowForUserCallback;
87+
88+
// A callback function which will be invoked when an ImGui context is created (which may happen several times as
89+
// Polyscope runs). By default, this is set to invoke `configureImGuiStyle()` from Polyscope's imgui_config.cpp, but you
90+
// may assign your own function to create custom styles. If this callback is null, the default ImGui style will be used.
91+
extern std::function<void()> configureImGuiStyleCallback;
92+
93+
// A callback function which will be invoked exactly once during initialization to construct a font atlas for ImGui to
94+
// use. The callback should return a tuple of three pointers: a newly created global shared font atlas, a regular font,
95+
// and a mono font. By default, this is set to invoke prepareImGuiFonts() from Polyscope's imgui_config.cpp, but you may
96+
// assign your own function to create custom styles. If this callback is null, default fonts will be used.
97+
extern std::function<std::tuple<ImFontAtlas*, ImFont*, ImFont*>()> prepareImGuiFontsCallback;
98+
99+
83100
// === Debug options
84101

85102
// Enables optional error checks in the rendering system

include/polyscope/polyscope.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,15 @@ bool redrawRequested();
113113
void pushContext(std::function<void()> callbackFunction, bool drawDefaultUI = true);
114114
void popContext();
115115

116+
// These helpers are called internally by Polyscope to render and build the UI.
117+
// Normally, applications should not need to call them, but in advanced settings when making custom UIs, they may be
118+
// useful to manually build pieces of the interface.
119+
void buildPolyscopeGui();
120+
void buildStructureGui();
121+
void buildPickGui();
122+
void buildUserGuiAndInvokeCallback();
123+
124+
116125
// === Utility
117126

118127
// Execute one iteration of the main loop

src/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ SET(SRCS
178178
volume_mesh_vector_quantity.cpp
179179

180180
# Rendering utilities
181+
imgui_config.cpp
181182
vector_artist.cpp
182183
trace_vector_field.cpp
183184
ribbon_artist.cpp
@@ -216,6 +217,7 @@ SET(HEADERS
216217
${INCLUDE_ROOT}/file_helpers.h
217218
${INCLUDE_ROOT}/histogram.h
218219
${INCLUDE_ROOT}/image_scalar_artist.h
220+
${INCLUDE_ROOT}/imgui_config.h
219221
${INCLUDE_ROOT}/messages.h
220222
${INCLUDE_ROOT}/options.h
221223
${INCLUDE_ROOT}/persistent_value.h

src/imgui_config.cpp

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
// Copyright 2017-2019, Nicholas Sharp and the Polyscope contributors. http://polyscope.run.
2+
#include "polyscope/imgui_config.h"
3+
4+
namespace polyscope {
5+
6+
7+
// Forward declare compressed binary font functions
8+
namespace render {
9+
unsigned int getCousineRegularCompressedSize();
10+
const unsigned int* getCousineRegularCompressedData();
11+
unsigned int getLatoRegularCompressedSize();
12+
const unsigned int* getLatoRegularCompressedData();
13+
} // namespace render
14+
15+
void configureImGuiStyle() {
16+
17+
// Style
18+
ImGuiStyle* style = &ImGui::GetStyle();
19+
style->WindowRounding = 1;
20+
style->FrameRounding = 1;
21+
style->FramePadding.y = 4;
22+
style->ScrollbarRounding = 1;
23+
style->ScrollbarSize = 20;
24+
25+
26+
// Colors
27+
ImVec4* colors = style->Colors;
28+
colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f);
29+
colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f);
30+
colors[ImGuiCol_WindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.70f);
31+
colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
32+
colors[ImGuiCol_PopupBg] = ImVec4(0.11f, 0.11f, 0.14f, 0.92f);
33+
colors[ImGuiCol_Border] = ImVec4(0.50f, 0.50f, 0.50f, 0.50f);
34+
colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
35+
colors[ImGuiCol_FrameBg] = ImVec4(0.63f, 0.63f, 0.63f, 0.39f);
36+
colors[ImGuiCol_FrameBgHovered] = ImVec4(0.47f, 0.69f, 0.59f, 0.40f);
37+
colors[ImGuiCol_FrameBgActive] = ImVec4(0.41f, 0.64f, 0.53f, 0.69f);
38+
colors[ImGuiCol_TitleBg] = ImVec4(0.27f, 0.54f, 0.42f, 0.83f);
39+
colors[ImGuiCol_TitleBgActive] = ImVec4(0.32f, 0.63f, 0.49f, 0.87f);
40+
colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.27f, 0.54f, 0.42f, 0.83f);
41+
colors[ImGuiCol_MenuBarBg] = ImVec4(0.40f, 0.55f, 0.48f, 0.80f);
42+
colors[ImGuiCol_ScrollbarBg] = ImVec4(0.63f, 0.63f, 0.63f, 0.39f);
43+
colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.00f, 0.00f, 0.00f, 0.30f);
44+
colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.80f, 0.62f, 0.40f);
45+
colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.39f, 0.80f, 0.61f, 0.60f);
46+
colors[ImGuiCol_CheckMark] = ImVec4(0.90f, 0.90f, 0.90f, 0.50f);
47+
colors[ImGuiCol_SliderGrab] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f);
48+
colors[ImGuiCol_SliderGrabActive] = ImVec4(0.39f, 0.80f, 0.61f, 0.60f);
49+
colors[ImGuiCol_Button] = ImVec4(0.35f, 0.61f, 0.49f, 0.62f);
50+
colors[ImGuiCol_ButtonHovered] = ImVec4(0.40f, 0.71f, 0.57f, 0.79f);
51+
colors[ImGuiCol_ButtonActive] = ImVec4(0.46f, 0.80f, 0.64f, 1.00f);
52+
colors[ImGuiCol_Header] = ImVec4(0.40f, 0.90f, 0.67f, 0.45f);
53+
colors[ImGuiCol_HeaderHovered] = ImVec4(0.45f, 0.90f, 0.69f, 0.80f);
54+
colors[ImGuiCol_HeaderActive] = ImVec4(0.53f, 0.87f, 0.71f, 0.80f);
55+
colors[ImGuiCol_Separator] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f);
56+
colors[ImGuiCol_SeparatorHovered] = ImVec4(0.60f, 0.70f, 0.66f, 1.00f);
57+
colors[ImGuiCol_SeparatorActive] = ImVec4(0.70f, 0.90f, 0.81f, 1.00f);
58+
colors[ImGuiCol_ResizeGrip] = ImVec4(1.00f, 1.00f, 1.00f, 0.16f);
59+
colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.78f, 1.00f, 0.90f, 0.60f);
60+
colors[ImGuiCol_ResizeGripActive] = ImVec4(0.78f, 1.00f, 0.90f, 0.90f);
61+
colors[ImGuiCol_PlotLines] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
62+
colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
63+
colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
64+
colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f);
65+
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f);
66+
colors[ImGuiCol_ModalWindowDarkening] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f);
67+
colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
68+
colors[ImGuiCol_Tab] = ImVec4(0.27f, 0.54f, 0.42f, 0.83f);
69+
colors[ImGuiCol_TabHovered] = ImVec4(0.34f, 0.68f, 0.53f, 0.83f);
70+
colors[ImGuiCol_TabActive] = ImVec4(0.38f, 0.76f, 0.58f, 0.83f);
71+
}
72+
73+
74+
std::tuple<ImFontAtlas*, ImFont*, ImFont*> prepareImGuiFonts() {
75+
76+
ImGuiIO& io = ImGui::GetIO();
77+
78+
// outputs
79+
ImFontAtlas* globalFontAtlas;
80+
ImFont* regularFont;
81+
ImFont* monoFont;
82+
83+
{ // add regular font
84+
ImFontConfig config;
85+
regularFont = io.Fonts->AddFontFromMemoryCompressedTTF(render::getLatoRegularCompressedData(),
86+
render::getLatoRegularCompressedSize(), 18.0f, &config);
87+
}
88+
89+
{ // add mono font
90+
ImFontConfig config;
91+
monoFont = io.Fonts->AddFontFromMemoryCompressedTTF(render::getCousineRegularCompressedData(),
92+
render::getCousineRegularCompressedSize(), 16.0f, &config);
93+
}
94+
95+
// io.Fonts->AddFontFromFileTTF("test-font-name.ttf", 16);
96+
97+
io.Fonts->Build();
98+
globalFontAtlas = io.Fonts;
99+
100+
return std::tuple<ImFontAtlas*, ImFont*, ImFont*>{globalFontAtlas, regularFont, monoFont};
101+
}
102+
103+
} // namespace polyscope

src/options.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// Copyright 2017-2019, Nicholas Sharp and the Polyscope contributors. http://polyscope.run.
22
#include "polyscope/options.h"
3+
#include "polyscope/imgui_config.h"
34

45
namespace polyscope {
56
namespace options {
@@ -16,8 +17,6 @@ bool alwaysRedraw = false;
1617
bool autocenterStructures = false;
1718
bool autoscaleStructures = false;
1819
bool automaticallyComputeSceneExtents = true;
19-
bool buildGui = true;
20-
bool openImGuiWindowForUserCallback = true;
2120
bool invokeUserCallbackForNestedShow = false;
2221
bool giveFocusOnShow = false;
2322

@@ -41,6 +40,14 @@ int ssaaFactor = 1;
4140
TransparencyMode transparencyMode = TransparencyMode::None;
4241
int transparencyRenderPasses = 8;
4342

43+
// === Advanced ImGui configuration
44+
45+
bool buildGui = true;
46+
bool openImGuiWindowForUserCallback = true;
47+
std::function<void()> configureImGuiStyleCallback = configureImGuiStyle;
48+
std::function<std::tuple<ImFontAtlas*, ImFont*, ImFont*>()> prepareImGuiFontsCallback = prepareImGuiFonts;
49+
50+
4451
// enabled by default in debug mode
4552
#ifndef NDEBUG
4653
bool enableRenderErrorChecks = false;

src/polyscope.cpp

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,10 @@ void pushContext(std::function<void()> callbackFunction, bool drawDefaultUI) {
139139
ImGuiIO& oldIO = ImGui::GetIO(); // used to copy below, see note
140140
ImGui::SetCurrentContext(newContext);
141141

142-
render::engine->setImGuiStyle();
142+
if (options::configureImGuiStyleCallback) {
143+
options::configureImGuiStyleCallback();
144+
}
145+
143146
ImGui::GetIO() = oldIO; // Copy all of the old IO values to new. With ImGUI 1.76 (and some previous versions), this
144147
// was necessary to fix a bug where keys like delete, etc would break in subcontexts. The
145148
// problem was that the key mappings (e.g. GLFW_KEY_BACKSPACE --> ImGuiKey_Backspace) need to
@@ -415,6 +418,10 @@ void renderSceneToScreen() {
415418
}
416419
}
417420

421+
auto lastMainLoopIterTime = std::chrono::steady_clock::now();
422+
423+
} // namespace
424+
418425
void buildPolyscopeGui() {
419426

420427
// Create window
@@ -555,6 +562,25 @@ void buildStructureGui() {
555562
ImGui::End();
556563
}
557564

565+
void buildPickGui() {
566+
if (pick::haveSelection()) {
567+
568+
ImGui::SetNextWindowPos(ImVec2(view::windowWidth - (rightWindowsWidth + imguiStackMargin),
569+
2 * imguiStackMargin + lastWindowHeightUser));
570+
ImGui::SetNextWindowSize(ImVec2(rightWindowsWidth, 0.));
571+
572+
ImGui::Begin("Selection", nullptr);
573+
std::pair<Structure*, size_t> selection = pick::getSelection();
574+
575+
ImGui::TextUnformatted((selection.first->typeName() + ": " + selection.first->name).c_str());
576+
ImGui::Separator();
577+
selection.first->buildPickUI(selection.second);
578+
579+
rightWindowsWidth = ImGui::GetWindowWidth();
580+
ImGui::End();
581+
}
582+
}
583+
558584
void buildUserGuiAndInvokeCallback() {
559585

560586
if (!options::invokeUserCallbackForNestedShow && contextStack.size() > 2) {
@@ -587,29 +613,6 @@ void buildUserGuiAndInvokeCallback() {
587613
}
588614
}
589615

590-
void buildPickGui() {
591-
if (pick::haveSelection()) {
592-
593-
ImGui::SetNextWindowPos(ImVec2(view::windowWidth - (rightWindowsWidth + imguiStackMargin),
594-
2 * imguiStackMargin + lastWindowHeightUser));
595-
ImGui::SetNextWindowSize(ImVec2(rightWindowsWidth, 0.));
596-
597-
ImGui::Begin("Selection", nullptr);
598-
std::pair<Structure*, size_t> selection = pick::getSelection();
599-
600-
ImGui::TextUnformatted((selection.first->typeName() + ": " + selection.first->name).c_str());
601-
ImGui::Separator();
602-
selection.first->buildPickUI(selection.second);
603-
604-
rightWindowsWidth = ImGui::GetWindowWidth();
605-
ImGui::End();
606-
}
607-
}
608-
609-
auto lastMainLoopIterTime = std::chrono::steady_clock::now();
610-
611-
} // namespace
612-
613616
void draw(bool withUI, bool withContextCallback) {
614617
processLazyProperties();
615618

0 commit comments

Comments
 (0)