CSC3224_Computer_Games_Development / GameEngine / Engine_Messages / MessageHandler.cpp
MessageHandler.cpp
Raw
#include "MessageHandler.h"
#include "MessageObserver.h"
MessageHandler::MessageHandler()
{
// Set up messages
	keyboardMessageMap.reserve(sf::Keyboard::KeyCount);
	keyboardControllMap.reserve(sf::Keyboard::KeyCount);
	mouseMessageMap.reserve(sf::Mouse::ButtonCount);
}

MessageHandler::~MessageHandler() {}
// Load Key Bindings from a File
void MessageHandler::loadMessagesFromFile(std::string filePath)
{
	loadingKeys.startTime();
	std::ifstream infile(filePath);
	int keyNumber, keyCode;
	std::string message;
	std::string correspondingKey;
// Read a line from current file 
	std::string textLine;
	auto cuntLineNumber = 0;
	while (getline(infile, textLine))
	{
		cuntLineNumber++;
		if (!textLine.empty())
		{
			std::stringstream parseToken(textLine);
// Parse into correct format 
			if (((parseToken >> keyNumber).fail())
				|| (parseToken >> keyCode).fail()
				|| (parseToken >> message).fail()
				|| (parseToken >> correspondingKey).fail()
				)
			{
// Invalid line from file
				std::cout << "Mapping Keys: The Line is invalid: " << cuntLineNumber << std::endl;
				continue;
			}
//Change keyCode into correct type
			switch (keyNumber)
			{	
// Keyboard	
			case 0:
				if (keyCode > sf::Keyboard::KeyCount || keyCode < 0)
				{
					std::cout << "The Keyboard code is out of range. At Line: " << cuntLineNumber << std::endl;
					continue;
				}
				keyboardMessageMap.erase(sf::Keyboard::Key(keyCode));
				keyboardMessageMap.emplace(sf::Keyboard::Key(keyCode), message);
				keyboardControllMap.erase(sf::Keyboard::Key(keyCode));
				keyboardControllMap.emplace(sf::Keyboard::Key(keyCode), correspondingKey);	
				break;
// Mouse 
			case 1:
				if (keyCode > sf::Mouse::ButtonCount || keyCode < 0)
				{
					std::cout << "The Mouse code is out of range. At Line: " << cuntLineNumber << std::endl;
					continue;
				}
				mouseMessageMap.erase(sf::Mouse::Button(keyCode));
				mouseMessageMap.emplace(sf::Mouse::Button(keyCode), message);
				mouseControllMap.erase(sf::Mouse::Button(keyCode));
				mouseControllMap.emplace(sf::Mouse::Button(keyCode), correspondingKey);
				 if (sf::Mouse::isButtonPressed(sf::Mouse::Left))
				 {
					 message.append(correspondingKey);
				 }
				break;
// Invalid number 
			default:;
				std::cout << "Mapping Keys:: The map number is invalid. At Line: " << cuntLineNumber << std::endl;
			}
		}
	}
	loadingKeys.finishProfiler();
}
// Print the Key bindings for the player
void MessageHandler::printKeyMap()
{
	std::cout << "Keyboard Keybindings " << std::endl;
	std::cout << "KeyCode\tFunction" << std::endl;
	for (auto assign : keyboardMessageMap)
	{
		std::cout << assign.first << "\t" << assign.second << std::endl;
	}

	std::cout << "Keyboard Button: " << std::endl;
	std::cout << "KeyCode\tButton" << std::endl;
	for (auto assign : keyboardControllMap)
	{
		std::cout << assign.first << "\t" << assign.second << std::endl;
	}

	std::cout << "\nMouse Keybindings " << std::endl;
	std::cout << "KeyCode\tFunction" << std::endl;
	for (auto assign : mouseMessageMap)
	{
		std::cout << assign.first << "\t" << assign.second << std::endl;
	}

	std::cout << "Mouse Button: " << std::endl;
	std::cout << "KeyCode\tFunction" << std::endl;
	for (auto assign : mouseControllMap)
	{
		std::cout << assign.first << "\t" << assign.second << std::endl;
	}


}
// Add Message Observer
void MessageHandler::addMessageObserver(MessageObserver* message)
{
	messageList.push_front(message);
}
// Remove Message Observer
void MessageHandler::removeMessageObserver(MessageObserver* message)
{
	messageList.remove(message);
}
// Process Messages - Events
void MessageHandler::processMessages()
{
// Keyboard messages
	for (auto assign : keyboardMessageMap)
	{
		auto messageKey = assign.first;
		MessageState currentMessageState;
// Check for previous previous message states -  If there are no previous message states
		if(keyboardState.count(messageKey) > 0)
		{
			currentMessageState = advanceMessageState(keyboardState[messageKey], sf::Keyboard::isKeyPressed(messageKey));
		}
// check for valid message states - If no valid message state - set as UP message State
		else
		{
			currentMessageState = advanceMessageState(MessageState::UP_STATE, sf::Keyboard::isKeyPressed(messageKey));
		}
		keyboardState[messageKey] = currentMessageState;
		MessageEvent message{0, assign.second, currentMessageState };
		sendMessage(message);
	}

//Mouse messages
	for (auto assign : mouseMessageMap)
	{
		auto button = assign.first;
		MessageState currentMessageState;
// check for valid message states-  If there are previous message states
		if (mouseState.count(button) > 0)
		{
			currentMessageState = advanceMessageState(mouseState[button], sf::Mouse::isButtonPressed(button));
		}
// check for valid message states - if no valid message state - set as UP message State
		else
		{
			currentMessageState = advanceMessageState(MessageState::UP_STATE, sf::Mouse::isButtonPressed(button));
		}
		mouseState[button] = currentMessageState;

		MessageEvent message{ 1, assign.second, currentMessageState, sf::Mouse::getPosition() };
		sendMessage(message);
	}
}
// Step through the Message States
MessageState MessageHandler::advanceMessageState(MessageState current, bool isKeyPressed)
{
//Update new message state based on old message state and proceed
	MessageState newMessageState;
	switch (current)
	{
	case MessageState::PRESSED_STATE:
	case MessageState::DOWN_STATE:
		{
			if (isKeyPressed)
				newMessageState = MessageState::DOWN_STATE;
			else
				newMessageState = MessageState::RELEASED_STATE;
			break;
		}
	case MessageState::RELEASED_STATE:
	case MessageState::UP_STATE:
		{
			if (isKeyPressed)
				newMessageState = MessageState::PRESSED_STATE;
			else
				newMessageState = MessageState::UP_STATE;
			break;
	}
	default:
		newMessageState = MessageState::UP_STATE;
	}

	return newMessageState;
}
// Send message
void MessageHandler::sendMessage(MessageEvent message)
{
	for (auto iterator = messageList.begin(), end = messageList.end(); iterator != end; ++iterator)
	{
		(*iterator)->onNotify(message);
	}
}