diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 722427282..ed57c6f6b 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -66,6 +66,7 @@ option(LIBIGL_WITH_PNG "Use PNG" ON) option(LIBIGL_WITH_TETGEN "Use Tetgen" ON) option(LIBIGL_WITH_TRIANGLE "Use Triangle" ON) option(LIBIGL_WITH_XML "Use XML" ON) +option(LIBIGL_WITH_PYTHON "Use Python" OFF) if(LIBIGL_WITH_CGAL) # Do not remove or move this block, cgal strange build system fails without it find_package(CGAL REQUIRED) @@ -132,6 +133,10 @@ set_target_properties(pyigl PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE target_link_libraries(pyigl ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES}) +# Copy the nanogui bindings +#get_target_property(NANOGUI_LIB nanogui_python LOCATION) +#file(COPY ${NANOGUI_LIB} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/../) + if (WIN32) if (MSVC) # Enforce size-based optimization and link time code generation on MSVC (~30% smaller binaries in experiments) @@ -147,7 +152,6 @@ if (WIN32) # target_link_libraries(igl ${PYTHON_LIBRARY}) target_link_libraries(pyigl ${PYTHON_LIBRARIES}) - elseif (UNIX) # It's quite common to have multiple copies of the same Python version # installed on one's system. E.g.: one copy from the OS and another copy diff --git a/python/modules/py_igl_viewer.cpp b/python/modules/py_igl_viewer.cpp index 8c3f21f6e..f8bfb77b0 100644 --- a/python/modules/py_igl_viewer.cpp +++ b/python/modules/py_igl_viewer.cpp @@ -312,6 +312,14 @@ py::class_ viewercore_class(me, "ViewerCore"); // UI Enumerations py::class_ viewer_class(me, "Viewer"); + #ifdef IGL_VIEWER_WITH_NANOGUI + py::object fh = (py::object) py::module::import("nanogui").attr("FormHelper"); + py::class_ form_helper_class(me, "FormHelper", fh); + + py::object screen = (py::object) py::module::import("nanogui").attr("Screen"); + py::class_ screen_class(me, "Screen", screen); + #endif + py::enum_(viewer_class, "MouseButton") .value("Left", igl::viewer::Viewer::MouseButton::Left) .value("Middle", igl::viewer::Viewer::MouseButton::Middle) @@ -323,6 +331,12 @@ py::class_ viewercore_class(me, "ViewerCore"); .def_readwrite("data", &igl::viewer::Viewer::data) .def_readwrite("core", &igl::viewer::Viewer::core) .def_readwrite("opengl", &igl::viewer::Viewer::opengl) + + #ifdef IGL_VIEWER_WITH_NANOGUI + .def_readwrite("ngui", &igl::viewer::Viewer::ngui) + .def_readwrite("screen", &igl::viewer::Viewer::screen) + #endif + .def("launch", &igl::viewer::Viewer::launch, py::arg("resizable") = true, py::arg("fullscreen") = false) .def("launch_init", &igl::viewer::Viewer::launch_init, py::arg("resizable") = true, py::arg("fullscreen") = false) .def("launch_rendering", &igl::viewer::Viewer::launch_rendering, py::arg("loop") = true) diff --git a/python/tutorial/106_ViewerMenu.py b/python/tutorial/106_ViewerMenu.py new file mode 100644 index 000000000..481299cb5 --- /dev/null +++ b/python/tutorial/106_ViewerMenu.py @@ -0,0 +1,83 @@ +# Add the igl library to the modules search path +import sys, os +sys.path.insert(0, os.getcwd() + "/../") + +import pyigl as igl +import nanogui + +V1 = igl.eigen.MatrixXd() +F1 = igl.eigen.MatrixXi() + +V2 = igl.eigen.MatrixXd() +F2 = igl.eigen.MatrixXi() + +float_variable = 0.1 +bool_variable = True +dir = 0 + + +def make_accessors(name): + def setter(value): + globals()[name] = value + + def getter(): + return globals()[name] + return setter, getter + + +def viewer_init(viewer): + # add new group + viewer.ngui.addGroup("New Group") + + # Expose the using general callback + viewer.ngui.addDoubleVariable("double", *make_accessors("float_variable")) + + def setter(val): + global bool_variable + bool_variable = val + + def getter(): + global bool_variable + return bool_variable + + # ... or using a custom callback + viewer.ngui.addBoolVariable("bool", setter, getter) + + viewer.ngui.addEnumVariable("Direction", *make_accessors("dir")) \ + .setItems(["Up", "Down", "Left", "Right"]) + + # Add a button + def cb(): + print("Hello") + viewer.ngui.addButton("Print Hello", cb) + + #Add an additional menu window + viewer.ngui.addWindow(nanogui.Vector2i(220, 10), "New Window") + + # add accessor + viewer.ngui.addDoubleVariable("double", *make_accessors("float_variable")) + + #Generate menu + viewer.screen.performLayout() + + return False + + + +def main(): + # Load a mesh in OFF format + igl.readOFF("../../tutorial/shared/bunny.off", V1, F1) + + # Init the viewer + viewer = igl.viewer.Viewer() + + # Extend viewer menu + viewer.callback_init = viewer_init + + # Plot the mesh + viewer.data.set_mesh(V1, F1) + viewer.launch() + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/shared/cmake/CMakeLists.txt b/shared/cmake/CMakeLists.txt index d113f1715..5f2d809ed 100644 --- a/shared/cmake/CMakeLists.txt +++ b/shared/cmake/CMakeLists.txt @@ -19,7 +19,7 @@ option(LIBIGL_WITH_TETGEN "Use Tetgen" OFF) option(LIBIGL_WITH_TRIANGLE "Use Triangle" OFF) option(LIBIGL_WITH_VIEWER "Use OpenGL viewer" OFF) option(LIBIGL_WITH_XML "Use XML" OFF) - +option(LIBIGL_WITH_PYTHON "Use Python" OFF) ### Compilation configuration ### if(MSVC) @@ -102,14 +102,14 @@ endif() if(LIBIGL_WITH_ANTTWEAKBAR) set(ANTTWEAKBAR_DIR "${LIBIGL_EXTERNAL}/anttweakbar") set(ANTTWEAKBAR_INCLUDE_DIR "${ANTTWEAKBAR_DIR}/include") - set(ANTTWEAKBAR_C_SRC_FILES + set(ANTTWEAKBAR_C_SRC_FILES "${ANTTWEAKBAR_DIR}/src/TwEventGLFW.c" "${ANTTWEAKBAR_DIR}/src/TwEventGLUT.c" "${ANTTWEAKBAR_DIR}/src/TwEventSDL.c" "${ANTTWEAKBAR_DIR}/src/TwEventSDL12.c" "${ANTTWEAKBAR_DIR}/src/TwEventSDL13.c" ) - set(ANTTWEAKBAR_CPP_SRC_FILES + set(ANTTWEAKBAR_CPP_SRC_FILES "${ANTTWEAKBAR_DIR}/src/LoadOGL.cpp" "${ANTTWEAKBAR_DIR}/src/LoadOGLCore.cpp" "${ANTTWEAKBAR_DIR}/src/TwBar.cpp" @@ -129,15 +129,15 @@ if(LIBIGL_WITH_ANTTWEAKBAR) #"${ANTTWEAKBAR_DIR}/src/TwDirect3D11.cpp" #"${ANTTWEAKBAR_DIR}/src/TwDirect3D9.cpp" list( - APPEND - ANTTWEAKBAR_SRC_FILES + APPEND + ANTTWEAKBAR_SRC_FILES "${ANTTWEAKBAR_C_SRC_FILES}" "${ANTTWEAKBAR_CPP_SRC_FILES}") add_library(AntTweakBar STATIC "${ANTTWEAKBAR_SRC_FILES}") target_include_directories(AntTweakBar PUBLIC "${ANTTWEAKBAR_INCLUDE_DIR}") if(APPLE) set_target_properties( - AntTweakBar + AntTweakBar PROPERTIES COMPILE_FLAGS "-fPIC -fno-strict-aliasing -x objective-c++") @@ -286,7 +286,7 @@ if(LIBIGL_WITH_LIM) add_subdirectory("${LIM_DIR}" "lim") list(APPEND LIBIGL_INCLUDE_DIRS ${LIM_DIR}) ## it depends on ligigl, so placing it here solve linking problems - #list(APPEND LIBIGL_LIBRARIES "lim") + #list(APPEND LIBIGL_LIBRARIES "lim") # ^--- Alec: I don't understand this comment. Does lim need to come before # libigl libraries? Why can't lim be placed where it belongs in # LIBIGL_EXTRA_LIBRARIES? @@ -389,7 +389,12 @@ if(LIBIGL_WITH_VIEWER) if(LIBIGL_WITH_NANOGUI) list(APPEND LIBIGL_DEFINITIONS "-DIGL_VIEWER_WITH_NANOGUI") - set(NANOGUI_BUILD_PYTHON OFF CACHE BOOL " " FORCE) + if (LIBIGL_WITH_PYTHON) + set(NANOGUI_BUILD_PYTHON ON CACHE BOOL " " FORCE) + else() + set(NANOGUI_BUILD_PYTHON OFF CACHE BOOL " " FORCE) + endif() + set(NANOGUI_BUILD_EXAMPLE OFF CACHE BOOL " " FORCE) set(NANOGUI_BUILD_SHARED OFF CACHE BOOL " " FORCE) add_subdirectory("${NANOGUI_DIR}" "nanogui")