Skip to content

Commit

Permalink
refactor to support deeper ImGui customization (#145)
Browse files Browse the repository at this point in the history
* refactor for custom GUIs

* move gui helpers to public namespace

* missing includes

Co-authored-by: xarthur <[email protected]>
  • Loading branch information
nmwsharp and xarthurx authored Dec 1, 2021
1 parent 49256eb commit a419ca8
Show file tree
Hide file tree
Showing 8 changed files with 199 additions and 121 deletions.
15 changes: 15 additions & 0 deletions include/polyscope/imgui_config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright 2017-2019, Nicholas Sharp and the Polyscope contributors. http://polyscope.run.
#pragma once

#include <tuple>

#include "imgui.h"


namespace polyscope {

// Default implementations of callbacks to set ImGui style / fonts
void configureImGuiStyle();
std::tuple<ImFontAtlas*, ImFont*, ImFont*> prepareImGuiFonts();

} // namespace polyscope
41 changes: 29 additions & 12 deletions include/polyscope/options.h
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
// Copyright 2017-2019, Nicholas Sharp and the Polyscope contributors. http://polyscope.run.
#pragma once

#include <string>
#include <functional>
#include <tuple>

#include "imgui.h"

#include "polyscope/scaled_value.h"
#include "polyscope/types.h"

#include <string>

namespace polyscope {
namespace options {

// A general name to use when referring to the program in window headings.
namespace options { // A general name to use when referring to the program in window headings.
extern std::string programName;

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

// If false, Polyscope will not create any ImGui UIs at all, but will still set up ImGui and invoke its render steps
// each frame. The allows advanced users to create their own UIs totally from scratch and circumvent the standard
// Polyscope UIs. (default: true)
extern bool buildGui;

// Should the user call back start out with an imgui window context open (default: true)
extern bool openImGuiWindowForUserCallback;

// If true, the user callback will be invoked for nested calls to polyscope::show(), otherwise not (default: false)
extern bool invokeUserCallbackForNestedShow;

Expand Down Expand Up @@ -80,6 +75,28 @@ extern int ssaaFactor;
extern TransparencyMode transparencyMode;
extern int transparencyRenderPasses;

// === Advanced ImGui configuration

// If false, Polyscope will not create any ImGui UIs at all, but will still set up ImGui and invoke its render steps
// each frame. The allows advanced users to create their own UIs totally from scratch and circumvent the standard
// Polyscope UIs. (default: true)
extern bool buildGui;

// Should the user call back start out with an imgui window context open (default: true)
extern bool openImGuiWindowForUserCallback;

// A callback function which will be invoked when an ImGui context is created (which may happen several times as
// Polyscope runs). By default, this is set to invoke `configureImGuiStyle()` from Polyscope's imgui_config.cpp, but you
// may assign your own function to create custom styles. If this callback is null, the default ImGui style will be used.
extern std::function<void()> configureImGuiStyleCallback;

// A callback function which will be invoked exactly once during initialization to construct a font atlas for ImGui to
// use. The callback should return a tuple of three pointers: a newly created global shared font atlas, a regular font,
// and a mono font. By default, this is set to invoke prepareImGuiFonts() from Polyscope's imgui_config.cpp, but you may
// assign your own function to create custom styles. If this callback is null, default fonts will be used.
extern std::function<std::tuple<ImFontAtlas*, ImFont*, ImFont*>()> prepareImGuiFontsCallback;


// === Debug options

// Enables optional error checks in the rendering system
Expand Down
9 changes: 9 additions & 0 deletions include/polyscope/polyscope.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,15 @@ bool redrawRequested();
void pushContext(std::function<void()> callbackFunction, bool drawDefaultUI = true);
void popContext();

// These helpers are called internally by Polyscope to render and build the UI.
// Normally, applications should not need to call them, but in advanced settings when making custom UIs, they may be
// useful to manually build pieces of the interface.
void buildPolyscopeGui();
void buildStructureGui();
void buildPickGui();
void buildUserGuiAndInvokeCallback();


// === Utility

// Execute one iteration of the main loop
Expand Down
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ SET(SRCS
volume_mesh_vector_quantity.cpp

# Rendering utilities
imgui_config.cpp
vector_artist.cpp
trace_vector_field.cpp
ribbon_artist.cpp
Expand Down Expand Up @@ -216,6 +217,7 @@ SET(HEADERS
${INCLUDE_ROOT}/file_helpers.h
${INCLUDE_ROOT}/histogram.h
${INCLUDE_ROOT}/image_scalar_artist.h
${INCLUDE_ROOT}/imgui_config.h
${INCLUDE_ROOT}/messages.h
${INCLUDE_ROOT}/options.h
${INCLUDE_ROOT}/persistent_value.h
Expand Down
103 changes: 103 additions & 0 deletions src/imgui_config.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// Copyright 2017-2019, Nicholas Sharp and the Polyscope contributors. http://polyscope.run.
#include "polyscope/imgui_config.h"

namespace polyscope {


// Forward declare compressed binary font functions
namespace render {
unsigned int getCousineRegularCompressedSize();
const unsigned int* getCousineRegularCompressedData();
unsigned int getLatoRegularCompressedSize();
const unsigned int* getLatoRegularCompressedData();
} // namespace render

void configureImGuiStyle() {

// Style
ImGuiStyle* style = &ImGui::GetStyle();
style->WindowRounding = 1;
style->FrameRounding = 1;
style->FramePadding.y = 4;
style->ScrollbarRounding = 1;
style->ScrollbarSize = 20;


// Colors
ImVec4* colors = style->Colors;
colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f);
colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f);
colors[ImGuiCol_WindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.70f);
colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
colors[ImGuiCol_PopupBg] = ImVec4(0.11f, 0.11f, 0.14f, 0.92f);
colors[ImGuiCol_Border] = ImVec4(0.50f, 0.50f, 0.50f, 0.50f);
colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
colors[ImGuiCol_FrameBg] = ImVec4(0.63f, 0.63f, 0.63f, 0.39f);
colors[ImGuiCol_FrameBgHovered] = ImVec4(0.47f, 0.69f, 0.59f, 0.40f);
colors[ImGuiCol_FrameBgActive] = ImVec4(0.41f, 0.64f, 0.53f, 0.69f);
colors[ImGuiCol_TitleBg] = ImVec4(0.27f, 0.54f, 0.42f, 0.83f);
colors[ImGuiCol_TitleBgActive] = ImVec4(0.32f, 0.63f, 0.49f, 0.87f);
colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.27f, 0.54f, 0.42f, 0.83f);
colors[ImGuiCol_MenuBarBg] = ImVec4(0.40f, 0.55f, 0.48f, 0.80f);
colors[ImGuiCol_ScrollbarBg] = ImVec4(0.63f, 0.63f, 0.63f, 0.39f);
colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.00f, 0.00f, 0.00f, 0.30f);
colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.80f, 0.62f, 0.40f);
colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.39f, 0.80f, 0.61f, 0.60f);
colors[ImGuiCol_CheckMark] = ImVec4(0.90f, 0.90f, 0.90f, 0.50f);
colors[ImGuiCol_SliderGrab] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f);
colors[ImGuiCol_SliderGrabActive] = ImVec4(0.39f, 0.80f, 0.61f, 0.60f);
colors[ImGuiCol_Button] = ImVec4(0.35f, 0.61f, 0.49f, 0.62f);
colors[ImGuiCol_ButtonHovered] = ImVec4(0.40f, 0.71f, 0.57f, 0.79f);
colors[ImGuiCol_ButtonActive] = ImVec4(0.46f, 0.80f, 0.64f, 1.00f);
colors[ImGuiCol_Header] = ImVec4(0.40f, 0.90f, 0.67f, 0.45f);
colors[ImGuiCol_HeaderHovered] = ImVec4(0.45f, 0.90f, 0.69f, 0.80f);
colors[ImGuiCol_HeaderActive] = ImVec4(0.53f, 0.87f, 0.71f, 0.80f);
colors[ImGuiCol_Separator] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f);
colors[ImGuiCol_SeparatorHovered] = ImVec4(0.60f, 0.70f, 0.66f, 1.00f);
colors[ImGuiCol_SeparatorActive] = ImVec4(0.70f, 0.90f, 0.81f, 1.00f);
colors[ImGuiCol_ResizeGrip] = ImVec4(1.00f, 1.00f, 1.00f, 0.16f);
colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.78f, 1.00f, 0.90f, 0.60f);
colors[ImGuiCol_ResizeGripActive] = ImVec4(0.78f, 1.00f, 0.90f, 0.90f);
colors[ImGuiCol_PlotLines] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f);
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f);
colors[ImGuiCol_ModalWindowDarkening] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f);
colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
colors[ImGuiCol_Tab] = ImVec4(0.27f, 0.54f, 0.42f, 0.83f);
colors[ImGuiCol_TabHovered] = ImVec4(0.34f, 0.68f, 0.53f, 0.83f);
colors[ImGuiCol_TabActive] = ImVec4(0.38f, 0.76f, 0.58f, 0.83f);
}


