Skip to content
This repository has been archived by the owner on Jul 16, 2020. It is now read-only.

Handling Input

JoshSnider edited this page May 2, 2018 · 5 revisions

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.

Input types

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.

Handling joystick 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;
}

Handling button input

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

Handling Custom Input

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

Cooling down controls

See the Triggering Cooldown section for details on how to put controls on cooldown for a period of time.