Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Info window #21

Merged
merged 4 commits into from
Aug 20, 2023
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
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ jobs:
uses: actions/checkout@v3
with:
submodules: recursive
- name: Configure git checkout as safe directory to allow dubious permission-setup
run: git config --system --add safe.directory $GITHUB_WORKSPACE
- name: Install depdendencies
run: |
. /opt/ros/$ROS_DISTRO/setup.sh
Expand Down
8 changes: 6 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ set(CMAKE_CXX_STANDARD 20)
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)

# embedding of latest commit hash within the executable
include(cmake/CheckGit.cmake)
CheckGitSetup()

# Download imgui
include(FetchContent)
FetchContent_Declare(imgui
Expand Down Expand Up @@ -40,14 +44,14 @@ add_executable(${PROJECT_NAME} src/rig_reconfigure.cpp src/service_wrapper.cpp s
#target_link_options(${PROJECT_NAME} PRIVATE -fsanitize=thread)

target_include_directories(${PROJECT_NAME} PRIVATE include external/imspinner external/lodepng)
target_link_libraries(${PROJECT_NAME} imgui)
target_link_libraries(${PROJECT_NAME} imgui git_version)
ament_target_dependencies(${PROJECT_NAME} rclcpp)

install(TARGETS ${PROJECT_NAME}
DESTINATION lib/${PROJECT_NAME}
)

install(FILES resource/rig_reconfigure.png
install(FILES resource/rig_reconfigure.png resource/rig_reconfigure_text.png
DESTINATION share/${PROJECT_NAME}/resource
)

Expand Down
89 changes: 89 additions & 0 deletions cmake/CheckGit.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# adapted from https://gitlab.com/jhamberg/cmake-examples/-/blob/master/cmake/CheckGit.cmake

set(CURRENT_LIST_DIR ${CMAKE_CURRENT_LIST_DIR})
if (NOT DEFINED pre_configure_inc_dir)
set(pre_configure_inc_dir ${CMAKE_SOURCE_DIR}/include)
endif ()

if (NOT DEFINED pre_configure_dir)
set(pre_configure_dir ${CMAKE_SOURCE_DIR}/src)
endif ()

if (NOT DEFINED post_configure_dir)
set(post_configure_dir ${CMAKE_BINARY_DIR}/generated)
endif ()

set(pre_configure_file ${pre_configure_dir}/git_version.cpp.in)
set(post_configure_file ${post_configure_dir}/git_version.cpp)

function(CheckGitWrite git_hash)
file(WRITE ${CMAKE_BINARY_DIR}/git-state.txt ${git_hash})
endfunction()

function(CheckGitRead git_hash)
if (EXISTS ${CMAKE_BINARY_DIR}/git-state.txt)
file(STRINGS ${CMAKE_BINARY_DIR}/git-state.txt CONTENT)
LIST(GET CONTENT 0 var)

set(${git_hash} ${var} PARENT_SCOPE)
endif ()
endfunction()

function(CheckGitVersion)
# Get the latest abbreviated commit hash of the working branch
execute_process(
COMMAND git log -1 --format=%h
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
OUTPUT_VARIABLE GIT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE
)

CheckGitRead(GIT_HASH_CACHE)
if (NOT EXISTS ${post_configure_dir})
file(MAKE_DIRECTORY ${post_configure_dir})
endif ()

if (NOT EXISTS ${post_configure_dir}/git_version.hpp)
file(COPY ${pre_configure_inc_dir}/git_version.hpp DESTINATION ${post_configure_dir})
endif()

if (NOT DEFINED GIT_HASH_CACHE)
set(GIT_HASH_CACHE "INVALID")
endif ()

# Only update the git_version.cpp if the hash has changed. This will
# prevent us from rebuilding the project more than we need to.
if (NOT ${GIT_HASH} STREQUAL ${GIT_HASH_CACHE} OR NOT EXISTS ${post_configure_file})
# Set che GIT_HASH_CACHE variable the next build won't have
# to regenerate the source file.
CheckGitWrite(${GIT_HASH})

configure_file(${pre_configure_file} ${post_configure_file} @ONLY)
endif ()

endfunction()

function(CheckGitSetup)

add_custom_target(AlwaysCheckGit COMMAND ${CMAKE_COMMAND}
-DRUN_CHECK_GIT_VERSION=1
-Dpre_configure_inc_dir=${pre_configure_inc_dir}
-Dpre_configure_dir=${pre_configure_dir}
-Dpost_configure_file=${post_configure_dir}
-DGIT_HASH_CACHE=${GIT_HASH_CACHE}
-P ${CURRENT_LIST_DIR}/CheckGit.cmake
BYPRODUCTS ${post_configure_file}
)

add_library(git_version ${CMAKE_BINARY_DIR}/generated/git_version.cpp)
target_include_directories(git_version PUBLIC ${CMAKE_BINARY_DIR}/generated)
add_dependencies(git_version AlwaysCheckGit)

CheckGitVersion()
endfunction()

# This is used to run this function from an external cmake process.
if (RUN_CHECK_GIT_VERSION)
CheckGitVersion()
endif ()

15 changes: 15 additions & 0 deletions include/git_version.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* @file git_version.hpp
* @author Dominik Authaler
* @date 12.08.2023
*
* Utility file for including the hash of the latest commit within the executable.
* Based on https://jonathanhamberg.com/post/cmake-embedding-git-hash/.
*/

#ifndef RIG_RECONFIGURE_GIT_VERSION_HPP
#define RIG_RECONFIGURE_GIT_VERSION_HPP

extern const char *gitHash;

#endif //RIG_RECONFIGURE_GIT_VERSION_HPP
Binary file added resource/rig_reconfigure_text.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions src/git_version.cpp.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* @file git_version.cpp.in
* @author Dominik Authaler
* @date 12.08.2023
*
* Utility file for including the hash of the latest commit within the executable.
* Based on https://jonathanhamberg.com/post/cmake-embedding-git-hash/.
*
* Note that this file is preprocessed by cmake before being forwarded to the compiler (this allows replacing
* the variable placeholder with the corresponding commit hash).
*/

#include "git_version.hpp"

const char *gitHash = "@GIT_HASH@";
147 changes: 118 additions & 29 deletions src/rig_reconfigure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
#include "parameter_tree.hpp"
#include "service_wrapper.hpp"

#include "git_version.hpp"

using namespace std::chrono_literals;

/// Minimum width specified for text input fields.
Expand Down Expand Up @@ -56,6 +58,10 @@ static void highlightedText(const std::string &text, std::size_t start, std::siz
static bool highlightedSelectableText(const std::string &text, std::size_t start, std::size_t end,
const ImVec4 &highlightColor = FILTER_HIGHLIGHTING_COLOR);

static std::filesystem::path findResourcePath(const std::string &execPath);
static void loadWindowIcon(GLFWwindow *windowPtr, const std::filesystem::path &resourcePath);
static void renderInfoWindow(bool *showInfoWindow, const std::filesystem::path &resourcePath);

int main(int argc, char *argv[]) {
rclcpp::init(argc, argv);

Expand Down Expand Up @@ -87,36 +93,9 @@ int main(int argc, char *argv[]) {
glfwMakeContextCurrent(window);
glfwSwapInterval(1); // Enable vsync

// load window icon
auto logoPath = std::filesystem::path(argv[0]).parent_path().append("resource/rig_reconfigure.png");
const auto resourcePath = findResourcePath(argv[0]);

try {
// Try getting package share dir via ament, and use that if it succeeds.
logoPath = ament_index_cpp::get_package_share_directory("rig_reconfigure");
logoPath.append("resource/rig_reconfigure.png");
} catch (ament_index_cpp::PackageNotFoundError &e) {
std::cerr << "Warning: Error while looking for package share directory to find the app icon: " << e.what()
<< "\n";
}

std::vector<unsigned char> iconData;
unsigned int width;
unsigned int height;

unsigned error = lodepng::decode(iconData, width, height, logoPath.string());

if (!error) {
GLFWimage icon;

icon.width = static_cast<int>(width);
icon.height = static_cast<int>(height);
icon.pixels = iconData.data();

glfwSetWindowIcon(window, 1, &icon);
} else {
std::cerr << "Unable to load window icon (decoder error " << error << " - " << lodepng_error_text(error) << ")"
<< std::endl;
}
loadWindowIcon(window, resourcePath);

// Setup Dear ImGui context
IMGUI_CHECKVERSION();
Expand Down Expand Up @@ -152,6 +131,7 @@ int main(int argc, char *argv[]) {
serviceWrapper.pushRequest(std::make_shared<Request>(Request::Type::QUERY_NODE_NAMES));

bool shouldResetLayout = true;
bool showInfo = false;

// Main loop
while (!glfwWindowShouldClose(window)) {
Expand Down Expand Up @@ -304,9 +284,16 @@ int main(int argc, char *argv[]) {
ImGui::EndMenu();
}

if (ImGui::BeginMenu("Info")) {
ImGui::MenuItem("Show info", nullptr, &showInfo);
ImGui::EndMenu();
}

ImGui::EndMainMenuBar();
}

renderInfoWindow(&showInfo, resourcePath);

if (ImGui::DockBuilderGetNode(dockspace_id) == NULL || shouldResetLayout) {
shouldResetLayout = false;
ImGui::DockBuilderRemoveNode(dockspace_id); // Clear out existing layout
Expand Down Expand Up @@ -652,3 +639,105 @@ bool highlightedSelectableText(const std::string &text, std::size_t start, std::

return selected;
}

std::filesystem::path findResourcePath(const std::string &execPath) {
auto resourcePath = std::filesystem::path(execPath).parent_path().append("resource");

try {
// Try getting package share dir via ament, and use that if it succeeds.
resourcePath = ament_index_cpp::get_package_share_directory("rig_reconfigure");
resourcePath.append("resource");
} catch (ament_index_cpp::PackageNotFoundError &e) {
std::cerr << "Warning: Error while looking for package share directory: " << e.what()
<< "\n";
}

return resourcePath;
}

void loadWindowIcon(GLFWwindow *windowPtr, const std::filesystem::path &resourcePath) {
const auto logoPath = resourcePath / "rig_reconfigure.png";

std::vector<unsigned char> iconData;
unsigned int width;
unsigned int height;

unsigned int error = lodepng::decode(iconData, width, height, logoPath.string());

if (error == 0) {
GLFWimage icon;

icon.width = static_cast<int>(width);
icon.height = static_cast<int>(height);
icon.pixels = iconData.data();

glfwSetWindowIcon(windowPtr, 1, &icon);
} else {
std::cerr << "Unable to load window icon (decoder error " << error << " - " << lodepng_error_text(error) << ")"
<< std::endl;
}
}

void renderInfoWindow(bool *showInfoWindow, const std::filesystem::path &resourcePath) {
// load the logo with text only once
static GLuint imageTexture;
static unsigned int width = 0;
static unsigned int height = 0;
static bool imageLoaded = false;

if (!imageLoaded) {
auto logoPath = resourcePath / "rig_reconfigure_text.png";

std::vector<unsigned char> imageData;

unsigned int error = lodepng::decode(imageData, width, height, logoPath.string());

if (error == 0) {
glGenTextures(1, &imageTexture);
glBindTexture(GL_TEXTURE_2D, imageTexture);

// Setup filtering parameters for display
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

#if defined(GL_UNPACK_ROW_LENGTH) && !defined(__EMSCRIPTEN__)
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
#endif
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData.data());
}

imageLoaded = true;
}

if (*showInfoWindow) {
ImGui::Begin("Info", showInfoWindow, ImGuiWindowFlags_AlwaysAutoResize);

if (width != 0 && height != 0) {
ImGui::Image((void*)(intptr_t)imageTexture,
ImVec2(static_cast<float>(width), static_cast<float>(height)));
} else {
ImGui::Text("rig-reconfigure");
}

ImGui::Text(" ");
ImGui::Text("Version: %s", gitHash);
ImGui::Text(" ");

ImGui::Text("Created in winter 2022 by");
ImGui::Text(" ");
ImGui::Text("Dominik Authaler");
ImGui::Text("Jonas Otto");
ImGui::Text(" ");
ImGui::Text("Sources available at https://github.com/teamspatzenhirn/rig_reconfigure");
ImGui::Text("under MIT license. Pull requests extending the functionality / fixing");
ImGui::Text("bugs are always welcome!");
ImGui::Text(" ");
ImGui::Text("This tool has been created while the authors have been part of Team Spatzenhirn,");
ImGui::Text("a student team at Ulm University. If you like rig-reconfigure, please consider");
ImGui::Text("supporting the team (e.g. by joining if you're studying at Ulm University).");

ImGui::End();
}
}