From 5457946fca917829adbc3dd1c77dbebf7d14d288 Mon Sep 17 00:00:00 2001 From: Fabrice CARUSO Date: Thu, 26 May 2022 01:54:15 +0200 Subject: [PATCH] Gun refactorings + preliminary aim cursor --- CMakeLists.txt | 7 +- es-app/src/main.cpp | 12 +- es-core/CMakeLists.txt | 2 + es-core/src/GunManager.cpp | 244 +++++++++++++++++++++++++++++++++++ es-core/src/GunManager.h | 75 +++++++++++ es-core/src/InputManager.cpp | 193 ++------------------------- es-core/src/InputManager.h | 36 ++---- es-core/src/Window.cpp | 45 +++++-- es-core/src/Window.h | 2 + resources/gun.png | Bin 0 -> 4648 bytes 10 files changed, 390 insertions(+), 226 deletions(-) create mode 100644 es-core/src/GunManager.cpp create mode 100644 es-core/src/GunManager.h create mode 100644 resources/gun.png diff --git a/CMakeLists.txt b/CMakeLists.txt index d30412afe..b55cc041b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -304,7 +304,6 @@ set(COMMON_LIBRARIES ${FREETYPE_LIBRARIES} ${FreeImage_LIBRARIES} ${SDL2_LIBRARY} - ${UDEV_LIBRARY} # batocera / background musics ${SDLMIXER_LIBRARY} # batocera / customisations @@ -316,6 +315,12 @@ set(COMMON_LIBRARIES libcheevos ) +if(UDEV_FOUND) + LIST(APPEND COMMON_LIBRARIES + ${UDEV_LIBRARY} + ) +endif() + if(ENABLE_PULSE) LIST(APPEND COMMON_LIBRARIES ${PULSEAUDIO_LIBRARY} diff --git a/es-app/src/main.cpp b/es-app/src/main.cpp index 206251f2a..2e3eb0568 100644 --- a/es-app/src/main.cpp +++ b/es-app/src/main.cpp @@ -668,7 +668,7 @@ int main(int argc, char* argv[]) while(SDL_PollEvent(&event)); // check guns - InputManager::getInstance()->parseGuns(&window); + InputManager::getInstance()->updateGuns(&window); // triggered if exiting from SDL_WaitEvent due to event if (ps_standby) @@ -685,17 +685,11 @@ int main(int argc, char* argv[]) // ps_time = SDL_GetTicks(); // check guns - InputManager::getInstance()->parseGuns(&window); + InputManager::getInstance()->updateGuns(&window); } - // just to test - float perx, pery; - for (auto iter = InputManager::getInstance()->getGuns().begin(); iter != InputManager::getInstance()->getGuns().end(); iter++) { - InputManager::getInstance()->getGunPosition(iter->second, perx, pery); - printf("gun %i : %.2f %.2f\n", iter->first, perx, pery); - } - if(window.isSleeping()) + if (window.isSleeping()) { lastTime = SDL_GetTicks(); SDL_Delay(1); // this doesn't need to be accurate, we're just giving up our CPU time until something wakes us up diff --git a/es-core/CMakeLists.txt b/es-core/CMakeLists.txt index d4bde71c5..941af27a2 100644 --- a/es-core/CMakeLists.txt +++ b/es-core/CMakeLists.txt @@ -10,6 +10,7 @@ set(CORE_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/src/ImageIO.h ${CMAKE_CURRENT_SOURCE_DIR}/src/InputConfig.h ${CMAKE_CURRENT_SOURCE_DIR}/src/InputManager.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/GunManager.h ${CMAKE_CURRENT_SOURCE_DIR}/src/Log.h ${CMAKE_CURRENT_SOURCE_DIR}/src/MameNames.h ${CMAKE_CURRENT_SOURCE_DIR}/src/gettext.h # batocera @@ -126,6 +127,7 @@ set(CORE_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/ImageIO.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/InputConfig.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/InputManager.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/GunManager.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Log.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/MameNames.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/LocaleES.cpp # batocera diff --git a/es-core/src/GunManager.cpp b/es-core/src/GunManager.cpp new file mode 100644 index 000000000..2ab9ae59b --- /dev/null +++ b/es-core/src/GunManager.cpp @@ -0,0 +1,244 @@ +#include "GunManager.h" +#include "Log.h" +#include "platform.h" +#include "Window.h" +#include +#include +#include +#include +#include "utils/StringUtil.h" +#include "LocaleES.h" + +#ifdef HAVE_UDEV +#include +#include +#include +#include +#include +#define test_bit(array, bit) (array[bit/8] & (1<<(bit%8))) +#endif + +#if WIN32 +#include +#endif + +GunManager::GunManager() +{ +#ifdef HAVE_UDEV + udev = udev_new(); + if (udev != NULL) + { + udev_monitor = udev_monitor_new_from_netlink(udev, "udev"); + if (udev_monitor) + { + udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "input", NULL); + udev_monitor_enable_receiving(udev_monitor); + } + } + udev_initial_gunsList(); +#endif +} + +GunManager::~GunManager() +{ +#ifdef HAVE_UDEV + if (udev != NULL) + { + // close guns + for (auto gun : mGuns) + { + udev_removeGun(gun->dev, NULL); + delete gun; + } + + mGuns.clear(); + + if (udev_monitor) + udev_monitor_unref(udev_monitor); + + udev_unref(udev); + } +#endif +} + +void GunManager::updateGuns(Window* window) +{ +#ifdef HAVE_UDEV + const char* val_gun; + const char* action; + + while (udev_monitor && udev_input_poll_hotplug_available(udev_monitor)) + { + struct udev_device *dev = udev_monitor_receive_device(udev_monitor); + bool dev_handled = false; + + if (dev != NULL) + { + val_gun = udev_device_get_property_value(dev, "ID_INPUT_GUN"); // ID_INPUT_GUN and ID_INPUT_MOUSE for some tests + action = udev_device_get_action(dev); + + if (val_gun != NULL && strncmp(val_gun, "1", 1) == 0) + { + if (strncmp(action, "add", 3) == 0) + { + if (udev_addGun(dev, window)) + dev_handled = true; + } + else if (strncmp(action, "remove", 6) == 0) + { + if (udev_removeGun(dev, window)) + dev_handled = true; + } + } + + if (!dev_handled) + udev_device_unref(dev); // not handled, clean it + } + } +#elif WIN32 + if (mGuns.size() == 0) + { + Gun* newgun = new Gun(); + newgun->mIndex = mGuns.size(); + newgun->mName = "Mouse"; + mGuns.push_back(newgun); + } +#endif + + for (Gun* gun : mGuns) + updateGunPosition(gun); +} + +bool GunManager::updateGunPosition(Gun* gun) +{ +#ifdef HAVE_UDEV + struct input_absinfo absinfo; + + if (ioctl(gun->fd, EVIOCGABS(ABS_X), &absinfo) == -1) + return false; + + gun->mX = ((float)(absinfo.value - absinfo.minimum)) / ((float)(absinfo.maximum - absinfo.minimum)); + + if (ioctl(gun->fd, EVIOCGABS(ABS_Y), &absinfo) == -1) + return false; + + gun->mY = ((float)(absinfo.value - absinfo.minimum)) / ((float)(absinfo.maximum - absinfo.minimum)); + + return true; +#elif WIN32 + int x, y; + SDL_GetMouseState(&x, &y); + gun->mX = x; + gun->mY = y; + return true; +#endif + + return false; +} + + +#ifdef HAVE_UDEV +// function from retroarch +bool GunManager::udev_input_poll_hotplug_available(struct udev_monitor *dev) +{ + struct pollfd fds; + + fds.fd = udev_monitor_get_fd(dev); + fds.events = POLLIN; + fds.revents = 0; + + return (poll(&fds, 1, 0) == 1) && (fds.revents & POLLIN); +} + +void GunManager::udev_initial_gunsList() +{ + struct udev_list_entry *devs = NULL; + struct udev_list_entry *item = NULL; + + struct udev_enumerate *enumerate = udev_enumerate_new(udev); + udev_enumerate_add_match_property(enumerate, "ID_INPUT_GUN", "1"); + udev_enumerate_add_match_subsystem(enumerate, "input"); + udev_enumerate_scan_devices(enumerate); + devs = udev_enumerate_get_list_entry(enumerate); + + for (item = devs; item; item = udev_list_entry_get_next(item)) + { + const char *name = udev_list_entry_get_name(item); + struct udev_device *dev = udev_device_new_from_syspath(udev, name); + + if (udev_addGun(dev, NULL) == false) udev_device_unref(dev); // unhandled device + } +} + +bool GunManager::udev_addGun(struct udev_device *dev, Window* window) +{ + char ident[256]; + const char* devnode; + unsigned char abscaps[(ABS_MAX / 8) + 1] = { '\0' }; + + // check that devnode is of form /dev/input/eventXX (to not include devices aliases) + devnode = udev_device_get_devnode(dev); + if (devnode == NULL) return false; + if (strncmp(devnode, "/dev/input/event", 16) != 0) return false; + + int fd = open(devnode, O_RDONLY | O_NONBLOCK); + if (fd < 0) return false; + + // check absolute capabilities + if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abscaps)), abscaps) == -1) { + close(fd); + return false; + } + + // check absolute capabilities x and y + if (((test_bit(abscaps, ABS_X)) && (test_bit(abscaps, ABS_Y))) == false) { + close(fd); + return false; + } + + LOG(LogInfo) << "Gun found at " << devnode; + + if (ioctl(fd, EVIOCGNAME(sizeof(ident)), ident) < 0) + ident[0] = '\0'; + + Gun* newgun = new Gun(); + newgun->mIndex = mGuns.size(); + newgun->mName = std::string(ident); + newgun->devpath = devnode; + newgun->dev = dev; + newgun->fd = fd; + + if (!newgun->mName.empty() && window != NULL) + window->displayNotificationMessage(_U("\uF05B ") + Utils::String::format(_("%s connected").c_str(), Utils::String::trim(newgun->mName).c_str())); + + mGuns.push_back(newgun); + + return false; +} + +bool GunManager::udev_removeGun(struct udev_device *dev, Window* window) +{ + const char* devnode; + LOG(LogInfo) << "Gun removed at " << devnode; + + devnode = udev_device_get_devnode(dev); + if (devnode == NULL) return false; + + for (auto iter = mGuns.begin(); iter != mGuns.end(); iter++) + { + if (iter->devpath == devnode) + { + LOG(LogInfo) << "Gun removed found at " << devnode; + if (window != NULL) + window->displayNotificationMessage(_U("\uF05B ") + Utils::String::format(_("%s disconnected").c_str(), Utils::String::trim(iter->mName).c_str())); + + close(iter->fd); + udev_device_unref(iter->dev); + delete *iter; + mGuns.erase(iter); + return true; + } + } + return false; +} +#endif diff --git a/es-core/src/GunManager.h b/es-core/src/GunManager.h new file mode 100644 index 000000000..4881708e3 --- /dev/null +++ b/es-core/src/GunManager.h @@ -0,0 +1,75 @@ +#pragma once +#ifndef ES_CORE_GUNMANAGER_H +#define ES_CORE_GUNMANAGER_H + +#include +#include + +#ifdef HAVE_UDEV +#include +#endif + +class InputConfig; +class Window; +union SDL_Event; + +class Gun +{ + friend class GunManager; + +public: + Gun() + { + mIndex = 0; + mX = -1; + mY = -1; + } + + int index() { return mIndex; } + std::string& name() { return mName; } + + float x() { return mX; } + float y() { return mY; } + +private: + std::string mName; + + float mX; + float mY; + + int mIndex; + +#ifdef HAVE_UDEV + std::string devpath; + udev_device* dev; + int fd; +#endif +}; + +//you should only ever instantiate one of these, by the way +class GunManager +{ +public: + GunManager(); + virtual ~GunManager(); + + std::vector& getGuns() { return mGuns; } + void updateGuns(Window* window); + +private: + bool updateGunPosition(Gun* gun); + + std::vector mGuns; + +#ifdef HAVE_UDEV + struct udev *udev; + struct udev_monitor *udev_monitor; + + static bool udev_input_poll_hotplug_available(struct udev_monitor *dev); + void udev_initial_gunsList(); + bool udev_addGun(struct udev_device *dev, Window* window); + bool udev_removeGun(struct udev_device *dev, Window* window); +#endif +}; + +#endif // ES_CORE_GUNMANAGER_H diff --git a/es-core/src/InputManager.cpp b/es-core/src/InputManager.cpp index fc038e351..8ea45713f 100644 --- a/es-core/src/InputManager.cpp +++ b/es-core/src/InputManager.cpp @@ -16,15 +16,7 @@ #include "utils/StringUtil.h" #include "LocaleES.h" #include "Paths.h" - -#ifdef HAVE_UDEV -#include -#include -#include -#include -#include -#define test_bit(array, bit) (array[bit/8] & (1<<(bit%8))) -#endif +#include "GunManager.h" #define KEYBOARD_GUID_STRING "-1" #define CEC_GUID_STRING "-2" @@ -60,7 +52,7 @@ InputManager::~InputManager() InputManager* InputManager::getInstance() { - if(!mInstance) + if (!mInstance) mInstance = new InputManager(); return mInstance; @@ -87,17 +79,7 @@ void InputManager::init() mMouseButtonsInputConfig->mapInput(BUTTON_OK, Input(DEVICE_MOUSE, TYPE_BUTTON, 1, 1, true)); mMouseButtonsInputConfig->mapInput(BUTTON_BACK, Input(DEVICE_MOUSE, TYPE_BUTTON, 3, 1, true)); -#ifdef HAVE_UDEV - udev = udev_new(); - if(udev != NULL) { - udev_monitor = udev_monitor_new_from_netlink(udev, "udev"); - if (udev_monitor){ - udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "input", NULL); - udev_monitor_enable_receiving(udev_monitor); - } - } - udev_initial_gunsList(); -#endif + mGunManager = new GunManager(); } void InputManager::deinit() @@ -130,20 +112,11 @@ void InputManager::deinit() SDL_JoystickEventState(SDL_DISABLE); SDL_QuitSubSystem(SDL_INIT_JOYSTICK); -#ifdef HAVE_UDEV - if(udev != NULL) { - // close guns - for (auto iter = mGuns.begin(); iter != mGuns.end(); iter++) { - udev_removeGun(iter->second->dev, NULL); - delete iter->second; - } - mGuns.clear(); - if (udev_monitor) { - udev_monitor_unref(udev_monitor); - } - udev_unref(udev); + if (mGunManager != nullptr) + { + delete mGunManager; + mGunManager = nullptr; } -#endif } int InputManager::getNumJoysticks() @@ -256,152 +229,6 @@ void InputManager::rebuildAllJoysticks(bool deinit) SDL_JoystickEventState(SDL_ENABLE); } -#ifdef HAVE_UDEV -// function from retroarch -bool InputManager::udev_input_poll_hotplug_available(struct udev_monitor *dev) -{ - struct pollfd fds; - - fds.fd = udev_monitor_get_fd(dev); - fds.events = POLLIN; - fds.revents = 0; - - return (poll(&fds, 1, 0) == 1) && (fds.revents & POLLIN); -} - -void InputManager::udev_initial_gunsList() { - struct udev_list_entry *devs = NULL; - struct udev_list_entry *item = NULL; - - struct udev_enumerate *enumerate = udev_enumerate_new(udev); - udev_enumerate_add_match_property(enumerate, "ID_INPUT_GUN", "1"); - udev_enumerate_add_match_subsystem(enumerate, "input"); - udev_enumerate_scan_devices(enumerate); - devs = udev_enumerate_get_list_entry(enumerate); - - for (item = devs; item; item = udev_list_entry_get_next(item)) { - const char *name = udev_list_entry_get_name(item); - struct udev_device *dev = udev_device_new_from_syspath(udev, name); - - if(udev_addGun(dev, NULL) == false) udev_device_unref(dev); // unhandled device - } -} - -bool InputManager::udev_addGun(struct udev_device *dev, Window* window) { - char ident[256]; - const char* devnode; - unsigned char abscaps[(ABS_MAX / 8) + 1] = {'\0'}; - - // check that devnode is of form /dev/input/eventXX (to not include devices aliases) - devnode = udev_device_get_devnode(dev); - if(devnode == NULL) return false; - if(strncmp(devnode, "/dev/input/event", 16) != 0) return false; - - int fd = open(devnode, O_RDONLY | O_NONBLOCK); - if(fd < 0) return false; - - // check absolute capabilities - if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abscaps)), abscaps) == -1) { - close(fd); - return false; - } - - // check absolute capabilities x and y - if( ( (test_bit(abscaps, ABS_X)) && (test_bit(abscaps, ABS_Y)) ) == false) { - close(fd); - return false; - } - - LOG(LogInfo) << "Gun found at " << devnode; - - if (ioctl(fd, EVIOCGNAME(sizeof(ident)), ident) < 0) - ident[0] = '\0'; - - Gun* newgun = new Gun(); - newgun->name = std::string(ident); - newgun->devpath = devnode; - newgun->dev = dev; - newgun->fd = fd; - - if (!newgun->name.empty() && window != NULL) - window->displayNotificationMessage(_U("\uF05B ") + Utils::String::format(_("%s connected").c_str(), Utils::String::trim(newgun->name).c_str())); - - mGuns[mGuns.size()] = newgun; - - return false; -} - -bool InputManager::udev_removeGun(struct udev_device *dev, Window* window) { - const char* devnode; - LOG(LogInfo) << "Gun removed at " << devnode; - - devnode = udev_device_get_devnode(dev); - if(devnode == NULL) return false; - - for (auto iter = mGuns.begin(); iter != mGuns.end(); iter++) { - if(iter->second->devpath == devnode) { - LOG(LogInfo) << "Gun removed found at " << devnode; - if(window != NULL) - window->displayNotificationMessage(_U("\uF05B ") + Utils::String::format(_("%s disconnected").c_str(), Utils::String::trim(iter->second->name).c_str())); - - close(iter->second->fd); - udev_device_unref(iter->second->dev); - delete iter->second; - mGuns.erase(iter); - return true; - } - } - return false; -} -#endif - -void InputManager::parseGuns(Window* window) { -#ifdef HAVE_UDEV - const char* val_gun; - const char* action; - - while (udev_monitor && udev_input_poll_hotplug_available(udev_monitor)) { - struct udev_device *dev = udev_monitor_receive_device(udev_monitor); - bool dev_handled = false; - - if(dev != NULL) { - val_gun = udev_device_get_property_value(dev, "ID_INPUT_GUN"); // ID_INPUT_GUN and ID_INPUT_MOUSE for some tests - action = udev_device_get_action(dev); - - if(val_gun != NULL && strncmp(val_gun, "1", 1) == 0) { - if(strncmp(action, "add", 3) == 0) { - if(udev_addGun(dev, window)) dev_handled = true; - - } else if(strncmp(action, "remove", 6) == 0) { - if(udev_removeGun(dev, window)) dev_handled = true; - } - } - - if(dev_handled == false) udev_device_unref(dev); // not handled, clean it - } - } -#endif -} - -bool InputManager::getGunPosition(Gun* gun, float& perx, float& pery) { -#ifdef HAVE_UDEV - struct input_absinfo absinfo; - - if (ioctl(gun->fd, EVIOCGABS(ABS_X), &absinfo) == -1) { - return false; - } - perx = ((float)(absinfo.value - absinfo.minimum)) / ((float)(absinfo.maximum - absinfo.minimum)); - - if (ioctl(gun->fd, EVIOCGABS(ABS_Y), &absinfo) == -1) { - return false; - } - pery = ((float)(absinfo.value - absinfo.minimum)) / ((float)(absinfo.maximum - absinfo.minimum)); - - return true; -#endif - return false; -} - bool InputManager::parseEvent(const SDL_Event& ev, Window* window) { bool causedEvent = false; @@ -965,3 +792,9 @@ std::vector InputManager::getInputConfigs() return ret; } + +void InputManager::updateGuns(Window* window) +{ + if (mGunManager) + mGunManager->updateGuns(window); +} diff --git a/es-core/src/InputManager.h b/es-core/src/InputManager.h index 13bbac065..baea49d17 100644 --- a/es-core/src/InputManager.h +++ b/es-core/src/InputManager.h @@ -7,12 +7,12 @@ #include #include -#ifdef HAVE_UDEV -#include -#endif +#include "GunManager.h" class InputConfig; class Window; +class GunManager; + union SDL_Event; struct PlayerDeviceInfo @@ -27,15 +27,6 @@ public: virtual void onJoystickChanged() = 0; }; -struct Gun { - std::string name; -#ifdef HAVE_UDEV - std::string devpath; - udev_device* dev; - int fd; -#endif -}; - //you should only ever instantiate one of these, by the way class InputManager { @@ -58,9 +49,8 @@ public: bool parseEvent(const SDL_Event& ev, Window* window); - void parseGuns(Window* window); - bool getGunPosition(Gun* gun, float& perx, float& pery); - std::map& getGuns() { return mGuns; } + void updateGuns(Window* window); + std::vector& getGuns() { return mGunManager->getGuns(); } std::string configureEmulators(); @@ -72,9 +62,13 @@ public: static Delegate joystickChanged; + GunManager* getGunManager() { return mGunManager; } + private: InputManager(); + GunManager* mGunManager; + static InputManager* mInstance; static const int DEADZONE = 23000; static std::string getTemporaryConfigPath(); @@ -85,8 +79,6 @@ private: std::map mJoysticks; std::map mInputConfigs; - std::map mGuns; - InputConfig* mMouseButtonsInputConfig; InputConfig* mKeyboardInputConfig; InputConfig* mCECInputConfig; @@ -104,16 +96,6 @@ private: void clearJoysticks(); void rebuildAllJoysticks(bool deinit = true); - -#ifdef HAVE_UDEV - struct udev *udev; - struct udev_monitor *udev_monitor; - - static bool udev_input_poll_hotplug_available(struct udev_monitor *dev); - void udev_initial_gunsList(); - bool udev_addGun(struct udev_device *dev, Window* window); - bool udev_removeGun(struct udev_device *dev, Window* window); -#endif }; #endif // ES_CORE_INPUT_MANAGER_H diff --git a/es-core/src/Window.cpp b/es-core/src/Window.cpp index 4593f5d71..69fabd382 100644 --- a/es-core/src/Window.cpp +++ b/es-core/src/Window.cpp @@ -502,13 +502,13 @@ void Window::render() mRenderedHelpPrompts = false; // draw only bottom and top of GuiStack (if they are different) - if(mGuiStack.size()) + if (mGuiStack.size()) { auto& bottom = mGuiStack.front(); auto& top = mGuiStack.back(); bottom->render(transform); - if(bottom != top) + if (bottom != top) { if ((top->getTag() == "GuiLoading") && mGuiStack.size() > 2) { @@ -534,21 +534,21 @@ void Window::render() } } } - + if (mGuiStack.size() < 2 || !Renderer::isSmallScreen()) - if(!mRenderedHelpPrompts) + if (!mRenderedHelpPrompts) mHelp->render(transform); - if(Settings::DrawFramerate() && mFrameDataText) + if (Settings::DrawFramerate() && mFrameDataText) { Renderer::setMatrix(Transform4x4f::Identity()); mDefaultFonts.at(1)->renderTextCache(mFrameDataText.get()); } - // clock + // clock if (Settings::DrawClock() && mClock && (mGuiStack.size() < 2 || !Renderer::isSmallScreen())) mClock->render(transform); - + if (Settings::ShowControllerActivity() && mControllerActivity != nullptr && (mGuiStack.size() < 2 || !Renderer::isSmallScreen())) mControllerActivity->render(transform); @@ -569,7 +569,7 @@ void Window::render() renderAsyncNotifications(transform); } - + // Always call the screensaver render function regardless of whether the screensaver is active // or not because it may perform a fade on transition renderScreenSaver(); @@ -580,7 +580,7 @@ void Window::render() if (mVolumeInfo && Settings::VolumePopup()) mVolumeInfo->render(transform); - if(mTimeSinceLastInput >= screensaverTime && screensaverTime != 0) + if (mTimeSinceLastInput >= screensaverTime && screensaverTime != 0) { if (!isProcessing() && mAllowSleep && (!mScreenSaver || mScreenSaver->allowSleep())) { @@ -591,6 +591,33 @@ void Window::render() } } } + + // just to test + for (auto gun : InputManager::getInstance()->getGuns()) + { + if (mGunAimTexture == nullptr) + mGunAimTexture = TextureResource::get(":/gun.png", false, false, true, false); + + if (mGunAimTexture->bind()) + { + int pointerSize = 24; + + const Vector2f topLeft = { gun->x() - pointerSize, gun->y() - pointerSize }; + const Vector2f bottomRight = { gun->x() + pointerSize, gun->y() + pointerSize }; + + Renderer::Vertex vertices[4]; + vertices[0] = { { topLeft.x() , topLeft.y() }, { 0.0f, 0.0f }, 0xFFFFFFFF }; + vertices[1] = { { topLeft.x() , bottomRight.y() }, { 0.0f, 1.0f }, 0xFFFFFFFF }; + vertices[2] = { { bottomRight.x(), topLeft.y() }, { 1.0f, 0.0f }, 0xFFFFFFFF }; + vertices[3] = { { bottomRight.x(), bottomRight.y() }, { 1.0f, 1.0f }, 0xFFFFFFFF }; + + Renderer::drawTriangleStrips(&vertices[0], 4); + + + } + } +// auto output = Utils::String::format("gun %i : %.2f %.2f\n", gun->index(), gun->x(), gun->y()); + } void Window::normalizeNextUpdate() diff --git a/es-core/src/Window.h b/es-core/src/Window.h index 29adf8c0a..fee532c07 100644 --- a/es-core/src/Window.h +++ b/es-core/src/Window.h @@ -159,6 +159,8 @@ private: bool mRenderedHelpPrompts; int mTransitionOffset; + + std::shared_ptr mGunAimTexture; }; #endif // ES_CORE_WINDOW_H diff --git a/resources/gun.png b/resources/gun.png new file mode 100644 index 0000000000000000000000000000000000000000..86e5eea0e68696d33f98b4c27f225923acaf8da6 GIT binary patch literal 4648 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 literal 0 HcmV?d00001