std::tuple<ImFontAtlas*, ImFont*, ImFont*> prepareImGuiFonts() {

ImGuiIO& io = ImGui::GetIO();

// outputs
ImFontAtlas* globalFontAtlas;
ImFont* regularFont;
ImFont* monoFont;

{ // add regular font
ImFontConfig config;
regularFont = io.Fonts->AddFontFromMemoryCompressedTTF(render::getLatoRegularCompressedData(),
render::getLatoRegularCompressedSize(), 18.0f, &config);
}

{ // add mono font
ImFontConfig config;
monoFont = io.Fonts->AddFontFromMemoryCompressedTTF(render::getCousineRegularCompressedData(),
render::getCousineRegularCompressedSize(), 16.0f, &config);
}

// io.Fonts->AddFontFromFileTTF("test-font-name.ttf", 16);

io.Fonts->Build();
globalFontAtlas = io.Fonts;

return std::tuple<ImFontAtlas*, ImFont*, ImFont*>{globalFontAtlas, regularFont, monoFont};
}

} // namespace polyscope
11 changes: 9 additions & 2 deletions src/options.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Copyright 2017-2019, Nicholas Sharp and the Polyscope contributors. http://polyscope.run.
#include "polyscope/options.h"
#include "polyscope/imgui_config.h"

