-
Notifications
You must be signed in to change notification settings - Fork 56
Handling Input
A handler callback function for the on_input
callback might look something like this:
void handle_interactive_input(void* context, interactive_session session, const interactive_input* input)
{
...
}
The first parameter, context
is a pass-through parameter that your code may set in order to retain context between calls since C++ lambda functions may not be used with this C-style interface that uses function pointers. The second parameter is the current session that you may use to make subsequent calls and the final parameter is a pointer to an interactive_input
struct.
There are currently 4 input types.
-
input_type_key
- When a keyboard shortcut key is used to send a button action. -
input_type_click
- When a mouse or other pointer (perhaps touch input) is used to send a button action. -
input_type_move
- When a mouse or other pointer moves within a control such as a joystick. -
input_type_custom
- Any other type of input.
You might handle joystick input like this:
if (input_type_move == input->type)
{
// Show which user moved the joystick.
float x = input->coordinateData.x;
float y = input->coordinateData.y;
std::cout << participantName << " moved joystick to x: " + std::to_string(x) << " y: " << std::to_string(y) << std::endl;
}
For button input that has a spark cost, you must first "capture" the transaction for that input in order to deduct sparks from the user. This is because you may get multiple inputs for a single button from different users OR your game may no longer be in a state where that input makes sense and so you can defer or avoid deducting sparks altogether.
If you intend to charge sparks for buttons you should register a transaction handler.
// Register a callback for completed transactions.
err = interactive_set_transaction_complete_handler(session, handle_transaction_complete);
Then you can capture transactions in your input handler.
std::map<std::string, std::string> controlsByTransaction; // Global
if ((input_type_key == input->type || input_type_click == input->type) && interactive_button_action_down == input->buttonData.action)
{
// Capture the transaction on button down to deduct the viewer's sparks before executing any game functionality.
controlsByTransaction[input->transactionId] = input->control.id;
std::cout << participantName << " clicked '" << input->control.id << "'. Deducting sparks..." << std::endl;
err = interactive_capture_transaction(session, input->transactionId);
if (err)
{
std::cerr << "Failed to capture interactive transaction." << std::endl;
}
}
And when those transactions are complete, you can execute the functionality behind the button.
void handle_transaction_complete(void* context, interactive_session session, const char* transactionId, size_t transactionIdLength, unsigned int errorCode, const char* errorMessage, size_t errorMessageLength)
{
if (!errorCode)
{
// Transaction was captured, now execute the most super awesome interactive functionality!
std::string controlId = controlsByTransaction[std::string(transactionId, transactionIdLength)];
if (0 == strcmp("GiveHealth", controlId.c_str()))
{
std::cout << "Giving health to the player!" << std::endl;
}
}
else
{
std::cerr << errorMessage << "(" << std::to_string(errorCode) << ")" << std::endl;
}
controlsByTransaction.erase(transactionId);
}
You may have a custom control and have defined your own input types. If you want to handle custom input you can do so relatively easily as the raw JSON is available to you. In this example we parse the JSON for a Text Input control that is not parsed by the interactive library. Using the included rapidjson library or your own JSON parsing library you can obtain the raw data from the input event.
if (input_type_custom == input->type && (0 == strcmp(input->control.id, "TextInput")))
{
// Handle text input.
rapidjson::Document inputJson;
if (inputJson.Parse(input->jsonData).HasParseError())
{
std::cerr << "Failed to parse input JSON data." << std::endl;
}
std::string textInput = inputJson["input"]["value"].GetString();
std::cout << participantName << " input '" << textInput << "'." << std::endl;
}
See the Triggering Cooldown section for details on how to put controls on cooldown for a period of time.