Jump to content

Как можно сохранить и воспроизвести нажатые клавиши ?


photo

Recommended Posts

Здравствуйте, как можно сохранить, а потом воспроизвести нажатые клавиши клавиатуры и мыши в приложении ?
Заранее спасибо.

Link to comment

Здравствуйте.

Чтобы получить все события нажатий клавиатуры и мыши можно добавить коллбэк в Input. Я бы советовал использовать CALLBACK_IMMEDIATE_INPUT, чтобы получать события также, как и движок без всякой обработки. В этот коллбэк будет приходить объект InputEvent, из которого можно получить всю необходимую информацию. В этом случае будут интересовать только события типа INPUT_EVENT_MOUSE_BUTTON и INPUT_EVENT_KEYBOARD. Сохраняем их параметры, а также кадр движка, когда получили событие. Для воспроизведения нужно использовать метод sendEvent. В нужный кадр создаем событие нужного типа и с сохраненными параметрами, а после отправляем в движок.

В статье про Input есть пример как эмулировать открытие консоли и ввод команды show_profiler 1. Можно для начала разобрать его. Возможно ещё будет полезен метод получения буфера событий, которые накопились за кадр.

Link to comment

Спасибо, просто мне казалось, что для этого уже есть встроенный механизм. На Unigine Open Air 2023 была лекция про оптимизацию и там затрагивался этот момент, но вот нюансов уже не помню )

Link to comment

@karpych11sendEvent не отрабатывает, сделал все по инструкции. 
 

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

Попробуйте эмулировать полный цикл событий клавиши:

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);

Должно точно сработать.

  • Like 1
Link to comment

@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 Можете пожалуйста помочь еще с мышью ?
Воспроизвожу события мыши,  но камера на них не реагирует, 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

Если вы используете движковое управление камерой на основе ControlsApp, то проверьте значение MouseHandle. Оно должно быть MOUSE_HANDLE_GRAB или MOUSE_HANDLE_SOFT. При этом если используется MOUSE_HANDLE_GRAB, то управление камерой захватится только по клику вне виджетов. Для теста можно выставить ControlsApp::setMouseEnabled(true) в начале эмуляции, а после выключить. Если заработает, то нужно смотреть в эмуляцию первого клика мышки.

Link to comment

@karpych11 Был выключен параметр RawInput, я его включил и мышь камера начала принимать сигнал.
Спасибо.
 

ControlsApp::setMouseRawInput(true);

 

Link to comment
×
×
  • Create New...