diff --git a/recipes/vsgimgui/bld.bat b/recipes/vsgimgui/bld.bat new file mode 100644 index 0000000000000..6855a17b2fdb8 --- /dev/null +++ b/recipes/vsgimgui/bld.bat @@ -0,0 +1,20 @@ +@echo on + +:: Remove existing imgui and implot headers to use the external ones installed by their Conda packages +del /q include\vsgImGui\imgui.h +del /q include\vsgImGui\implot.h +if errorlevel 1 exit 1 + +cmake %SRC_DIR% ^ + %CMAKE_ARGS% ^ + -B build ^ + -DBUILD_SHARED_LIBS=ON ^ + -DVSG_IMGUI_USE_SYSTEM_IMGUI=ON ^ + -DVSG_IMGUI_USE_SYSTEM_IMPLOT=ON +if errorlevel 1 exit 1 + +cmake --build build --parallel --config Release +if errorlevel 1 exit 1 + +cmake --install build --config Release +if errorlevel 1 exit 1 diff --git a/recipes/vsgimgui/build.sh b/recipes/vsgimgui/build.sh new file mode 100644 index 0000000000000..53674596016e2 --- /dev/null +++ b/recipes/vsgimgui/build.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +set -exo pipefail + +# Remove existing imgui and implot headers to use the external ones installed by their Conda packages +rm include/vsgImGui/imgui.h +rm include/vsgImGui/implot.h + +cmake $SRC_DIR \ + ${CMAKE_ARGS} \ + -G Ninja \ + -B build \ + -DBUILD_SHARED_LIBS=ON \ + -DCMAKE_BUILD_TYPE=Release \ + -DVSG_IMGUI_USE_SYSTEM_IMGUI=ON \ + -DVSG_IMGUI_USE_SYSTEM_IMPLOT=ON + +cmake --build build --parallel + +cmake --install build --strip diff --git a/recipes/vsgimgui/meta.yaml b/recipes/vsgimgui/meta.yaml new file mode 100644 index 0000000000000..dd969445c6539 --- /dev/null +++ b/recipes/vsgimgui/meta.yaml @@ -0,0 +1,65 @@ +{% set name = "vsgImGui" %} +{% set version = "0.6.0" %} + +package: + name: {{ name|lower }} + version: {{ version }} + +source: + - url: https://github.com/vsg-dev/vsgImGui/archive/v{{ version }}.tar.gz + sha256: 1697d53c4d4a91b90837c16196d891ecff20bb0469e1947caccada03e6dca864 + patches: + - patches/0001-Add-options-to-use-system-dependencies.patch + - patches/0003-Find-imgui-and-implot-in-package-config-when-system-.patch + +build: + number: 0 + run_exports: + - {{ pin_subpackage('vsgimgui', max_pin='x.x') }} + +requirements: + build: + - {{ compiler('cxx') }} + - {{ stdlib('c') }} + - cmake + - ninja # [not win] + - pkgconfig # [linux] + host: + - imgui + - implot + - libvulkan-headers + - libvulkan-loader + - vulkanscenegraph + run: + - libvulkan-loader + - vulkanscenegraph + +test: + commands: + - test -f $PREFIX/include/vsgImGui/Export.h # [not win] + - test -f $PREFIX/lib/libvsgImGui${SHLIB_EXT} # [not win] + - test -f $PREFIX/lib/cmake/vsgImGui/vsgImGuiConfig.cmake # [not win] + - if not exist %PREFIX%\\Library\\include\\vsgImGui\\Export.h exit 1 # [win] + - if not exist %PREFIX%\\Library\\lib\\vsgImGui.lib exit 1 # [win] + - if not exist %PREFIX%\\Library\\bin\\vsgImGui.dll exit 1 # [win] + - if not exist %PREFIX%\\Library\\lib\\cmake\\vsgImGui\\vsgImGuiConfig.cmake exit 1 # [win] + requires: + - {{ compiler("c") }} + - {{ compiler("cxx") }} + - cmake + - ninja # [not win] + - pkgconfig # [linux] + - vsgXchange + files: + - tests/ + +about: + home: https://vsg-dev.github.io/vsg-dev.io/ + summary: Integration of VulkanSceneGraph with ImGui + license: MIT + license_file: LICENSE.md + dev_url: https://github.com/vsg-dev/vsgImGui + +extra: + recipe-maintainers: + - jeongseok-meta diff --git a/recipes/vsgimgui/patches/0001-Add-options-to-use-system-dependencies.patch b/recipes/vsgimgui/patches/0001-Add-options-to-use-system-dependencies.patch new file mode 100644 index 0000000000000..3bda7443c8ed4 --- /dev/null +++ b/recipes/vsgimgui/patches/0001-Add-options-to-use-system-dependencies.patch @@ -0,0 +1,248 @@ +From 13d974246cea7cb24b985008516a947bf393f53c Mon Sep 17 00:00:00 2001 +From: Jeongseok Lee +Date: Thu, 23 Jan 2025 15:36:00 -0800 +Subject: [PATCH 1/2] Add options to use system dependencies + +--- + CMakeLists.txt | 54 ++++++++++++++-------- + include/vsgImGui/RenderImGui.h | 2 +- + src/CMakeLists.txt | 74 +++++++++++++++++++++--------- + src/vsgImGui/RenderImGui.cpp | 4 +- + src/vsgImGui/SendEventsToImGui.cpp | 2 +- + 5 files changed, 93 insertions(+), 43 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index e1679d2..464b8ee 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -5,6 +5,10 @@ project(vsgImGui + DESCRIPTION "VulkanSceneGraph, ImGui and ImPlot integration library" + LANGUAGES CXX + ) ++ ++option(VSG_IMGUI_USE_SYSTEM_IMGUI "Use system installed ImGui" OFF) ++option(VSG_IMGUI_USE_SYSTEM_IMPLOT "Use system installed ImPlot" OFF) ++ + set(VSGIMGUI_SOVERSION 0) + SET(VSGIMGUI_RELEASE_CANDIDATE 0) + +@@ -27,29 +31,43 @@ find_package(vsg 1.0.5) + vsg_setup_dir_vars() + vsg_setup_build_vars() + +-if ( (NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/src/imgui/imgui.h) OR +- (NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/src/implot/implot.h) ) +- find_package(Git QUIET) ++if(NOT VSG_IMGUI_USE_SYSTEM_IMGUI OR NOT VSG_IMGUI_USE_SYSTEM_IMPLOT) ++ if ( (NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/src/imgui/imgui.h) OR ++ (NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/src/implot/implot.h) ) ++ find_package(Git QUIET) + +- execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive +- WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +- RESULT_VARIABLE GIT_SUBMOD_RESULT) ++ execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive ++ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ++ RESULT_VARIABLE GIT_SUBMOD_RESULT) + +- if(NOT GIT_SUBMOD_RESULT EQUAL "0") +- message(FATAL_ERROR "git submodule update --init --recursive failed with ${GIT_SUBMOD_RESULT}, please checkout submodules") ++ if(NOT GIT_SUBMOD_RESULT EQUAL "0") ++ message(FATAL_ERROR "git submodule update --init --recursive failed with ${GIT_SUBMOD_RESULT}, please checkout submodules") ++ endif() + endif() + endif() + +-vsg_copy_imgui_headers( +- FILES +- ${VSGIMGUI_SOURCE_DIR}/src/imgui/imgui.h +- ${VSGIMGUI_SOURCE_DIR}/src/imgui/imconfig.h +- ${VSGIMGUI_SOURCE_DIR}/src/imgui/imgui_internal.h +- ${VSGIMGUI_SOURCE_DIR}/src/imgui/imstb_textedit.h +- ${VSGIMGUI_SOURCE_DIR}/src/imgui//misc/cpp/imgui_stdlib.h +- ${VSGIMGUI_SOURCE_DIR}/src/implot/implot.h +- ${VSGIMGUI_SOURCE_DIR}/src/implot/implot_internal.h +-) ++if(VSG_IMGUI_USE_SYSTEM_IMGUI) ++ find_package(imgui CONFIG REQUIRED) ++else() ++ vsg_copy_imgui_headers( ++ FILES ++ ${VSGIMGUI_SOURCE_DIR}/src/imgui/imgui.h ++ ${VSGIMGUI_SOURCE_DIR}/src/imgui/imconfig.h ++ ${VSGIMGUI_SOURCE_DIR}/src/imgui/imgui_internal.h ++ ${VSGIMGUI_SOURCE_DIR}/src/imgui/imstb_textedit.h ++ ${VSGIMGUI_SOURCE_DIR}/src/imgui//misc/cpp/imgui_stdlib.h ++ ) ++endif() ++ ++if(VSG_IMGUI_USE_SYSTEM_IMPLOT) ++ find_package(implot CONFIG REQUIRED) ++else() ++ vsg_copy_imgui_headers( ++ FILES ++ ${VSGIMGUI_SOURCE_DIR}/src/implot/implot.h ++ ${VSGIMGUI_SOURCE_DIR}/src/implot/implot_internal.h ++ ) ++endif() + + vsg_add_target_clang_format( + FILES +diff --git a/include/vsgImGui/RenderImGui.h b/include/vsgImGui/RenderImGui.h +index 26a644d..3e427cd 100644 +--- a/include/vsgImGui/RenderImGui.h ++++ b/include/vsgImGui/RenderImGui.h +@@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + #include + + #include +-#include ++#include + + namespace vsgImGui + { +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index 41d749d..97720b2 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -6,41 +6,60 @@ set(EXTRA_INCLUDES) + SET(HEADER_PATH ${VSGIMGUI_SOURCE_DIR}/include/vsgImGui) + + set(HEADERS +- ${HEADER_PATH}/imgui.h + ${HEADER_PATH}/SendEventsToImGui.h + ${HEADER_PATH}/RenderImGui.h + ${HEADER_PATH}/Texture.h +- imgui/imconfig.h +- imgui/imgui_internal.h +- imgui/imstb_rectpack.h +- imgui/imstb_textedit.h +- imgui/imstb_truetype.h +- imgui/misc/cpp/imgui_stdlib.h +- implot/implot.h +- implot/implot_internal.h + ) + + set(SOURCES + vsgImGui/RenderImGui.cpp + vsgImGui/SendEventsToImGui.cpp + vsgImGui/Texture.cpp +- imgui/imgui.cpp +- imgui/imgui_draw.cpp +- imgui/imgui_tables.cpp +- imgui/imgui_widgets.cpp +- imgui/backends/imgui_impl_vulkan.cpp +- imgui/misc/cpp/imgui_stdlib.cpp +- implot/implot.cpp +- implot/implot_items.cpp + ) + +-OPTION(SHOW_DEMO_WINDOW "Toggle the build of the ImGui::ShowDemoWindow(bool*) and ImPlot::ShadowDemoWindow(bool*)" ON) ++if(NOT VSG_IMGUI_USE_SYSTEM_IMGUI) ++ set(HEADERS ${HEADERS} ++ imgui/imgui.h ++ imgui/imconfig.h ++ imgui/imgui_internal.h ++ imgui/imstb_rectpack.h ++ imgui/imstb_textedit.h ++ imgui/imstb_truetype.h ++ imgui/misc/cpp/imgui_stdlib.h ++ ) + +-if (SHOW_DEMO_WINDOW) + set(SOURCES ${SOURCES} +- imgui/imgui_demo.cpp +- implot/implot_demo.cpp ++ imgui/imgui.cpp ++ imgui/imgui_draw.cpp ++ imgui/imgui_tables.cpp ++ imgui/imgui_widgets.cpp ++ imgui/backends/imgui_impl_vulkan.cpp ++ imgui/misc/cpp/imgui_stdlib.cpp ++ ) ++endif() ++ ++if(NOT VSG_IMGUI_USE_SYSTEM_IMPLOT) ++ set(HEADERS ${HEADERS} ++ implot/implot.h ++ implot/implot_internal.h + ) ++ ++ set(SOURCES ${SOURCES} ++ implot/implot.cpp ++ implot/implot_items.cpp ++ ) ++endif() ++ ++OPTION(SHOW_DEMO_WINDOW "Toggle the build of the ImGui::ShowDemoWindow(bool*) and ImPlot::ShadowDemoWindow(bool*)" ON) ++ ++if (SHOW_DEMO_WINDOW) ++ if(NOT VSG_IMGUI_USE_SYSTEM_IMGUI) ++ set(HEADERS ${HEADERS} imgui/imgui_demo.cpp) ++ endif() ++ ++ if(NOT VSG_IMGUI_USE_SYSTEM_IMPLOT) ++ set(SOURCES ${SOURCES} implot/implot_demo.cpp) ++ endif() + else() + set(SOURCES ${SOURCES} + vsgImGui/fallback_demo.cpp +@@ -69,6 +88,11 @@ target_include_directories(vsgImGui PUBLIC + $ + ${EXTRA_INCLUDES} + ) ++if(NOT VSG_IMGUI_USE_SYSTEM_IMGUI) ++ target_include_directories(vsgImGui PRIVATE ++ $ ++ ) ++endif() + + target_link_libraries(vsgImGui + PUBLIC +@@ -77,6 +101,14 @@ target_link_libraries(vsgImGui + ${EXTRA_LIBRARIES} + ) + ++if(VSG_IMGUI_USE_SYSTEM_IMGUI) ++ target_link_libraries(vsgImGui PUBLIC imgui::imgui) ++endif() ++ ++if(VSG_IMGUI_USE_SYSTEM_IMPLOT) ++ target_link_libraries(vsgImGui PUBLIC implot::implot) ++endif() ++ + install(TARGETS vsgImGui ${INSTALL_TARGETS_DEFAULT_FLAGS}) + + if (BUILD_SHARED_LIBS) +diff --git a/src/vsgImGui/RenderImGui.cpp b/src/vsgImGui/RenderImGui.cpp +index 306030b..f0af046 100644 +--- a/src/vsgImGui/RenderImGui.cpp ++++ b/src/vsgImGui/RenderImGui.cpp +@@ -22,9 +22,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + #include +-#include ++#include + +-#include "../imgui/backends/imgui_impl_vulkan.h" ++#include + + #include + #include +diff --git a/src/vsgImGui/SendEventsToImGui.cpp b/src/vsgImGui/SendEventsToImGui.cpp +index 11de226..ef784fc 100644 +--- a/src/vsgImGui/SendEventsToImGui.cpp ++++ b/src/vsgImGui/SendEventsToImGui.cpp +@@ -22,7 +22,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + #include +-#include ++#include + + #include + #include +-- +2.20.1.windows.1 + diff --git a/recipes/vsgimgui/patches/0003-Find-imgui-and-implot-in-package-config-when-system-.patch b/recipes/vsgimgui/patches/0003-Find-imgui-and-implot-in-package-config-when-system-.patch new file mode 100644 index 0000000000000..8c3422597bdb8 --- /dev/null +++ b/recipes/vsgimgui/patches/0003-Find-imgui-and-implot-in-package-config-when-system-.patch @@ -0,0 +1,30 @@ +From 371693daf6845b7051fcbbd99f45533100e17864 Mon Sep 17 00:00:00 2001 +From: Jeongseok Lee +Date: Thu, 23 Jan 2025 17:01:25 -0800 +Subject: [PATCH 3/3] Find imgui and implot in package config when system + installed ones were used + +--- + src/vsgImGuiConfig.cmake.in | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/src/vsgImGuiConfig.cmake.in b/src/vsgImGuiConfig.cmake.in +index e2c14f2..80f9b41 100644 +--- a/src/vsgImGuiConfig.cmake.in ++++ b/src/vsgImGuiConfig.cmake.in +@@ -2,5 +2,12 @@ include(CMakeFindDependencyMacro) + + find_dependency(Vulkan) + find_dependency(vsg) ++if(@VSG_IMGUI_USE_SYSTEM_IMGUI@) ++ find_dependency(imgui CONFIG) ++endif() ++ ++if(@VSG_IMGUI_USE_SYSTEM_IMPLOT@) ++ find_dependency(implot CONFIG) ++endif() + + include("${CMAKE_CURRENT_LIST_DIR}/vsgImGuiTargets.cmake") +-- +2.20.1.windows.1 + diff --git a/recipes/vsgimgui/run_test.bat b/recipes/vsgimgui/run_test.bat new file mode 100644 index 0000000000000..b0ac1ca0eaeb3 --- /dev/null +++ b/recipes/vsgimgui/run_test.bat @@ -0,0 +1,10 @@ +@echo on + +cmake tests ^ + %CMAKE_ARGS% ^ + -B tests/build ^ + -DBUILD_SHARED_LIBS=ON +if errorlevel 1 exit 1 + +cmake --build tests/build --parallel --config Release +if errorlevel 1 exit 1 diff --git a/recipes/vsgimgui/run_test.sh b/recipes/vsgimgui/run_test.sh new file mode 100644 index 0000000000000..89909aa8a46f5 --- /dev/null +++ b/recipes/vsgimgui/run_test.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +set -exo pipefail + +cmake tests \ + ${CMAKE_ARGS} \ + -G Ninja \ + -B tests/build \ + -DBUILD_SHARED_LIBS=ON \ + -DCMAKE_BUILD_TYPE=Release + +cmake --build tests/build --parallel diff --git a/recipes/vsgimgui/tests/CMakeLists.txt b/recipes/vsgimgui/tests/CMakeLists.txt new file mode 100644 index 0000000000000..b250be661da06 --- /dev/null +++ b/recipes/vsgimgui/tests/CMakeLists.txt @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 3.7) + +project(vsghelloworld) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +find_package(vsgXchange CONFIG REQUIRED) +find_package(vsgImGui CONFIG REQUIRED) + +add_executable(vsghelloworld main.cpp) +target_link_libraries(vsghelloworld PRIVATE vsgXchange::vsgXchange vsgImGui::vsgImGui) diff --git a/recipes/vsgimgui/tests/main.cpp b/recipes/vsgimgui/tests/main.cpp new file mode 100644 index 0000000000000..eba88f8b32a00 --- /dev/null +++ b/recipes/vsgimgui/tests/main.cpp @@ -0,0 +1,283 @@ +// https://github.com/vsg-dev/vsgExamples/blob/d4272d5d80c995ffa309601a9847f05f3acaa805/examples/ui/vsgimgui_example/vsgimgui_example.cpp + +#include +#include +#include +#include +#include + +#include + +#include + +#include + +struct Params : public vsg::Inherit +{ + bool showGui = true; // you can toggle this with your own EventHandler and key + bool showDemoWindow = false; + bool showSecondWindow = false; + bool showImPlotDemoWindow = false; + bool showLogoWindow = true; + bool showImagesWindow = false; + float clearColor[3]{0.2f, 0.2f, 0.4f}; // Unfortunately, this doesn't change dynamically in vsg + uint32_t counter = 0; + float dist = 0.f; +}; + +class MyGui : public vsg::Inherit +{ +public: + vsg::ref_ptr texture; + vsg::ref_ptr params; + + MyGui(vsg::ref_ptr in_params, vsg::ref_ptr options = {}) : + params(in_params) + { + auto texData = vsg::read_cast("textures/VSGlogo.png", options); + texture = vsgImGui::Texture::create_if(texData, texData); + } + + // we need to compile textures before we can use them for rendering + void compile(vsg::Context& context) override + { + if (texture) texture->compile(context); + } + + // Example here taken from the Dear imgui comments (mostly) + void record(vsg::CommandBuffer& cb) const override + { + // 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window. + if (params->showGui) + { + ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it. + + ImGui::Text("Some useful message here."); // Display some text (you can use format strings too) + ImGui::Checkbox("Demo Window", ¶ms->showDemoWindow); // Edit bools storing our window open/close state + ImGui::Checkbox("Another Window", ¶ms->showSecondWindow); + ImGui::Checkbox("ImPlot Demo Window", ¶ms->showImPlotDemoWindow); + if (texture) + { + ImGui::Checkbox("Images Window", ¶ms->showImagesWindow); + } + + ImGui::SliderFloat("float", ¶ms->dist, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f + ImGui::ColorEdit3("clear color", (float*)¶ms->clearColor); // Edit 3 floats representing a color + + if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated) + params->counter++; + + ImGui::SameLine(); + ImGui::Text("counter = %d", params->counter); + + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); + ImGui::End(); + } + + // 3. Show another simple window. + if (params->showSecondWindow) + { + ImGui::Begin("Another Window", ¶ms->showSecondWindow); // Pass a pointer to our bool variable (the window will have a close button that will clear the bool when clicked) + ImGui::Text("Hello from another window!"); + if (ImGui::Button("Close Me")) + params->showSecondWindow = false; + ImGui::End(); + } + + if (params->showDemoWindow) + { + ImGui::ShowDemoWindow(¶ms->showDemoWindow); + } + + if (params->showImPlotDemoWindow) + { + ImPlot::ShowDemoWindow(¶ms->showImPlotDemoWindow); + } + } +}; + +int main(int argc, char** argv) +{ + auto options = vsg::Options::create(); + options->sharedObjects = vsg::SharedObjects::create(); + options->fileCache = vsg::getEnv("VSG_FILE_CACHE"); + options->paths = vsg::getEnvPaths("VSG_FILE_PATH"); +#ifdef vsgXchange_all + // add vsgXchange's support for reading and writing 3rd party file formats + options->add(vsgXchange::all::create()); +#endif + + auto windowTraits = vsg::WindowTraits::create(); + windowTraits->windowTitle = "vsgimgui"; + + // set up defaults and read command line arguments to override them + vsg::CommandLine arguments(&argc, argv); + arguments.read(options); + + auto event_read_filename = arguments.value(std::string(""), "-i"); + auto event_output_filename = arguments.value(std::string(""), "-o"); + + windowTraits->debugLayer = arguments.read({"--debug", "-d"}); + windowTraits->apiDumpLayer = arguments.read({"--api", "-a"}); + arguments.read("--screen", windowTraits->screenNum); + arguments.read("--display", windowTraits->display); + arguments.read("--samples", windowTraits->samples); + auto numFrames = arguments.value(-1, "-f"); + auto fontFile = arguments.value({}, "--font"); + auto fontSize = arguments.value(30.0f, "--font-size"); + + if (arguments.errors()) return arguments.writeErrorMessages(std::cerr); + + try + { + auto vsg_scene = vsg::Group::create(); + vsg::ref_ptr ellipsoidModel; + + if (argc > 1) + { + vsg::Path filename = arguments[1]; + if (auto node = vsg::read_cast(filename, options); node) + { + vsg_scene->addChild(node); + + ellipsoidModel = node->getRefObject("EllipsoidModel"); + } + } + + // create the viewer and assign window(s) to it + auto viewer = vsg::Viewer::create(); + + vsg::ref_ptr window(vsg::Window::create(windowTraits)); + if (!window) + { + std::cout << "Could not create window." << std::endl; + return 1; + } + + viewer->addWindow(window); + + // compute the bounds of the scene graph to help position camera + vsg::ComputeBounds computeBounds; + vsg_scene->accept(computeBounds); + vsg::dvec3 centre = (computeBounds.bounds.min + computeBounds.bounds.max) * 0.5; + double radius = vsg::length(computeBounds.bounds.max - computeBounds.bounds.min) * 0.6; + + // These are set statically because the geometry in the class is expanded in the shader + double nearFarRatio = 0.01; + + // set up the camera + auto lookAt = vsg::LookAt::create(centre + vsg::dvec3(0.0, -radius * 3.5, 0.0), centre, vsg::dvec3(0.0, 0.0, 1.0)); + + vsg::ref_ptr perspective; + if (ellipsoidModel) + { + perspective = vsg::EllipsoidPerspective::create(lookAt, ellipsoidModel, 30.0, static_cast(window->extent2D().width) / static_cast(window->extent2D().height), nearFarRatio, 0.0); + } + else + { + perspective = vsg::Perspective::create(30.0, static_cast(window->extent2D().width) / static_cast(window->extent2D().height), nearFarRatio * radius, radius * 400.5); + } + + auto camera = vsg::Camera::create(perspective, lookAt, vsg::ViewportState::create(window->extent2D())); + + // The commandGraph will contain a 2 stage renderGraph: 1) 3D scene 2) ImGui (by default also includes clearing of depth buffers) + auto commandGraph = vsg::CommandGraph::create(window); + auto renderGraph = vsg::RenderGraph::create(window); + commandGraph->addChild(renderGraph); + + // create the normal 3D view of the scene + auto view = vsg::View::create(camera); + view->addChild(vsg::createHeadlight()); + view->addChild(vsg_scene); + + renderGraph->addChild(view); + + if (fontFile) + { + auto foundFontFile = vsg::findFile(fontFile, options); + if (foundFontFile) + { + // convert native filename to UTF8 string that is compatible with ImGui. + std::string c_fontFile = foundFontFile.string(); + + // initialize ImGui + ImGui::CreateContext(); + + // read the font via ImGui, which will then be current when vsgImGui::RenderImGui initializes the rest of ImGui/Vulkan below + ImGuiIO& io = ImGui::GetIO(); + auto imguiFont = io.Fonts->AddFontFromFileTTF(c_fontFile.c_str(), fontSize); + if (!imguiFont) + { + std::cout << "Failed to load font: " << c_fontFile << std::endl; + return 0; + } + } + } + + // Create the ImGui node and add it to the renderGraph + auto params = Params::create(); + auto renderImGui = vsgImGui::RenderImGui::create(window, MyGui::create(params, options)); + renderGraph->addChild(renderImGui); + + // Add the ImGui event handler first to handle events early + viewer->addEventHandler(vsgImGui::SendEventsToImGui::create()); + + // add close handler to respond to the close window button and pressing escape + viewer->addEventHandler(vsg::CloseHandler::create(viewer)); + + viewer->addEventHandler(vsg::Trackball::create(camera, ellipsoidModel)); + + viewer->assignRecordAndSubmitTaskAndPresentation({commandGraph}); + + viewer->compile(); + + vsg::ref_ptr recordEvents; + if (!event_output_filename.empty()) + { + recordEvents = vsg::RecordEvents::create(); + viewer->addEventHandler(recordEvents); + } + + vsg::ref_ptr playEvents; + if (!event_read_filename.empty()) + { + auto read_events = vsg::read(event_read_filename); + if (read_events) + { + playEvents = vsg::PlayEvents::create(read_events, viewer->start_point().time_since_epoch()); + } + } + + // rendering main loop + while (viewer->advanceToNextFrame() && (numFrames < 0 || (numFrames--) > 0)) + { + if (playEvents) + { + playEvents->dispatchFrameEvents(viewer->getEvents()); + } + + viewer->handleEvents(); + + viewer->update(); + + viewer->recordAndSubmit(); + + viewer->present(); + } + + if (recordEvents && !event_output_filename.empty()) + { + // shift the time of recorded events to relative to 0, so we can later add in any new viewer->start_point() during playback. + vsg::ShiftEventTime shiftTime(-viewer->start_point().time_since_epoch()); + recordEvents->events->accept(shiftTime); + + vsg::write(recordEvents->events, event_output_filename); + } + } + catch (const vsg::Exception& ve) + { + std::cerr << "[Exception] - " << ve.message << std::endl; + } + + return 0; +}