Marsik Posted August 10, 2023 Share Posted August 10, 2023 Здравствуйте, как можно сохранить, а потом воспроизвести нажатые клавиши клавиатуры и мыши в приложении ? Заранее спасибо. Link to comment
karpych11 Posted August 10, 2023 Share Posted August 10, 2023 Здравствуйте. Чтобы получить все события нажатий клавиатуры и мыши можно добавить коллбэк в Input. Я бы советовал использовать CALLBACK_IMMEDIATE_INPUT, чтобы получать события также, как и движок без всякой обработки. В этот коллбэк будет приходить объект InputEvent, из которого можно получить всю необходимую информацию. В этом случае будут интересовать только события типа INPUT_EVENT_MOUSE_BUTTON и INPUT_EVENT_KEYBOARD. Сохраняем их параметры, а также кадр движка, когда получили событие. Для воспроизведения нужно использовать метод sendEvent. В нужный кадр создаем событие нужного типа и с сохраненными параметрами, а после отправляем в движок. В статье про Input есть пример как эмулировать открытие консоли и ввод команды show_profiler 1. Можно для начала разобрать его. Возможно ещё будет полезен метод получения буфера событий, которые накопились за кадр. Link to comment
Marsik Posted August 11, 2023 Author Share Posted August 11, 2023 Спасибо, просто мне казалось, что для этого уже есть встроенный механизм. На Unigine Open Air 2023 была лекция про оптимизацию и там затрагивался этот момент, но вот нюансов уже не помню ) Link to comment
Marsik Posted August 11, 2023 Author Share Posted August 11, 2023 @karpych11. sendEvent не отрабатывает, сделал все по инструкции. int AppWorldLogic::update() { int frame = Game::getFrame(); if (frame == 100) { InputEventKeyboardPtr key = InputEventKeyboard::create(); key->setAction(InputEventKeyboard::ACTION_DOWN); key->setKey(Input::KEY_BACK_QUOTE); Input::sendEvent(key); } return 1; } Можете подсказать в чем проблема ? Link to comment
karpych11 Posted August 11, 2023 Share Posted August 11, 2023 Попробуйте эмулировать полный цикл событий клавиши: InputEventKeyboardPtr key_down = InputEventKeyboard::create(); key_down->setAction(InputEventKeyboard::ACTION_DOWN); key_down->setKey(Input::KEY_BACK_QUOTE); InputEventKeyboardPtr key_repeat = InputEventKeyboard::create(); key_repeat->setAction(InputEventKeyboard::ACTION_REPEAT); key_repeat->setKey(Input::KEY_BACK_QUOTE); InputEventKeyboardPtr key_up = InputEventKeyboard::create(); key_up->setAction(InputEventKeyboard::ACTION_UP); key_up->setKey(Input::KEY_BACK_QUOTE); Input::sendEvent(key_down); Input::sendEvent(key_repeat); Input::sendEvent(key_up); Должно точно сработать. 1 Link to comment
Marsik Posted August 11, 2023 Author Share Posted August 11, 2023 @karpych11 да, так работает. Пример с доков совсем не рабочий. #include "AppWorldLogic.h" #include <UnigineInput.h> using namespace Unigine; enum { STATE_OPEN_CONSOLE = 0, STATE_TYPING_COMMAND, STATE_APPLY_COMMAND, STATE_FINISH, }; int state = STATE_OPEN_CONSOLE; const char* command = "show_profiler 1"; int AppWorldLogic::update() { switch (state) { case STATE_OPEN_CONSOLE: { InputEventKeyboardPtr key = InputEventKeyboard::create(); key->setAction(InputEventKeyboard::ACTION_DOWN); key->setKey(Input::KEY_BACK_QUOTE); Input::sendEvent(key); state = STATE_TYPING_COMMAND; break; } case STATE_TYPING_COMMAND: { int size = strlen(command); for (int i = 0; i < size; i++) { InputEventTextPtr text = InputEventText::create(); text->setUnicode(command[i]); Input::sendEvent(text); } state = STATE_APPLY_COMMAND; break; } case STATE_APPLY_COMMAND: { InputEventKeyboardPtr key = InputEventKeyboard::create(); key->setAction(InputEventKeyboard::ACTION_REPEAT); key->setKey(Input::KEY_ENTER); Input::sendEvent(key); state = STATE_FINISH; break; } default: break; } return 1; } Link to comment
karpych11 Posted August 14, 2023 Share Posted August 14, 2023 Спасибо что сообщили. Поправим этот пример в ближайшее время. Link to comment
Marsik Posted August 14, 2023 Author Share Posted August 14, 2023 @karpych11 Спасибо. Link to comment
Marsik Posted August 14, 2023 Author Share Posted August 14, 2023 @karpych11 Можете пожалуйста помочь еще с мышью ? Воспроизвожу события мыши, но камера на них не реагирует, GUI отзывается. if (type == InputEvent::INPUT_EVENT_MOUSE_BUTTON) { auto inputEventMouseButton = InputEventMouseButton::create(); inputEventMouseButton->setAction((InputEventMouseButton::ACTION)actionKey); inputEventMouseButton->setButton((Input::MOUSE_BUTTON)key); inputEventMouseButton->setMousePosition(mousePosition); Input::setMousePosition(mousePosition); Input::sendEvent(inputEventMouseButton); } else if (type == InputEvent::INPUT_EVENT_MOUSE_MOTION) { auto inputEventMouseMotion = InputEventMouseMotion::create(); inputEventMouseMotion->setMousePosition(mousePosition); inputEventMouseMotion->setDelta(delta); Input::setMousePosition(mousePosition); Input::sendEvent(inputEventMouseMotion); } Link to comment
karpych11 Posted August 14, 2023 Share Posted August 14, 2023 Если вы используете движковое управление камерой на основе ControlsApp, то проверьте значение MouseHandle. Оно должно быть MOUSE_HANDLE_GRAB или MOUSE_HANDLE_SOFT. При этом если используется MOUSE_HANDLE_GRAB, то управление камерой захватится только по клику вне виджетов. Для теста можно выставить ControlsApp::setMouseEnabled(true) в начале эмуляции, а после выключить. Если заработает, то нужно смотреть в эмуляцию первого клика мышки. Link to comment
Marsik Posted August 15, 2023 Author Share Posted August 15, 2023 @karpych11 Был выключен параметр RawInput, я его включил и мышь камера начала принимать сигнал. Спасибо. ControlsApp::setMouseRawInput(true); Link to comment
Recommended Posts