namespace polyscope {
namespace options {
Expand All @@ -16,8 +17,6 @@ bool alwaysRedraw = false;
bool autocenterStructures = false;
bool autoscaleStructures = false;
bool automaticallyComputeSceneExtents = true;
bool buildGui = true;
bool openImGuiWindowForUserCallback = true;
bool invokeUserCallbackForNestedShow = false;
bool giveFocusOnShow = false;

Expand All @@ -41,6 +40,14 @@ int ssaaFactor = 1;
TransparencyMode transparencyMode = TransparencyMode::None;
int transparencyRenderPasses = 8;

// === Advanced ImGui configuration

bool buildGui = true;
bool openImGuiWindowForUserCallback = true;
std::function<void()> configureImGuiStyleCallback = configureImGuiStyle;
std::function<std::tuple<ImFontAtlas*, ImFont*, ImFont*>()> prepareImGuiFontsCallback = prepareImGuiFonts;


// enabled by default in debug mode
#ifndef NDEBUG
bool enableRenderErrorChecks = false;
Expand Down
51 changes: 27 additions & 24 deletions src/polyscope.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,10 @@ void pushContext(std::function<void()> callbackFunction, bool drawDefaultUI) {
ImGuiIO& oldIO = ImGui::GetIO(); // used to copy below, see note
ImGui::SetCurrentContext(newContext);

render::engine->setImGuiStyle();
if (options::configureImGuiStyleCallback) {
options::configureImGuiStyleCallback();
}

ImGui::GetIO() = oldIO; // Copy all of the old IO values to new. With ImGUI 1.76 (and some previous versions), this
// was necessary to fix a bug where keys like delete, etc would break in subcontexts. The
// problem was that the key mappings (e.g. GLFW_KEY_BACKSPACE --> ImGuiKey_Backspace) need to
Expand Down Expand Up @@ -415,6 +418,10 @@ void renderSceneToScreen() {
}
}

auto lastMainLoopIterTime = std::chrono::steady_clock::now();

} // namespace

void buildPolyscopeGui() {

// Create window
Expand Down Expand Up @@ -555,6 +562,25 @@ void buildStructureGui() {
ImGui::End();
}

void buildPickGui() {
if (pick::haveSelection()) {

ImGui::SetNextWindowPos(ImVec2(view::windowWidth - (rightWindowsWidth + imguiStackMargin),
2 * imguiStackMargin + lastWindowHeightUser));
ImGui::SetNextWindowSize(ImVec2(rightWindowsWidth, 0.));

ImGui::Begin("Selection", nullptr);
std::pair<Structure*, size_t> selection = pick::getSelection();

ImGui::TextUnformatted((selection.first->typeName() + ": " + selection.first->name).c_str());
ImGui::Separator();
selection.first->buildPickUI(selection.second);

rightWindowsWidth = ImGui::GetWindowWidth();
ImGui::End();
}
}

void buildUserGuiAndInvokeCallback() {

if (!options::invokeUserCallbackForNestedShow && contextStack.size() > 2) {
Expand Down Expand Up @@ -587,29 +613,6 @@ void buildUserGuiAndInvokeCallback() {
}
}

void buildPickGui() {
if (pick::haveSelection()) {

ImGui::SetNextWindowPos(ImVec2(view::windowWidth - (rightWindowsWidth + imguiStackMargin),
2 * imguiStackMargin + lastWindowHeightUser));
ImGui::SetNextWindowSize(ImVec2(rightWindowsWidth, 0.));

ImGui::Begin("Selection", nullptr);
std::pair<Structure*, size_t> selection = pick::getSelection();

ImGui::TextUnformatted((selection.first->typeName() + ": " + selection.first->name).c_str());
ImGui::Separator();
selection.first->buildPickUI(selection.second);

rightWindowsWidth = ImGui::GetWindowWidth();
ImGui::End();
}
}

auto lastMainLoopIterTime = std::chrono::steady_clock::now();

} // namespace

void draw(bool withUI, bool withContextCallback) {
processLazyProperties();

Expand Down
Loading

0 comments on commit a419ca8

Please sign in to comment.