Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@
[submodule "deps/glm"]
path = deps/glm
url = https://github.com/g-truc/glm.git
[submodule "deps/imgui/implot"]
path = deps/imgui/implot
url = https://github.com/epezent/implot
10 changes: 9 additions & 1 deletion deps/imgui/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,22 @@ endif()

if("${POLYSCOPE_BACKEND_OPENGL3_GLFW}")

set(SRCS imgui/imgui.cpp imgui/imgui_draw.cpp imgui/imgui_tables.cpp imgui/imgui_widgets.cpp imgui/imgui_demo.cpp imgui/backends/imgui_impl_glfw.cpp imgui/backends/imgui_impl_opengl3.cpp)
# imgui sources
list(APPEND SRCS imgui/imgui.cpp imgui/imgui_draw.cpp imgui/imgui_tables.cpp imgui/imgui_widgets.cpp imgui/imgui_demo.cpp imgui/backends/imgui_impl_glfw.cpp imgui/backends/imgui_impl_opengl3.cpp)

# implot sources
list(APPEND SRCS
implot/implot.cpp
implot/implot_items.cpp
)

add_library(
imgui
${SRCS}
)

target_include_directories(imgui PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/imgui/")
target_include_directories(imgui PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/implot/")
target_include_directories(imgui PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../glfw/include/")
target_include_directories(imgui PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../glad/include/")

Expand Down
1 change: 1 addition & 0 deletions deps/imgui/implot
Submodule implot added at 3da8bd
25 changes: 24 additions & 1 deletion examples/demo-app/demo_app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ void constructDemoCurveNetwork(std::string curveName, std::vector<glm::vec3> nod
valYabs[iE] = std::fabs(midpointPos.y);
}
polyscope::getCurveNetwork(curveName)->addEdgeScalarQuantity("edge len", edgeLen, polyscope::DataType::MAGNITUDE);
polyscope::getCurveNetwork(curveName)->addEdgeScalarQuantity("edge valYabs", valYabs, polyscope::DataType::MAGNITUDE);
polyscope::getCurveNetwork(curveName)->addEdgeScalarQuantity("edge valYabs", valYabs,
polyscope::DataType::MAGNITUDE);
polyscope::getCurveNetwork(curveName)->addEdgeScalarQuantity("edge categorical", valEdgeCat,
polyscope::DataType::CATEGORICAL);
polyscope::getCurveNetwork(curveName)->addEdgeColorQuantity("eColor", randColor);
Expand Down Expand Up @@ -845,6 +846,9 @@ void callback() {
}
}

if (ImGui::Button("nested show")) {
polyscope::show();
}

if (ImGui::Button("drop camera view here")) {
dropCameraView();
Expand All @@ -858,9 +862,28 @@ void callback() {
addVolumeGrid();
}

// ImPlot
// dummy data
if (ImGui::TreeNode("ImPlot")) {

std::vector<float> plotVals;
for (float t = 0; t < 10.; t += 0.01) {
plotVals.push_back(std::cosf(t + ImGui::GetTime()));
}

// sample plot
if (ImPlot::BeginPlot("test plot")) {
ImPlot::PlotLine("sample_val", &plotVals.front(), plotVals.size());
ImPlot::EndPlot();
}

ImGui::TreePop();
}

ImGui::PopItemWidth();
}


int main(int argc, char** argv) {
// Configure the argument parser
args::ArgumentParser parser("A simple demo of Polyscope.\nBy "
Expand Down
1 change: 1 addition & 0 deletions include/polyscope/polyscope.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <unordered_set>

#include "imgui.h"
#include "implot.h"

#include "polyscope/context.h"
#include "polyscope/group.h"
Expand Down
12 changes: 10 additions & 2 deletions src/polyscope.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <thread>

#include "imgui.h"
#include "implot.h"

#include "polyscope/options.h"
#include "polyscope/pick.h"
Expand All @@ -33,6 +34,7 @@ namespace {
// initialization.
struct ContextEntry {
ImGuiContext* context;
ImPlotContext* plotContext;
std ::function<void()> callback;
bool drawDefaultUI;
};
Expand Down Expand Up @@ -183,7 +185,7 @@ void init(std::string backend) {

// Create an initial context based context. Note that calling show() never actually uses this context, because it
// pushes a new one each time. But using frameTick() may use this context.
contextStack.push_back(ContextEntry{ImGui::GetCurrentContext(), nullptr, true});
contextStack.push_back(ContextEntry{ImGui::GetCurrentContext(), ImPlot::GetCurrentContext(), nullptr, true});

view::invalidateView();

Expand All @@ -205,11 +207,13 @@ void pushContext(std::function<void()> callbackFunction, bool drawDefaultUI) {

// Create a new context and push it on to the stack
ImGuiContext* newContext = ImGui::CreateContext();
ImPlotContext* newPlotContext = ImPlot::CreateContext();
ImGuiIO& oldIO = ImGui::GetIO(); // used to GLFW + OpenGL data to the new IO object
#ifdef IMGUI_HAS_DOCK
ImGuiPlatformIO& oldPlatformIO = ImGui::GetPlatformIO();
#endif
ImGui::SetCurrentContext(newContext);
ImPlot::SetCurrentContext(newPlotContext);
#ifdef IMGUI_HAS_DOCK
// Propagate GLFW window handle to new context
ImGui::GetMainViewport()->PlatformHandle = oldPlatformIO.Viewports[0]->PlatformHandle;
Expand All @@ -219,7 +223,8 @@ void pushContext(std::function<void()> callbackFunction, bool drawDefaultUI) {

render::engine->configureImGui();

contextStack.push_back(ContextEntry{newContext, callbackFunction, drawDefaultUI});

contextStack.push_back(ContextEntry{newContext, newPlotContext, callbackFunction, drawDefaultUI});

if (contextStack.size() > 50) {
// Catch bugs with nested show()
Expand Down Expand Up @@ -259,14 +264,17 @@ void pushContext(std::function<void()> callbackFunction, bool drawDefaultUI) {
// Workaround overzealous ImGui assertion before destroying any inner context
// https://github.com/ocornut/imgui/pull/7175
ImGui::SetCurrentContext(newContext);
ImPlot::SetCurrentContext(newPlotContext);
ImGui::GetIO().BackendPlatformUserData = nullptr;
ImGui::GetIO().BackendRendererUserData = nullptr;

ImPlot::DestroyContext(newPlotContext);
ImGui::DestroyContext(newContext);

// Restore the previous context, if there was one
if (!contextStack.empty()) {
ImGui::SetCurrentContext(contextStack.back().context);
ImPlot::SetCurrentContext(contextStack.back().plotContext);
}
}

Expand Down
6 changes: 5 additions & 1 deletion src/render/mock_opengl/mock_gl_engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1576,6 +1576,7 @@ void MockGLEngine::initialize() {

void MockGLEngine::initializeImGui() {
ImGui::CreateContext(); // must call once at start
ImPlot::CreateContext();
configureImGui();
}

Expand All @@ -1597,7 +1598,10 @@ void MockGLEngine::shutdown() {
shutdownImGui();
}

void MockGLEngine::shutdownImGui() { ImGui::DestroyContext(); }
void MockGLEngine::shutdownImGui() {
ImPlot::DestroyContext();
ImGui::DestroyContext();
}

void MockGLEngine::swapDisplayBuffers() {}

Expand Down
1 change: 1 addition & 0 deletions src/render/opengl/gl_engine_egl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,7 @@ void GLEngineEGL::initializeImGui() {
// functions

ImGui::CreateContext();
ImPlot::CreateContext();
configureImGui();
}

Expand Down
2 changes: 2 additions & 0 deletions src/render/opengl/gl_engine_glfw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ void GLEngineGLFW::initializeImGui() {
bindDisplay();

ImGui::CreateContext(); // must call once at start
ImPlot::CreateContext();

// Set up ImGUI glfw bindings
ImGui_ImplGlfw_InitForOpenGL(mainWindow, true);
Expand Down Expand Up @@ -197,6 +198,7 @@ void GLEngineGLFW::shutdownImGui() {
// ImGui shutdown things
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImPlot::DestroyContext();
ImGui::DestroyContext();
}

Expand Down
15 changes: 15 additions & 0 deletions src/screenshot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,18 +47,29 @@ std::vector<unsigned char> getRenderInBuffer(const ScreenshotOptions& options =
bool requestedAlready = redrawRequested();
requestRedraw();

// There's a ton of junk needed here to handle the includeUI case...
// Create a new context and push it on to the stack
// FIXME this solution doesn't really work, it forgets UI state like which nodes were open, scrolled setting, etc.
// I'm not sure if it's possible to do this like we want in ImGui. The alternate solution would be to save the render
// from the previous render pass, but I think that comes with other problems on the Polyscope side. I'm not sure what
// the answer is.
ImGuiContext* oldContext;
ImGuiContext* newContext;
ImPlotContext* oldPlotContext;
ImPlotContext* newPlotContext;
if (options.includeUI) {
// WARNING: code duplicated here and in pushContext()
oldContext = ImGui::GetCurrentContext();
newContext = ImGui::CreateContext();
oldPlotContext = ImPlot::GetCurrentContext();
newPlotContext = ImPlot::CreateContext();
ImGuiIO& oldIO = ImGui::GetIO(); // used to GLFW + OpenGL data to the new IO object
#ifdef IMGUI_HAS_DOCK
ImGuiPlatformIO& oldPlatformIO = ImGui::GetPlatformIO();
#endif
ImGui::SetCurrentContext(newContext);
ImPlot::SetCurrentContext(newPlotContext);

#ifdef IMGUI_HAS_DOCK
// Propagate GLFW window handle to new context
ImGui::GetMainViewport()->PlatformHandle = oldPlatformIO.Viewports[0]->PlatformHandle;
Expand All @@ -81,11 +92,15 @@ std::vector<unsigned char> getRenderInBuffer(const ScreenshotOptions& options =
// Workaround overzealous ImGui assertion before destroying any inner context
// https://github.com/ocornut/imgui/pull/7175
ImGui::SetCurrentContext(newContext);
ImPlot::SetCurrentContext(newPlotContext);
ImGui::GetIO().BackendPlatformUserData = nullptr;
ImGui::GetIO().BackendRendererUserData = nullptr;

ImPlot::DestroyContext(newPlotContext);
ImGui::DestroyContext(newContext);

ImGui::SetCurrentContext(oldContext);
ImPlot::SetCurrentContext(oldPlotContext);
}


Expand Down
50 changes: 50 additions & 0 deletions test/src/basics_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ TEST_F(PolyscopeTest, FrameTickWithImgui) {
polyscope::state::userCallback = nullptr;
}


// We should be able to nest calls to show() via the callback. ImGUI causes headaches here
TEST_F(PolyscopeTest, NestedShow) {

Expand Down Expand Up @@ -148,6 +149,55 @@ TEST_F(PolyscopeTest, ScreenshotBuffer) {
EXPECT_EQ(buff2.size(), polyscope::view::bufferWidth * polyscope::view::bufferHeight * 4);
}

TEST_F(PolyscopeTest, ImPlotBasic) {

std::vector<float> xvals = {0., 2., 4., 8.};

auto showCallback = [&]() {
ImGui::Button("do something");
if(ImPlot::BeginPlot("test plot")) {
ImPlot::PlotLine("test line", &xvals.front(), xvals.size());
ImPlot::EndPlot();
}
};
polyscope::state::userCallback = showCallback;

polyscope::show(3);

for (int i = 0; i < 3; i++) {
polyscope::frameTick();
}

polyscope::state::userCallback = nullptr;
}


TEST_F(PolyscopeTest, ImPlotScreenshot) {
// test this because there is some context logic duplicated there

std::vector<float> xvals = {0., 2., 4., 8.};

auto showCallback = [&]() {
ImGui::Button("do something");
if(ImPlot::BeginPlot("test plot")) {
ImPlot::PlotLine("test line", &xvals.front(), xvals.size());
ImPlot::EndPlot();
}
};
polyscope::state::userCallback = showCallback;

polyscope::show(3);

polyscope::ScreenshotOptions opts;
opts.includeUI = true;
opts.transparentBackground = false;
polyscope::screenshot(opts);

polyscope::show(3);

polyscope::state::userCallback = nullptr;
}

// ============================================================
// =============== View and navigation
// ============================================================
Expand Down
Loading