From 71ae01b12cd6fb9f91ffcbb1897df7a1e0af4a00 Mon Sep 17 00:00:00 2001 From: Sergej Geringer Date: Fri, 18 Feb 2022 13:28:11 +0100 Subject: [PATCH] add Exotic Inputs Service: injecting input device controls (e.g. gamepads) into graph modules (e.g. View 3D) --- frontend/main/src/main.cpp | 6 + frontend/services/CMakeLists.txt | 3 + .../exotic_inputs/ExoticInputs_Service.cpp | 138 ++++++++++++++++++ .../exotic_inputs/ExoticInputs_Service.hpp | 59 ++++++++ 4 files changed, 206 insertions(+) create mode 100644 frontend/services/exotic_inputs/ExoticInputs_Service.cpp create mode 100644 frontend/services/exotic_inputs/ExoticInputs_Service.hpp diff --git a/frontend/main/src/main.cpp b/frontend/main/src/main.cpp index 7f2eaba399..f747a7a52b 100644 --- a/frontend/main/src/main.cpp +++ b/frontend/main/src/main.cpp @@ -7,6 +7,7 @@ #include "CLIConfigParsing.h" #include "CUDA_Service.hpp" #include "Command_Service.hpp" +#include "ExoticInputs_Service.hpp" #include "FrameStatistics_Service.hpp" #include "FrontendServiceCollection.hpp" #include "GUI_Service.hpp" @@ -100,6 +101,10 @@ int main(const int argc, const char** argv) { openglConfig.forceWindowSize = config.force_window_size; gl_service.setPriority(2); + megamol::frontend::ExoticInputs_Service exoticinputs_service; + megamol::frontend::ExoticInputs_Service::Config exoticinputsConfig; + exoticinputs_service.setPriority(gl_service.getPriority() + 1); // depends on gamepad updates from GLFW + megamol::frontend::GUI_Service gui_service; megamol::frontend::GUI_Service::Config guiConfig; guiConfig.backend = (with_gl) ? (megamol::gui::GUIRenderBackend::OPEN_GL) : (megamol::gui::GUIRenderBackend::CPU); @@ -196,6 +201,7 @@ int main(const int argc, const char** argv) { if (with_gl) { services.add(gl_service, &openglConfig); } + services.add(exoticinputs_service, &exoticinputsConfig); services.add(gui_service, &guiConfig); services.add(lua_service_wrapper, &luaConfig); services.add(screenshot_service, &screenshotConfig); diff --git a/frontend/services/CMakeLists.txt b/frontend/services/CMakeLists.txt index 3d314937e1..db4d5fd309 100644 --- a/frontend/services/CMakeLists.txt +++ b/frontend/services/CMakeLists.txt @@ -32,6 +32,7 @@ file(GLOB_RECURSE header_files RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "remote_service/*.hpp" "profiling_service/*.hpp" "vr_service/*.hpp" + "exotic_inputs/*.hpp" # "service_template/*.hpp" ) @@ -48,6 +49,7 @@ file(GLOB_RECURSE source_files RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "remote_service/*.cpp" "profiling_service/*.cpp" "vr_service/*.cpp" + "exotic_inputs/*.cpp" # "service_template/*.cpp" ) @@ -109,6 +111,7 @@ target_include_directories(${PROJECT_NAME} PUBLIC "gui/3rd" "gui/src" "vr_service" + "exotic_inputs" # "service_template" ) diff --git a/frontend/services/exotic_inputs/ExoticInputs_Service.cpp b/frontend/services/exotic_inputs/ExoticInputs_Service.cpp new file mode 100644 index 0000000000..364be09aa3 --- /dev/null +++ b/frontend/services/exotic_inputs/ExoticInputs_Service.cpp @@ -0,0 +1,138 @@ +/* + * ExoticInputs_Service.cpp + * + * Copyright (C) 2022 by MegaMol Team + * Alle Rechte vorbehalten. + */ + +#include "ExoticInputs_Service.hpp" + +#include "GamepadState.h" + +#include "GUIRegisterWindow.h" // register UI window for remote control +#include "imgui_stdlib.h" + +// local logging wrapper for your convenience until central MegaMol logger established +#include "mmcore/utility/log/Log.h" + +#include + +static const std::string service_name = "ExoticInputs_Service: "; +static void log(std::string const& text) { + const std::string msg = service_name + text; + megamol::core::utility::log::Log::DefaultLog.WriteInfo(msg.c_str()); +} + +static void log_error(std::string const& text) { + const std::string msg = service_name + text; + megamol::core::utility::log::Log::DefaultLog.WriteError(msg.c_str()); +} + +static void log_warning(std::string const& text) { + const std::string msg = service_name + text; + megamol::core::utility::log::Log::DefaultLog.WriteWarn(msg.c_str()); +} + + +namespace megamol { +namespace frontend { + +ExoticInputs_Service::ExoticInputs_Service() { + // init members to default states +} + +ExoticInputs_Service::~ExoticInputs_Service() { + // clean up raw pointers you allocated with new, which is bad practice and nobody does +} + +bool ExoticInputs_Service::init(void* configPtr) { + if (configPtr == nullptr) + return false; + + return init(*static_cast(configPtr)); +} + +bool ExoticInputs_Service::init(const Config& config) { + // initialize your service and its provided resources using config parameters + // for now, you dont need to worry about your service beeing initialized or closed multiple times + // init() and close() only get called once in the lifetime of each service object + // but maybe more instances of your service will get created? this may be relevant for central resources you manage (like libraries, network connections). + + m_providedResourceReferences = {}; + + m_requestedResourcesNames = { + "optional", + "optional", + }; + + log("initialized successfully"); + return true; +} + +void ExoticInputs_Service::close() {} + +std::vector& ExoticInputs_Service::getProvidedResources() { + return m_providedResourceReferences; +} + +const std::vector ExoticInputs_Service::getRequestedResourceNames() const { + return m_requestedResourcesNames; +} + +void ExoticInputs_Service::setRequestedResources(std::vector resources) { + m_requestedResourceReferences = resources; + + gamepad_window(); +} + +void ExoticInputs_Service::updateProvidedResources() {} + +void ExoticInputs_Service::digestChangedRequestedResources() {} + +void ExoticInputs_Service::resetProvidedResources() {} + +void ExoticInputs_Service::preGraphRender() {} + +void ExoticInputs_Service::postGraphRender() {} + +void ExoticInputs_Service::gamepad_window() const { + auto maybe_gamepad_resource = + m_requestedResourceReferences[0].getOptionalResource(); + auto maybe_window_resource = + m_requestedResourceReferences[1].getOptionalResource(); + + if (maybe_gamepad_resource.has_value() && maybe_window_resource.has_value()) { + // draw window showing gamepad stats + auto& gui_window = maybe_window_resource.value().get(); + auto& connected_gamepads = maybe_gamepad_resource.value().get(); + + gui_window.register_window("GLFW Gamepads ", [&](megamol::gui::AbstractWindow::BasicConfig& window_config) { + for (auto& gamepad : connected_gamepads.gamepads) { + window_config.flags = ImGuiWindowFlags_AlwaysAutoResize; + + ImGui::Text(gamepad.get().name.c_str()); + + int i = 0; + for (auto axis : gamepad.get().axes) { + ImGui::Text(("Axis " + std::to_string(i) + ": " + std::to_string(axis)).c_str()); + ImGui::SameLine(); + i++; + } + ImGui::NewLine(); + + i = 0; + for (auto button : gamepad.get().buttons) { + ImGui::Text(("Button " + std::to_string(i) + ": " + std::to_string(button)).c_str()); + ImGui::SameLine(); + i++; + } + ImGui::NewLine(); + ImGui::Separator(); + } + }); + } +} + + +} // namespace frontend +} // namespace megamol diff --git a/frontend/services/exotic_inputs/ExoticInputs_Service.hpp b/frontend/services/exotic_inputs/ExoticInputs_Service.hpp new file mode 100644 index 0000000000..6858f305dd --- /dev/null +++ b/frontend/services/exotic_inputs/ExoticInputs_Service.hpp @@ -0,0 +1,59 @@ +/* + * ExoticInputs_Service.hpp + * + * Copyright (C) 2022 by MegaMol Team + * Alle Rechte vorbehalten. + */ + +#pragma once + +#include "AbstractFrontendService.hpp" + +namespace megamol { +namespace frontend { + +// The Exotic Inputs Service is supposed to implement the injection of raw input device state (e.g.gamepads via GLFW) +// into the MegaMol Graph by matching input devices to graph modules which can be controlled in some usefull way using that device +// So this ervice looks up present input device resources, or manages input devices on his own, and knows how to connect them to graph modules +// For example, gamepads may be used to control View3D Cameras or positions of Clipping Planes in space +class ExoticInputs_Service final : public AbstractFrontendService { +public: + struct Config {}; + + std::string serviceName() const override { + return "ExoticInputs_Service"; + } + + ExoticInputs_Service(); + ~ExoticInputs_Service(); + + bool init(const Config& config); + bool init(void* configPtr) override; + void close() override; + + std::vector& getProvidedResources() override; + const std::vector getRequestedResourceNames() const override; + void setRequestedResources(std::vector resources) override; + + void updateProvidedResources() override; + void digestChangedRequestedResources() override; + void resetProvidedResources() override; + void preGraphRender() override; + void postGraphRender() override; + + // from AbstractFrontendService + // int setPriority(const int p) // priority initially 0 + // int getPriority() const; + // bool shouldShutdown() const; // shutdown initially false + // void setShutdown(const bool s = true); + +private: + std::vector m_providedResourceReferences; + std::vector m_requestedResourcesNames; + std::vector m_requestedResourceReferences; + + void gamepad_window() const; +}; + +} // namespace frontend +} // namespace megamol