Commit 6b7a6bd0 authored by Sreekanth Arikatla's avatar Sreekanth Arikatla

Merge branch 'GUI_Feature' into 'master'

ENH: added GUI features

See merge request iMSTK/iMSTK!263
parents 6e07b009 1ef18f0e
#-----------------------------------------------------------------------------
# Add External Project
#-----------------------------------------------------------------------------
include(imstkAddExternalProject)
imstk_add_external_project( imgui
GIT_REPOSITORY https://github.com/ocornut/imgui.git
GIT_TAG v1.65
CONFIGURE_COMMAND ${SKIP_STEP_COMMAND}
BUILD_COMMAND ${SKIP_STEP_COMMAND}
INSTALL_COMMAND ${SKIP_STEP_COMMAND}
RELATIVE_INCLUDE_PATH ""
DEPENDENCIES ""
#VERBOSE
)
#-----------------------------------------------------------------------------
# Find path
#-----------------------------------------------------------------------------
find_path(imgui_INCLUDE_DIR
NAMES
imgui.h
)
mark_as_advanced(imgui_INCLUDE_DIR)
message(STATUS "imgui_INCLUDE_DIR : ${imgui_INCLUDE_DIR}")
#-----------------------------------------------------------------------------
# Find package
#-----------------------------------------------------------------------------
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(imgui
REQUIRED_VARS
imgui_INCLUDE_DIR)
#-----------------------------------------------------------------------------
# If missing target, create it
#-----------------------------------------------------------------------------
if(GLM_FOUND AND NOT TARGET imgui)
add_library(imgui INTERFACE IMPORTED)
endif()
......@@ -126,6 +126,7 @@ if(${PROJECT_NAME}_SUPERBUILD)
imstk_define_dependency(VTK)
imstk_define_dependency(VRPN)
imstk_define_dependency(LibNiFalcon)
imstk_define_dependency(imgui)
if(APPLE OR LINUX)
message("Warning: Building iMSTK WITHOUT audio support!")
......@@ -229,16 +230,16 @@ find_package( Assimp REQUIRED )
include_directories( ${Assimp_INCLUDE_DIRS} )
# glm
find_package(glm)
find_package( glm )
include_directories( ${glm_INCLUDE_DIR} )
if( ${PROJECT_NAME}_USE_Vulkan )
# glfw
find_package(glfw)
find_package( glfw )
include_directories( ${glfw_INCLUDE_DIR} )
# gli
find_package(gli)
find_package( gli )
include_directories( ${gli_INCLUDE_DIR} )
endif()
......@@ -256,6 +257,10 @@ include_directories( ${g3log_INCLUDE_DIR} )
find_package( Eigen 3.1.2 REQUIRED )
include_directories( ${Eigen_INCLUDE_DIR} )
# imgui
find_package( imgui REQUIRED )
include_directories( ${imgui_INCLUDE_DIR} )
# SCCD
find_package( SCCD REQUIRED )
include_directories( ${SCCD_INCLUDE_DIR} )
......@@ -337,6 +342,7 @@ add_subdirectory(Source/Scene)
add_subdirectory(Source/SimulationManager)
add_subdirectory(Source/Constraint)
add_subdirectory(Source/Materials)
add_subdirectory(Source/GUIOverlay)
#--------------------------------------------------------------------------
# Export Targets
......
###########################################################################
#
# Copyright (c) Kitware, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0.txt
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
###########################################################################
project(Example-GUIOverlay)
#-----------------------------------------------------------------------------
# Create executable
#-----------------------------------------------------------------------------
add_executable(${PROJECT_NAME} GUIOverlayExample.cpp)
#-----------------------------------------------------------------------------
# Link libraries to executable
#-----------------------------------------------------------------------------
target_link_libraries(${PROJECT_NAME} SimulationManager)
#-----------------------------------------------------------------------------
# Add shaders
#-----------------------------------------------------------------------------
include(imstkCopyAndCompileShaders)
CopyAndCompileShaders()
#-----------------------------------------------------------------------------
# Associate external data
#-----------------------------------------------------------------------------
list(APPEND FILE_LIST
decals/,REGEX:.*)
imstk_add_data(${PROJECT_NAME} ${FILE_LIST})
\ No newline at end of file
/*=========================================================================
Library: iMSTK
Copyright (c) Kitware, Inc. & Center for Modeling, Simulation,
& Imaging in Medicine, Rensselaer Polytechnic Institute.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0.txt
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
=========================================================================*/
#include "imstkSimulationManager.h"
#include "imstkAPIUtilities.h"
#include "imstkGUICanvas.h"
#include "imstkGUIWindow.h"
#include "imstkGUIShapes.h"
#include "imstkGUIText.h"
using namespace imstk;
///
/// \brief This example demonstrates the GUI feature.
/// NOTE: Requires enabling Vulkan rendering backend
///
int main()
{
// SDK and Scene
auto sdk = std::make_shared<SimulationManager>();
auto scene = sdk->createNewScene("GraphicalUserInterface");
auto canvas = sdk->getViewer()->getCanvas();
// Cube
auto cube = apiutils::createVisualAnalyticalSceneObject(Geometry::Type::Cube, scene, "cube", 0.5);
cube->getVisualGeometry()->translate(0, 0, 0);
cube->getVisualGeometry()->rotate(UP_VECTOR, PI_4);
// Plane
auto plane = apiutils::createVisualAnalyticalSceneObject(Geometry::Type::Plane, scene, "plane", 10);
// Window logic
auto window = std::make_shared<GUIOverlay::Window>("Test Window", "Test Window", 200.0f, 100.0f, 200.0f, 0.0f);
auto windowText = std::make_shared<GUIOverlay::Text>("Window Text", "Window Text", 0.0f, 0.0f);
window->addWidget(windowText);
auto circle = std::make_shared<GUIOverlay::Circle>("Circle", 100.0f, 100.0f, 25.0f, Color::Red, true);
auto circleOutline = std::make_shared<GUIOverlay::Circle>("CircleOutline", 100.0f, 100.0f, 25.0f, Color::Black, false);
// These two rectangles show that the ordering matters
auto underRectangle = std::make_shared<GUIOverlay::Rectangle>("UnderRectangle", 100.0f, 100.0f, 100.0f, 100.0f, Color(0.0f, 0.0f, 1.0f, 0.7f), true);
auto overRectangle = std::make_shared<GUIOverlay::Rectangle>("OverRectangle", 0.0f, 0.0f, 100.0f, 100.0f, Color(0.7f, 0.0f, 1.0f, 0.7f), true);
canvas->addWidget(underRectangle);
canvas->addWidget(circle);
canvas->addWidget(circleOutline);
canvas->addWidget(overRectangle);
canvas->addWidget(window);
StopWatch watch;
watch.start();
auto startTime = watch.getTimeElapsed();
auto lastTime = startTime;
// Update function
auto GUIUpdateFunction =
[&](InteractorStyle* style) -> bool
{
auto time = watch.getTimeElapsed();
float angle = time / 1000.0f;
circle->setPosition(std::sin(angle) * 50.0f + 100.0f, std::cos(angle) * 50.0f + 100.0f);
circle->setRadius(std::abs(std::sin(angle)) * 25.0f);
circleOutline->setPosition(std::sin(angle) * 50.0f + 100.0f, std::cos(angle) * 50.0f + 100.0f);
if (time - lastTime > 1000)
{
auto seconds = (int)((lastTime - startTime) / 1000);
windowText->setText("Elapsed Time: " + std::to_string(seconds)+ "s");
lastTime = time;
}
return false;
};
sdk->getViewer()->setOnTimerFunction(GUIUpdateFunction);
bool canvasVisible = true;
auto hideShowCanvasFunction =
[&](InteractorStyle* style) -> bool
{
if (canvasVisible)
{
canvas->hide();
}
else
{
canvas->show();
}
canvasVisible = !canvasVisible;
return true;
};
sdk->getViewer()->setOnCharFunction('c', hideShowCanvasFunction);
// Position camera
auto cam = scene->getCamera();
cam->setPosition(0, 3, 6);
cam->setFocalPoint(0, 0, 0);
// Light
auto light = std::make_shared<DirectionalLight>("Light");
light->setIntensity(7);
light->setColor(Color(1.0, 0.95, 0.8));
light->setFocalPoint(Vec3d(-1, -1, 0));
scene->addLight(light);
// Run
sdk->setActiveScene(scene);
sdk->startSimulation(SimulationStatus::PAUSED);
return 0;
}
......@@ -91,7 +91,6 @@ int main()
object->setVisualGeometry(mesh);
scene->addSceneObject(object);
}
}
int frame = 0;
......@@ -102,41 +101,41 @@ int main()
int startupFrame = -1;
sdk->getViewer()->setOnTimerFunction([&](InteractorStyle* c) -> bool
{
if (dynamicMesh)
{
if (dynamicMesh)
for (int j = 0; j < numMeshes; j++)
{
for (int j = 0; j < numMeshes; j++)
{
auto object = scene->getSceneObject(std::string("mesh") + std::to_string(j));
auto mesh = std::dynamic_pointer_cast<LineMesh>(object->getVisualGeometry());
mesh->setVertexPositions(vertices);
mesh->setLinesVertices(lines);
}
}
auto object = scene->getSceneObject(std::string("mesh") + std::to_string(j));
auto mesh = std::dynamic_pointer_cast<LineMesh>(object->getVisualGeometry());
if (scene->getSceneObject("mesh" + std::to_string(numMeshes - 1)) && startupFrame == -1)
{
startupFrame = frame;
LOG(INFO) << "Start time: " << startWatch->getTimeElapsed();
}
if (frame == startupFrame + 100)
{
startFrame = frame;
watch->start();
watch->reset();
LOG(INFO) << "Starting time";
}
else if (frame == startFrame + 100 && startFrame != -1)
{
endTime = watch->getTimeElapsed();
LOG(INFO) << "Total time: " << endTime;
LOG(INFO) << "Frame time: " << endTime / (frame - startFrame);
mesh->setVertexPositions(vertices);
mesh->setLinesVertices(lines);
}
frame++;
return true;
}
);
if (scene->getSceneObject("mesh" + std::to_string(numMeshes - 1)) && startupFrame == -1)
{
startupFrame = frame;
LOG(INFO) << "Start time: " << startWatch->getTimeElapsed();
}
if (frame == startupFrame + 100)
{
startFrame = frame;
watch->start();
watch->reset();
LOG(INFO) << "Starting time";
}
else if (frame == startFrame + 100 && startFrame != -1)
{
endTime = watch->getTimeElapsed();
LOG(INFO) << "Total time: " << endTime;
LOG(INFO) << "Frame time: " << endTime / (frame - startFrame);
}
frame++;
return true;
}
);
// Start simulation
startWatch->start();
......
#-----------------------------------------------------------------------------
# Create target
#-----------------------------------------------------------------------------
include(imstkAddLibrary)
file (GLOB_RECURSE GUI_h_files "${CMAKE_CURRENT_SOURCE_DIR}/imstk*.h")
file (GLOB_RECURSE GUI_cpp_files "${CMAKE_CURRENT_SOURCE_DIR}/imstk*.cpp")
if( iMSTK_USE_VULKAN )
set (IMPLEMENTATION_H_FILES
${imgui_INCLUDE_DIR}/examples/imgui_impl_vulkan.h
${imgui_INCLUDE_DIR}/examples/imgui_impl_glfw.h)
set (IMPLENTATION_CPP_FILES
${imgui_INCLUDE_DIR}/examples/imgui_impl_vulkan.cpp
${imgui_INCLUDE_DIR}/examples/imgui_impl_glfw.cpp)
endif()
imstk_add_library( GUIOverlay
H_FILES
${imgui_INCLUDE_DIR}/imconfig.h
${imgui_INCLUDE_DIR}/imgui.h
${imgui_INCLUDE_DIR}/imgui_internal.h
${imgui_INCLUDE_DIR}/imstb_rectpack.h
${imgui_INCLUDE_DIR}/imstb_textedit.h
${imgui_INCLUDE_DIR}/imstb_truetype.h
${IMPLEMENTATION_H_FILES}
${GUI_h_files}
CPP_FILES
${imgui_INCLUDE_DIR}/imgui.cpp
${imgui_INCLUDE_DIR}/imgui_demo.cpp
${imgui_INCLUDE_DIR}/imgui_draw.cpp
${imgui_INCLUDE_DIR}/imgui_widgets.cpp
${IMPLEMENTATION_CPP_FILES}
${GUI_cpp_files}
DEPENDS
Core
imgui
)
#-----------------------------------------------------------------------------
# Testing
#-----------------------------------------------------------------------------
if( iMSTK_BUILD_TESTING )
add_subdirectory( Testing )
endif()
/*=========================================================================
Library: iMSTK
Copyright (c) Kitware, Inc. & Center for Modeling, Simulation,
& Imaging in Medicine, Rensselaer Polytechnic Institute.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0.txt
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
=========================================================================*/
#include "imstkGUICanvas.h"
namespace imstk
{
namespace GUIOverlay
{
Canvas::~Canvas()
{
this->clear();
}
void
Canvas::clear()
{
m_widgets.clear();
}
void
Canvas::render()
{
if (!m_visible)
{
return;
}
for (int i = 0; i < m_widgets.getSize(); i++)
{
auto type = m_widgets[i]->getType();
if (!m_widgets[i]->isVisible())
{
continue;
}
bool needsWindow = (type == Widget::Type::None);
if (needsWindow)
{
ImGui::SetNextWindowPos(ImVec2(0,0));
ImGui::SetNextWindowBgAlpha(0.0);
ImGui::Begin("", nullptr, ImGuiWindowFlags_NoInputs
| ImGuiWindowFlags_NoTitleBar
| ImGuiWindowFlags_NoResize);
}
m_widgets[i]->render(needsWindow);
if (needsWindow)
{
ImGui::End();
}
}
}
void
Canvas::addWidget(std::shared_ptr<Widget> widget)
{
m_widgets.addWidget(widget);
}
void
Canvas::removeWidget(std::string name)
{
m_widgets.removeWidget(name);
}
std::shared_ptr<Widget>
Canvas::getWidget(std::string name)
{
return m_widgets.getWidget(name);
}
void
Canvas::show()
{
m_visible = true;
}
void
Canvas::hide()
{
m_visible = false;
}
} // GUI
} // imstk
/*=========================================================================
Library: iMSTK
Copyright (c) Kitware, Inc. & Center for Modeling, Simulation,
& Imaging in Medicine, Rensselaer Polytechnic Institute.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0.txt
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
=========================================================================*/
#ifndef imstkCanvas_h
#define imstkCanvas_h
#include "imgui.h"
#include <map>
#include <string>
#include <memory>
#include "imstkGUIWidget.h"
#include "imstkGUIWidgetList.h"
namespace imstk
{
namespace GUIOverlay
{
///
/// \class Canvas
///
/// \brief Base class for GUI
///
class Canvas
{
public:
///
/// \brief Protected constructor
///
Canvas() {};
///
/// \brief Destructor
///
~Canvas();
///
/// \brief Clears all the widgets
///
void clear();
///
/// \brief Render the widgets
///
void render();
///
/// \brief Add widget
///
void addWidget(std::shared_ptr<Widget> widget);
///
/// \brief Remove widget
///
void removeWidget(std::string name);
///
/// \brief Get widget
///
std::shared_ptr<Widget> getWidget(std::string name);
///
/// \brief Show canvas
///
void show();
///
/// \brief Hide canvas
///
void hide();
protected:
WidgetList m_widgets;
bool m_visible = true;
};
} // GUI
} // imstk
#endif // ifndef imstkCanvas_h
/*=========================================================================
Library: iMSTK
Copyright (c) Kitware, Inc. & Center for Modeling, Simulation,
& Imaging in Medicine, Rensselaer Polytechnic Institute.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0.txt
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
=========================================================================*/
#ifndef imstkShapes_h
#define imstkShapes_h
#include "imgui.h"
#include <string>
#include "imstkGUIWidget.h"
#include "imstkColor.h"
#include "imstkGUIUtilities.h"
namespace imstk
{
namespace GUIOverlay
{
///
/// \class Shape
///
/// \brief Abstract shape class
///
class Shape : public Widget
{
protected:
///
/// \brief Constructor
///
Shape(std::string name, float x, float y, Color color, bool filled)
: Widget(name, x, y)
{
m_color = color;
m_filled = filled;
m_type = Widget::Type::Shape;
}
Shape() = delete;
Color m_color;
bool m_filled;
};
///
/// \class Circle
///
/// \brief Circle widget
///
class Circle : public Shape
{
public:
///
/// \brief Protected constructor
///
Circle(std::string name,
float x,
float y,
float radius,
Color color,
bool filled = false)
: Shape(name, x, y, color, filled)
{
m_radius = radius;
}
///
/// \brief Render
///
virtual void render(const bool inWindow)
{
ImDrawList * drawList;
if (inWindow)
{
drawList = ImGui::GetWindowDrawList();
}
else
{
drawList = ImGui::GetOverlayDrawList();
}
if (m_filled)
{
drawList->AddCircleFilled(ImVec2(m_position[0], m_position[1]),
m_radius,
GUIOverlay::Utilities::convertToGUIColor(m_color),
24);
}
else
{
drawList->AddCircle(ImVec2(m_position[0], m_position[1]),
m_radius,
GUIOverlay::Utilities::convertToGUIColor(m_color),
24);
}
}
///
/// \brief Set radius
///
void setRadius(const float radius)
{
m_radius = radius;
}
///
/// \brief Get radius
///
const float getRadius()