//==========================================================================//
// File:	controls.cc                                                       //
// Project: MUNGA           Brick: Controls Manager                         //
// Contents: Interface specification for Controls                           //
//--------------------------------------------------------------------------//
//   Date    Who  Modification                                              //
// --------  ---  ----------------------------------------------------------//
// 11/21/94  CPB  Initial coding.                                           //
// 01/25/95  CPB  Major surgery! Removed Entities, added Subsystems.        //
//--------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc.               //
// All Rights reserved worldwide                                            //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL              //
//==========================================================================//

#include "AdeptHeaders.hpp"

#include "Controls.hpp"
#include "EntityAttribute.hpp"
#include "Joystick.hpp"
#include "Application.hpp"
#include "Interface.hpp"
//############################################################################
//#######################    ControlsInstance    #############################
//############################################################################

//
// Shared Data Support
//
ControlsInstance::ClassData*
	ControlsInstance::DefaultData = NULL;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	ControlsInstance::InitializeClass()
{
	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			ControlsInstanceClassID,
			"Adept::ControlsInstance",
			Plug::DefaultData
		);
	Register_Object(DefaultData);
	gos_EnableSetting (gos_Set_NumLockMode,1);
	gos_EnableSetting (gos_Set_ScrollLockMode,0);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	ControlsInstance::TerminateClass()
{
	Unregister_Object(DefaultData);
	delete DefaultData;
	DefaultData = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
ControlsInstance::ControlsInstance(
	ClassData *class_data,
	int control_mask,
	Plug *owner
):
	Plug(class_data),
	dependantPlug(this)
{
	Check_Pointer(this);

	controlMask = control_mask;
	dependantPlug.Add(owner);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
ControlsInstance::~ControlsInstance()
{
	Check_Object(this);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	ControlsInstance::TestInstance()
{
	Verify(IsDerivedFrom(DefaultData));
}

//############################################################################
//######################### DirectControlsInstance ###########################
//############################################################################

DirectControlsInstance::ClassData*
	DirectControlsInstance::DefaultData = NULL;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	DirectControlsInstance::InitializeClass()
{
	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			DirectControlsInstanceClassID,
			"Adept::DirectControlsInstance",
			ControlsInstance::DefaultData
		);
	Register_Object(DefaultData);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	DirectControlsInstance::TerminateClass()
{
	Unregister_Object(DefaultData);
	delete DefaultData;
	DefaultData = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
DirectControlsInstance::DirectControlsInstance(
	int control_mask,
	Entity *entity_to_control,
	Entity::AttributeID attribute_ID,
	RegisteredClass::ClassID attribute_type,
	Plug *dependant,
	bool invert
):
	ControlsInstance(DefaultData, control_mask, dependant)
{
	entity = entity_to_control;
	Check_Object(entity);
	attributeEntry = entity->GetAttributeEntry(attribute_ID);
	Check_Object(attributeEntry);
	Verify(attributeEntry->attributeType == attribute_type);
	m_Invert = invert;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
DirectControlsInstance::~DirectControlsInstance()
{
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	DirectControlsInstance::Update(void *data_source)
{
	Scalar hack;
	hack = -*((Scalar *) data_source);
	Check_Object(attributeEntry);
	if (m_Invert)
		attributeEntry->SetValue(entity, &hack);
	else
		attributeEntry->SetValue(entity, data_source);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	DirectControlsInstance::TestInstance()
{
	Verify(IsDerivedFrom(DefaultData));
}

//############################################################################
//######################### EventControlsInstance ############################
//############################################################################

//
// Shared Data Support
//
EventControlsInstance::ClassData*
	EventControlsInstance::DefaultData = NULL;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EventControlsInstance::InitializeClass()
{
	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			EventControlsInstanceClassID,
			"Adept::EventControlsInstance",
			ControlsInstance::DefaultData
		);
	Register_Object(DefaultData);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EventControlsInstance::TerminateClass()
{
	Unregister_Object(DefaultData);
	delete DefaultData;
	DefaultData = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EventControlsInstance::EventControlsInstance(
	ClassData *class_data,
	int control_mask,
	Receiver *receiver,
	Receiver::MessageID message_id,
	Plug *dependant
):
	ControlsInstance(class_data, control_mask, dependant)
{
	Check_Object(receiver);
	receiverPointer = receiver;
	messageID = message_id;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EventControlsInstance::~EventControlsInstance()
{
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EventControlsInstance::TestInstance()
{
	Verify(IsDerivedFrom(DefaultData));
}

//############################################################################
//######################### ControlsMappingGroup #############################
//############################################################################

//
// Shared Data Support
//
ControlsMappingGroup::ClassData*
	ControlsMappingGroup::DefaultData = NULL;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	ControlsMappingGroup::InitializeClass()
{
	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			ControlsMappingGroupClassID,
			"Adept::ControlsMappingGroup",
			Plug::DefaultData
		);
	Register_Object(DefaultData);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	ControlsMappingGroup::TerminateClass()
{
	Unregister_Object(DefaultData);
	delete DefaultData;
	DefaultData = NULL;
}

//
// The ControlsMappingGroup object maintains a group of ControlInstances.
//
// ControlsMappingGroup.Update() will call ControlsInstance.Update()
// for each instance in the group.
//

ControlsMappingGroup::ControlsMappingGroup():
	Plug(DefaultData),
	instanceList(NULL)
{
	Check_Pointer(this);
}

ControlsMappingGroup::~ControlsMappingGroup()
{
	Check_Object(this);
	Remove(0);		// remove all mappings
}

void ControlsMappingGroup::Remove(const Entity::AttributeID& attr_id,const Receiver::MessageID& mesg_id)
{
	Check_Object(this);

	ChainIteratorOf<ControlsInstance*> i(&instanceList);

	ControlsInstance *controls_instance;

	while ((controls_instance=i.ReadAndNext()) != NULL)
	{
		Check_Object(controls_instance);
		//---------------------------------------------
		// Remove mapping bit(s)
		//---------------------------------------------
		if ((attr_id != 0) && (controls_instance->IsDerivedFrom (DirectControlsInstance::DefaultData)))
		{
			DirectControlsInstance *di;
			di = Cast_Object (DirectControlsInstance *,controls_instance);
			if (di->attributeEntry->attributeID == attr_id)
			{
				Unregister_Object (controls_instance);
				delete controls_instance;
			}
		}
		else if ((mesg_id != 0) && (controls_instance->IsDerivedFrom (EventControlsInstance::DefaultData)))
		{
			EventControlsInstance *ei;
			ei = Cast_Object (EventControlsInstance *,controls_instance);
			if (ei->messageID == mesg_id)
			{
				Unregister_Object (controls_instance);
				delete controls_instance;
			}
		}
	}
}

void ControlsMappingGroup::Remove(int control_mask)
{
	Check_Object(this);

	ChainIteratorOf<ControlsInstance*> i(&instanceList);

	ControlsInstance *controls_instance;

	while ((controls_instance=i.ReadAndNext()) != NULL)
	{
		Check_Object(controls_instance);
		//---------------------------------------------
		// Remove mapping bit(s)
		//---------------------------------------------
		controls_instance->controlMask &= ~control_mask;
		//---------------------------------------------
		// If no bits left, delete mapping
		//---------------------------------------------
		if (controls_instance->controlMask == (int)0)
		{
			Unregister_Object(controls_instance);
			delete controls_instance;
		}
	}
}

void
	ControlsMappingGroup::Update(void *data_source, int control_mask)
{
	Check_Object(this);
	Check_Pointer(data_source);

	ChainIteratorOf<ControlsInstance*>
		i(&instanceList);

	ControlsInstance
		*controls_instance = NULL;

	while ((controls_instance=i.ReadAndNext()) != NULL)
	{
		//------------------------------------------------
		// Process only if at least one mode bit matches
		//------------------------------------------------
		Check_Object(controls_instance);
		if (controls_instance->controlMask & control_mask)
		{
			controls_instance->Update(data_source);
		}
	}
}

bool
	ControlsMappingGroup::CurrentFilterStatus(int control_mask)
{
	Check_Object(this);

	ChainIteratorOf<ControlsInstance*>
		i(&instanceList);

	ControlsInstance
		*controls_instance;

	while ((controls_instance=i.ReadAndNext()) != NULL)
	{
		Check_Object(controls_instance);

		if (controls_instance->controlMask & control_mask)
		{
			return true;
		}
	}
	return false;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	ControlsMappingGroup::TestInstance()
{
	Verify(IsDerivedFrom(DefaultData));
}

//############################################################################
//########################### ControlsManager ################################
//############################################################################

//---------------------------------------------------------------------------
// Class derivation
//---------------------------------------------------------------------------

ControlsManager::ClassData*
	ControlsManager::DefaultData = NULL;

ControlsManager*
	ControlsManager::Instance = NULL;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	ControlsManager::InitializeClass()
{
	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			ControlsManagerClassID,
			"Adept::ControlsManager",
			Receiver::DefaultData,
			0, NULL
		);
	Register_Object(DefaultData);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	ControlsManager::TerminateClass()
{
	Unregister_Object(DefaultData);
	delete DefaultData;
	DefaultData = NULL;
}

//
//############################################################################
// ControlsManager
//
// Creator method
//----------------------------------------------------------------------------
// Enter: virtualDataPtr
//############################################################################
//
ControlsManager::ControlsManager():
	Receiver(DefaultData),
	activeButtons(NULL),
	m_ChatInterface (NULL)
{
	activeDestination = NULL;
	activeReceiver = NULL;
	activeMessageID = (Receiver::MessageID) 0;
	activeDependant = NULL;
	m_ChatMode = false;
	m_ListChanged = false;
	m_IgnoreCommands = false;

	//
	//---------------------------
	// Get mode mask for updating
	//---------------------------
	//
	m_ClearingChatEnter=false;
	m_ClearingChatEscape = false;
	controlMask = 0;
	int i;
	
	pressAnyKey = false;

	//
	//-----------------------------------------------------------------
	// See if there is a GOS joystick.  If so, create and initialize it
	//-----------------------------------------------------------------
	//
	systemJoystick = NULL;
	joystickAxisGroup = NULL;
	joystickButtonGroup = NULL;
	joystickHat = NULL;
/*
	if (gosJoystick_CountJoysticks() > 0)
	{
		gosJoystick_SetPolling(0, true);
		systemJoystick = new Joystick(
			0,		//Joystick ID
			0.08f,	//XAxis dead zone percent
			0.05f,	//YAxis dead zone percent
			0.05f,	//ThrottleAxis dead zone percent
			0.15f	//RudderAxis dead zone percent
		);
		Register_Object(systemJoystick);

		//
		//-------------------------
		// Create the axis managers
		//-------------------------
		//
		joystickAxisGroup =
			new ControlsUpdateManagerOf<Scalar>[Joystick::AxisCount];
		Register_Pointer(joystickAxisGroup);
		for (i=0; i<Joystick::AxisCount; ++i)
		{
			joystickAxisGroup[i].ForceUpdate(
				&systemJoystick->axisValues[i],
				controlMask
			);
		}

		//
		//---------------------------
		// Create the button managers
		//---------------------------
		//
		joystickButtonGroup =
			new ControlsUpdateManagerOf<int>[
				systemJoystick->buttonCount
			];
		Register_Pointer(joystickButtonGroup);
		int initial_button_value = 0;
		for (i=0; i<systemJoystick->buttonCount; ++i)
		{
			joystickButtonGroup[i].ForceUpdate(
				&initial_button_value,
				controlMask
			);
		}

		//
		//---------------------------
		// Create the button managers
		//---------------------------
		//
		if (systemJoystick->HasHat())
		{
			joystickHat = new ControlsUpdateManagerOf<Radian>;
			Register_Object(joystickHat);
			Radian rad(Two_Pi);
			joystickHat->ForceUpdate(&rad, controlMask);
		}
	}
*/
	//
	//-----------------------------------
	// Check to see if a mouse is present
	//-----------------------------------
	//
	Scalar initial_data(0.0f);
	mousePosX.ForceUpdate(&initial_data, controlMask);
	mousePosY.ForceUpdate(&initial_data, controlMask);

	Scalar initial_speed(0);
	mouseDeltaX.ForceUpdate(&initial_speed, controlMask);
	mouseDeltaY.ForceUpdate(&initial_speed, controlMask);

	int press=0;
	mouseWheelDelta.ForceUpdate(&press,controlMask);
	for (i=0; i<ELEMENTS(mouseButtonGroup); ++i)
		mouseButtonGroup[i].ForceUpdate(&press, controlMask);

	//
	//-------------------------------
	// Set up the button value arrays
	//-------------------------------
	//
	int key=0;
	for (i=0; i<ELEMENTS(virtualButtonGroup); ++i)
		virtualButtonGroup[i].ForceUpdate(&key, controlMask);

	//
	//------------------------
	// Initialize the keyboard
	//------------------------
	//
	systemKeyboard.Update(&press, controlMask);
}

//
//############################################################################
// ~ControlsManager
//
// Destructor method
//############################################################################
//
ControlsManager::~ControlsManager()
{
	Check_Object(this);

	//
	//--------------------
	// Delete the joystick
	//--------------------
	//
	if (systemJoystick)
	{
		Check_Object(systemJoystick);
		Unregister_Pointer(joystickHat);
		delete[] joystickHat;
		Unregister_Pointer(joystickButtonGroup);
		delete[] joystickButtonGroup;
		Unregister_Pointer(joystickAxisGroup);
		delete[] joystickAxisGroup;
		Unregister_Object(systemJoystick);
		delete systemJoystick;
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void ControlsManager::JoyStickShift (int value)
{
	m_JoyStickShiftButton = value;
	if (systemJoystick)
		systemJoystick->ShiftButton (value);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void ControlsManager::SetJoystick (int id)
{
	int i;
	if (systemJoystick)
	{
		Check_Object(systemJoystick);
		Unregister_Pointer(joystickHat);
		delete[] joystickHat;
		Unregister_Pointer(joystickButtonGroup);
		delete[] joystickButtonGroup;
		Unregister_Pointer(joystickAxisGroup);
		delete[] joystickAxisGroup;
		Unregister_Object(systemJoystick);
		delete systemJoystick;
	}
	systemJoystick = NULL;
	joystickAxisGroup = NULL;
	joystickButtonGroup = NULL;
	joystickHat = NULL;

	if (gosJoystick_CountJoysticks(false) > id)
	{
		gosJoystick_SetPolling(id, true);
		systemJoystick = new Joystick(
			id,		//Joystick ID
			0.08f,	//XAxis dead zone percent
			0.05f,	//YAxis dead zone percent
			0.05f,	//ThrottleAxis dead zone percent
			0.15f	//RudderAxis dead zone percent
		);
		Register_Object(systemJoystick);
		if (systemJoystick)
			systemJoystick->ShiftButton (m_JoyStickShiftButton);

		//
		//-------------------------
		// Create the axis managers
		//-------------------------
		//
		joystickAxisGroup =	new ControlsUpdateManagerOf<Scalar>[Joystick::AxisCount];
		Register_Pointer(joystickAxisGroup);
		for (i=0; i<Joystick::AxisCount; ++i)
		{
			joystickAxisGroup[i].ForceUpdate(&systemJoystick->axisValues[i],controlMask);
		}

		//
		//---------------------------
		// Create the button managers
		//---------------------------
		//
		joystickButtonGroup = new ControlsUpdateManagerOf<int>[systemJoystick->buttonCount];
		Register_Pointer(joystickButtonGroup);
		int initial_button_value = 0;
		for (i=0; i<systemJoystick->buttonCount; ++i)
		{
			joystickButtonGroup[i].ForceUpdate(&initial_button_value,controlMask);
		}

		//
		//---------------------------
		// Create the button managers
		//---------------------------
		//
		if (systemJoystick->HasHat())
		{
			joystickHat = new ControlsUpdateManagerOf<int>[4];
			Register_Pointer(joystickHat);
			int initial_button_value = 0;
			for (i=0; i<4; ++i)
			{
				joystickHat[i].ForceUpdate(&initial_button_value, controlMask);
			}
		}
	}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

void ControlsManager::RemoveAllMappings()
{
	Check_Object(this);

	pressAnyKey = false;
	m_ListChanged = true;
	m_AllMappings.clear ();

	int i;
	if (systemJoystick)
	{
		Check_Object(systemJoystick);
		Check_Pointer(joystickAxisGroup);
		for (i=0; i<Joystick::AxisCount; ++i)
		{
			Check_Object(&joystickAxisGroup[i]);
			joystickAxisGroup[i].RemoveAll();
		}
		for (i=0; i<systemJoystick->buttonCount; ++i)
		{
			Check_Object(&joystickButtonGroup[i]);
			joystickButtonGroup[i].RemoveAll();
		}
		if (joystickHat)
		{
			Check_Object(joystickHat);
			for (i=0; i<4; ++i) 
			{
				Check_Object(&joystickHat[i]);
				joystickHat[i].RemoveAll();
			}
		}
	}

	//
	//---------------------------
	// Remove mappings from mouse
	//---------------------------
	//
	mousePosX.RemoveAll();
	mousePosY.RemoveAll();
	mouseDeltaX.RemoveAll();
	mouseDeltaY.RemoveAll();
	mouseWheelDelta.RemoveAll ();
	for (i=0; i<ELEMENTS(mouseButtonGroup); ++i)
	{
		Check_Object(&mouseButtonGroup[i]);
		mouseButtonGroup[i].RemoveAll();
	}

	//
	//----------------------------------------
	// Remove mappings from the system buttons
	//----------------------------------------
	//
	for (i=0; i<ELEMENTS(virtualButtonGroup); ++i)
	{
		Check_Object(&virtualButtonGroup[i]);
		virtualButtonGroup[i].RemoveAll();
	}

	//
	//----------------------------------
	// Remove mappings from the keyboard
	//----------------------------------
	//

	ButtonIterator buttons(&activeButtons);
	ControlsUpdateManagerOf<int>* button;
	while ((button = buttons.GetCurrent()) != NULL)
	{
		buttons.Remove();
		
	}

	

	systemKeyboard.RemoveAll();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int ControlsManager::Remove(int group,int element,int control_mask)
{
	stlport::vector<ControlData>::iterator iter;
	int count;
	
	iter = m_AllMappings.begin ();
	count = 0;
	while (iter != m_AllMappings.end ())
	{
		if ((iter->group == group) && (iter->element == element))
		{
			iter = m_AllMappings.erase (iter);
			count++;
		}
		else
			iter++;
	}

	switch (group)
	{
	case JoystickAxisGroupID:
		if (systemJoystick)
		{
			Check_Object(systemJoystick);
			if (static_cast<unsigned>(element) < Joystick::AxisCount && systemJoystick->HasAxis(element) )
				joystickAxisGroup[element].Remove (control_mask);
		}
		break;

	case JoystickButtonGroupID:
		if (systemJoystick)
		{
			Check_Object(systemJoystick);
			if (static_cast<unsigned>(element) < systemJoystick->buttonCount)
				joystickButtonGroup[element].Remove (control_mask);
		}
		break;

	case JoystickHatID:
		if (systemJoystick)
		{
			Check_Object(systemJoystick);
			if (systemJoystick->HasHat())
			{
				Check_Object(joystickHat);
				if (static_cast<unsigned>(element) < 4)
					joystickHat[element].Remove (control_mask);
			}
		}
		break;

	//
	//-----------------------
	// Add the mouse mappings
	//-----------------------
	//
	case MousePosXID:
		Check_Object(&mousePosX);
		mousePosX.Remove (control_mask);
		break;

	case MousePosYID:
		Check_Object(&mousePosY);
		mousePosY.Remove (control_mask);
		break;

	case MouseDeltaXID:
		Check_Object(&mouseDeltaX);
		mouseDeltaX.Remove (control_mask);
		break;

	case MouseDeltaYID:
		Check_Object(&mouseDeltaY);
		mouseDeltaY.Remove (control_mask);
		break;

	case MouseWheelDeltaID:
		Check_Object(&mouseWheelDelta);
		mouseWheelDelta.Remove (control_mask);
		break;

	case MouseButtonGroupID:
		Verify(static_cast<unsigned>(element) < ELEMENTS(mouseButtonGroup));
		mouseButtonGroup[element].Remove (control_mask);
		break;

	//
	//-----------------------------------
	// Add the keyboard 'button' mappings
	//-----------------------------------
	//
	case VirtualButtonGroupID:
		Verify(static_cast<unsigned>(element) < ELEMENTS(virtualButtonGroup));

		virtualButtonGroup[element].Remove (control_mask);

		break;

	case SystemKeyboardID:
		systemKeyboard.Remove (control_mask);
		break;

	default:
		STOP(("Unknown mapping group!\n"));
		break;
	}

	return count;
}

int ControlsManager::Remove (const Entity::AttributeID& attr_id,const MessageID& mesg_id)
{
	Verify ((attr_id == 0) || (mesg_id == 0));
	
	stlport::vector<ControlData>::iterator iter;
	int count;
	
	iter = m_AllMappings.begin ();
	count = 0;
	while (iter != m_AllMappings.end ())
	{
		if ((iter->attr_id == attr_id) && (iter->mesg_id == mesg_id))
		{
			iter = m_AllMappings.erase (iter);
			count++;
		}
		else
			iter++;
	}

	//
	//------------------------------
	// Remove mappings from joystick
	//------------------------------
	//

	int i;
	if (systemJoystick)
	{
		Check_Object(systemJoystick);
		Check_Pointer(joystickAxisGroup);
		for (i=0; i<Joystick::AxisCount; ++i)
		{
			Check_Object(&joystickAxisGroup[i]);
			joystickAxisGroup[i].Remove(attr_id,mesg_id);
		}
		for (i=0; i<systemJoystick->buttonCount; ++i)
		{
			Check_Object(&joystickButtonGroup[i]);
			joystickButtonGroup[i].Remove(attr_id,mesg_id);
		}
		if (joystickHat)
		{
			Check_Object(joystickHat);
			for (i=0; i<4; ++i)
			{
				Check_Object(&joystickHat[i]);
				joystickHat[i].Remove(attr_id,mesg_id);
			}
		}
	}

	//
	//---------------------------
	// Remove mappings from mouse
	//---------------------------
	//
	mousePosX.Remove(attr_id,mesg_id);
	mousePosY.Remove(attr_id,mesg_id);
	mouseDeltaX.Remove(attr_id,mesg_id);
	mouseDeltaY.Remove(attr_id,mesg_id);
	mouseWheelDelta.Remove(attr_id,mesg_id);
	for (i=0; i<ELEMENTS(mouseButtonGroup); ++i)
	{
		Check_Object(&mouseButtonGroup[i]);
		mouseButtonGroup[i].Remove(attr_id,mesg_id);
	}

	//
	//----------------------------------------
	// Remove mappings from the system buttons
	//----------------------------------------
	//
	for (i=0; i<ELEMENTS(virtualButtonGroup); ++i)
	{
		Check_Object(&virtualButtonGroup[i]);
		virtualButtonGroup[i].Remove(attr_id,mesg_id);
	}



	//
	//----------------------------------
	// Remove mappings from the keyboard
	//----------------------------------
	//
	systemKeyboard.Remove(attr_id,mesg_id);

	return count;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void ControlsManager::Remove(int control_mask)
{
	Check_Object(this);

	stlport::vector<ControlData>::iterator iter;
	
	iter = m_AllMappings.begin ();
	while (iter != m_AllMappings.end ())
	{
		if (iter->control_mask == control_mask)
			iter = m_AllMappings.erase (iter);
		else
			iter++;
	}


	//
	//------------------------------
	// Remove mappings from joystick
	//------------------------------
	//
	int i;
	if (systemJoystick)
	{
		Check_Object(systemJoystick);
		Check_Pointer(joystickAxisGroup);
		for (i=0; i<Joystick::AxisCount; ++i)
		{
			Check_Object(&joystickAxisGroup[i]);
			joystickAxisGroup[i].Remove(control_mask);
		}
		for (i=0; i<systemJoystick->buttonCount; ++i)
		{
			Check_Object(&joystickButtonGroup[i]);
			joystickButtonGroup[i].Remove(control_mask);
		}
		if (joystickHat)
		{
			Check_Object(joystickHat);
			for (i=0; i<4; ++i) 
			{
				Check_Object(&joystickHat[i]);
				joystickHat[i].Remove(control_mask);
			}
		}
	}

	//
	//---------------------------
	// Remove mappings from mouse
	//---------------------------
	//
	mousePosX.Remove(control_mask);
	mousePosY.Remove(control_mask);
	mouseDeltaX.Remove(control_mask);
	mouseDeltaY.Remove(control_mask);
	mouseWheelDelta.Remove(control_mask);
	for (i=0; i<ELEMENTS(mouseButtonGroup); ++i)
	{
		Check_Object(&mouseButtonGroup[i]);
		mouseButtonGroup[i].Remove(control_mask);
	}

	//
	//----------------------------------------
	// Remove mappings from the system buttons
	//----------------------------------------
	//
	for (i=0; i<ELEMENTS(virtualButtonGroup); ++i)
	{
		Check_Object(&virtualButtonGroup[i]);
		virtualButtonGroup[i].Remove(control_mask);
	}



	//
	//----------------------------------
	// Remove mappings from the keyboard
	//----------------------------------
	//
	systemKeyboard.Remove(control_mask);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void ControlsManager::CenterMouse(void)
{
	gos_SetMousePosition (0.5f,0.5f);

}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void ControlsManager::TowardsCenterMouse (Scalar amountx,Scalar amounty)
{
	Scalar posx,posy;

	if (amountx < 0)
		amountx *= -1.0f;
	if (amounty < 0)
		amounty *= -1.0f;
 	gos_GetMouseInfo(&posx,&posy,NULL,NULL,NULL,NULL);

	if (posx < 0.5f)
	{
		posx += amountx;
		Max_Clamp (posx,0.5f);
	}
	else if (posx > 0.5f)
	{
		posx -= amountx;
		Min_Clamp (posx,0.5f);
	}
	if (posy < 0.5f)
	{
		posy += amounty;
		Max_Clamp (posy,0.5f);
	}
	else if (posy > 0.5f)
	{
		posy -= amounty;
		Min_Clamp (posy,0.5f);
	}
	gos_SetMousePosition (posx,posy);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	ControlsManager::Execute()
{
	Check_Object(this);

	if (m_IgnoreCommands)
	{
		return;
	}

	bool wheelup=false,wheeldown = false;
	bool mousex_left = false;
	bool mousex_right = false;
	bool mousey_up = false;
	bool mousey_down = false;
	bool joyx_left = false;
	bool joyx_right = false;
	bool joyy_up = false;
	bool joyy_down = false;
	bool joyrudder_left = false;
	bool joyrudder_right = false;
	bool joythrottle_up = false;
	bool joythrottle_down = false;
	bool hat_left = false;
	bool hat_right = false;
	bool hat_up = false;
	bool hat_down = false;
			
	//
			//---------------------
	// Set the control mask
	//---------------------
	//
	int control_mode = 0;
	if (gos_GetKeyStatus(KEY_LSHIFT))
		control_mode |= ShiftMode;
	if (gos_GetKeyStatus(KEY_LCONTROL))
		control_mode |= CtrlMode;
	if (gos_GetKeyStatus(KEY_LMENU))
		control_mode |= AltMode;

	//
	//----------------------------
	// Read system joystick inputs
	//----------------------------
	//
	if (systemJoystick)
	{
		int temp_mode = control_mode;
		temp_mode &= ShiftMode;
		if (systemJoystick->ShiftButton ())
			temp_mode |= ShiftMode;
		controlMask = 1<<temp_mode;
		Check_Object(systemJoystick);
		systemJoystick->Update(
			controlMask,
			joystickAxisGroup,
			joystickButtonGroup,
			joystickHat
		);

		if (systemJoystick->HasAxis (Joystick::XAxis))
		{
			if (systemJoystick->axisValues[Joystick::XAxis] < -0.5f)
				joyx_left = true;
			else if (systemJoystick->axisValues[Joystick::XAxis] > 0.5f)
				joyx_right = true;
		}
		
		if (systemJoystick->HasAxis (Joystick::YAxis))
		{
			if (systemJoystick->axisValues[Joystick::YAxis] < -0.5f)
				joyy_up = true;
			else if (systemJoystick->axisValues[Joystick::YAxis] > 0.5f)
				joyy_down = true;
		}

		if (systemJoystick->HasAxis (Joystick::ThrottleAxis))
		{
			if (systemJoystick->axisValues[Joystick::ThrottleAxis] < 0.25f)
				joythrottle_up = true;
			else if (systemJoystick->axisValues[Joystick::ThrottleAxis] > 0.75f)
				joythrottle_down = true;
		}
		
		if (systemJoystick->HasAxis (Joystick::RudderAxis))
		{
			if (systemJoystick->axisValues[Joystick::RudderAxis] < -0.5f)
				joyrudder_left = true;
			else if (systemJoystick->axisValues[Joystick::RudderAxis] > 0.5f)
				joyrudder_right = true;
		}
		
		if (systemJoystick->HasHat ())
		{
			Scalar value = systemJoystick->hatValue;

			if (value == -1.0f)
			{
			}
			else if ((value > 0.875f) || (value < 0.125f))
				hat_up = true;
			else if ((value>= 0.125f) && (value <= 0.375f))
				hat_right = true;
			else if ((value> 0.375f) && (value < 0.625f))
				hat_down = true;
			else if ((value>= 0.625f) && (value <= 0.875f))
				hat_left = true;
		}

	}

	controlMask = 1<<control_mode;

	//
	//---------------
	// Read the mouse
	//---------------
	//
	{
		int temp_mode = control_mode;
		temp_mode &= ShiftMode;
		controlMask = 1<<temp_mode;

		Scalar posx,posy,temp;
		int deltax,deltay;
		int wheel;
		DWORD buttons;
		gos_GetMouseInfo(&posx,&posy,&deltax,&deltay,&wheel,&buttons);
	
		if (deltax < -25)
			mousex_left = true;
		else if (deltax>25)
			mousex_right = true;
		if (deltay < -25)
			mousey_up = true;
		else if (deltay>25)
			mousey_down = true;
	
		mousePosX.ForceUpdate(&posx, 1);
		mousePosY.ForceUpdate(&posy, 1);
		temp = (float)deltax;
	//	temp = posx - lastMousePosX;
		mouseDeltaX.ForceUpdate(&temp, 1);
		temp = (float) deltay;
	//	temp = posy - lastMousePosY;
		mouseDeltaY.ForceUpdate(&temp, 1);
	
	
		if (wheel == 999)
			wheel = 0;
		if (wheel < 0)
			wheeldown = true;
		else if (wheel > 0)
			wheelup = true;
	
		mouseWheelDelta.Update (&wheel,1);
	
		int button_state = (buttons&0x01) ? 1 : -1;
		mouseButtonGroup[0].Update(&button_state, 1);
	
		button_state = (buttons&0x02) ? 1 : -1;
		mouseButtonGroup[1].Update(&button_state, 1);
	
		button_state = (buttons&0x04) ? 1 : -1;
		mouseButtonGroup[2].Update(&button_state, 1);
	
		button_state = (buttons&0x08) ? 1 : -1;
		mouseButtonGroup[3].Update(&button_state, 1);
	
		button_state = (buttons&0x10) ? 1 : -1;
		mouseButtonGroup[4].Update(&button_state, 1);
	}
	controlMask = 1<<control_mode;


	//
	//-----------------------------------------------------------------------
	// Read the button states for the active buttons.  For each one found,
	// figure out where it is in the array, and thus find the virtual keycode
	// to check
	//-----------------------------------------------------------------------
	//
	if (!m_ChatMode)
	{
		Check_Object(Application::GetInstance());
		if(Application::GetInstance()->applicationMode == Application::NormalGameMode)
		{
			ButtonIterator buttons(&activeButtons);
			ControlsUpdateManagerOf<int>* button;
			while ((button = buttons.ReadAndNext()) != NULL)
			{
				if (m_ChatMode)					// just entered it
					break;
				if (m_ListChanged)
				{
					m_ListChanged = false;			// the mappings have changed under it.
					return;
				}
				Check_Object(button);
				int key = button - virtualButtonGroup;
				Verify(static_cast<unsigned>(key) < ELEMENTS(virtualButtonGroup));
				DWORD status;
				switch (key)
				{
				case MOUSE_WHEEL_UP:
					if (wheelup)
						status = KEY_PRESSED;
					else
						status = KEY_FREE;
					break;
				case MOUSE_WHEEL_DOWN:
					if (wheeldown)
						status = KEY_PRESSED;
					else
						status = KEY_FREE;
					break;
				case MOUSEX_LEFT:
					if (mousex_left)
						status = KEY_PRESSED;
					else
						status = KEY_FREE;
					break;
				case MOUSEX_RIGHT:
					if (mousex_right)
						status = KEY_PRESSED;
					else
						status = KEY_FREE;
					break;
				case MOUSEY_UP:
					if (mousey_up)
						status = KEY_PRESSED;
					else
						status = KEY_FREE;
					break;
				case MOUSEY_DOWN:
					if (mousey_down)
						status = KEY_PRESSED;
					else
						status = KEY_FREE;
					break;
				case JOYX_LEFT:
					if (joyx_left)
						status = KEY_PRESSED;
					else
						status = KEY_FREE;
					break;
				case JOYX_RIGHT:
					if (joyx_right)
						status = KEY_PRESSED;
					else
						status = KEY_FREE;
					break;
				case JOYY_UP:
					if (joyy_up)
						status = KEY_PRESSED;
					else
						status = KEY_FREE;
					break;
				case JOYY_DOWN:
					if (joyy_down)
						status = KEY_PRESSED;
					else
						status = KEY_FREE;
					break;
				case JOYRUDDER_LEFT:
					if (joyrudder_left)
						status = KEY_PRESSED;
					else
						status = KEY_FREE;
					break;
				case JOYRUDDER_RIGHT:
					if (joyrudder_right)
						status = KEY_PRESSED;
					else
						status = KEY_FREE;
					break;
				case JOYTHROTTLE_UP:
					if (joythrottle_up)
						status = KEY_PRESSED;
					else
						status = KEY_FREE;
					break;
				case JOYTHROTTLE_DOWN:
					if (joythrottle_down)
						status = KEY_PRESSED;
					else
						status = KEY_FREE;
					break;
				case HAT_LEFT:
					if (hat_left)
						status = KEY_PRESSED;
					else
						status = KEY_FREE;
					break;
				case HAT_RIGHT:
					if (hat_right)
						status = KEY_PRESSED;
					else
						status = KEY_FREE;
					break;
				case HAT_UP:
					if (hat_up)
						status = KEY_PRESSED;
					else
						status = KEY_FREE;
					break;
				case HAT_DOWN:
					if (hat_down)
						status = KEY_PRESSED;
					else
						status = KEY_FREE;
					break;
				default:
					status = gos_GetKeyStatus(static_cast<gosEnum_KeyIndex>(key));
					break;
				}
				if (status == KEY_FREE)
				{
					if (m_ClearingChatEnter && (static_cast<gosEnum_KeyIndex>(key) == KEY_RETURN))
					{
						m_ClearingChatEnter = false;
					}
					else if (m_ClearingChatEscape && (static_cast<gosEnum_KeyIndex>(key) == KEY_ESCAPE))
					{
						m_ClearingChatEscape = false;
					}
					else
					{
						key = -key;
						button->Update(&key, AlwaysActive);
					}
				}
				else
				{
					if (m_ClearingChatEnter && (static_cast<gosEnum_KeyIndex>(key) == KEY_RETURN))
					{
					}
					else if (m_ClearingChatEscape && (static_cast<gosEnum_KeyIndex>(key) == KEY_ESCAPE))
					{
					}
					else
					{
						button->Update(&key, controlMask);
					}
				}
			}

			//
			//-------------------------
			// Read the keyboard stream
			//-------------------------
			//
			int keypress = (int)(gos_GetKey()&255);
			if (keypress != 0)
			{
				pressAnyKey = true;
				systemKeyboard.Update(&keypress, controlMask);
			}
		}

	}
	else
	{
		if (m_ChatInterface.GetCurrent ())
		{
			Check_Object (m_ChatInterface.GetCurrent ());
			DWORD key;
			while ((key = gos_GetKey()) != 0)
			{
				if (m_ChatInterface.GetCurrent ())
					m_ChatInterface.GetCurrent ()->pushChatKey (key);
			}
		}
		else
		{
			LeaveChatMode ();
		}
	}
}
void ControlsManager::EnterChatMode (Interface *dest)
{
	Check_Object(Application::GetInstance());
	if(Application::GetInstance()->applicationMode == Application::NormalGameMode)
	{
		ButtonIterator buttons(&activeButtons);
		ControlsUpdateManagerOf<int>* button;
		while ((button = buttons.ReadAndNext()) != NULL)
		{
			Check_Object(button);
			int key = button - virtualButtonGroup;
			Verify(static_cast<unsigned>(key) < ELEMENTS(virtualButtonGroup));
			key = -key;
			button->Update(&key, AlwaysActive);
		}
	}

	m_ChatMode = true;
	if (m_ChatInterface.GetCurrent ())
		m_ChatInterface.Remove ();
	m_ChatInterface.Add (dest);
}
void ControlsManager::LeaveChatMode (void)
{
	if (m_ChatInterface.GetCurrent ())
		m_ChatInterface.Remove ();
	m_ChatMode = false;
	m_ClearingChatEnter = true;
	m_ClearingChatEscape = true;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void ControlsManager::Remap (Entity *entity_to_control,Entity::AttributeID attribute_ID,Receiver *receiver,MessageID message,Stuff::Plug *owner,int control_mask,int group,int element,bool invert,int nameid,int type)
{
	Check_Object(this);
	Check_Object(owner);

	Remove (attribute_ID,message);
	Remove (group,element,control_mask);
	CreateMapping (entity_to_control,attribute_ID,receiver,message,owner,control_mask,group,element,invert,nameid,type);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void ControlsManager::CreateMapping(Entity *entity_to_control,Entity::AttributeID attribute_ID,Receiver *receiver,MessageID message,Plug *owner,int control_mask,int group,int element,bool invert,int nameid,int type)
{
	Check_Object(this);
	Check_Object(owner);

	m_AllMappings.push_back (ControlData (attribute_ID,message,control_mask,group,element,owner,invert,nameid,type));
	//
	//------------------------------------------------------------------
	// If this is a direct mapping, get the attribute we will be routing
	// input into
	//------------------------------------------------------------------
	//
	if (entity_to_control != NULL)
	{
		//
		//--------------------------------------------------------------------
		// Figure out which group we will be creating the mapping from.  If it
		// is to a joystick group, make sure that the stick exists and has
		// sufficient capabilities
		//--------------------------------------------------------------------
		//
		Check_Object(entity_to_control);
		switch (group)
		{
		case JoystickAxisGroupID:
			if (systemJoystick)
			{
				Check_Object(systemJoystick);
				if (
					static_cast<unsigned>(element) < Joystick::AxisCount
					 && systemJoystick->HasAxis(element)
				)
					joystickAxisGroup[element].Add(
						control_mask,
						entity_to_control,
						attribute_ID,
						ScalarClassID,
						owner,
						invert
					);
			}
			break;

		case JoystickButtonGroupID:
			if (systemJoystick)
			{
				Check_Object(systemJoystick);
				if (static_cast<unsigned>(element) < systemJoystick->buttonCount)
					joystickButtonGroup[element].Add(
						control_mask,
						entity_to_control,
						attribute_ID,
						IntClassID,
						owner,
						false
					);
			}
			break;

		case JoystickHatID:
			if (systemJoystick)
			{
				Check_Object(systemJoystick);
				if (systemJoystick->HasHat())
				{
					// To support old pilot options.mw4
					if (static_cast<unsigned>(element) == Joystick::HatAxis)
						joystickAxisGroup[Joystick::HatAxis].Add(
							control_mask,
							entity_to_control,
							attribute_ID,
							ScalarClassID,
							owner,
							invert
						);
				}
			}
			break;

		//
		//-----------------------
		// Add the mouse mappings
		//-----------------------
		//
		case MousePosXID:
			Check_Object(&mousePosX);
			mousePosX.Add(
				control_mask,
				entity_to_control,
				attribute_ID,
				ScalarClassID,
				owner,
				invert
			);
			break;

		case MousePosYID:
			Check_Object(&mousePosY);
			mousePosY.Add(
				control_mask,
				entity_to_control,
				attribute_ID,
				ScalarClassID,
				owner,
				invert
			);
			break;

		case MouseDeltaXID:
			Check_Object(&mouseDeltaX);
			mouseDeltaX.Add(
				control_mask,
				entity_to_control,
				attribute_ID,
				ScalarClassID,
				owner,
				invert
			);
			break;

		case MouseDeltaYID:
			Check_Object(&mouseDeltaY);
			mouseDeltaY.Add(
				control_mask,
				entity_to_control,
				attribute_ID,
				ScalarClassID,
				owner,
				invert
			);
			break;

		case MouseWheelDeltaID:
			Check_Object(&mouseWheelDelta);
			mouseWheelDelta.Add(
				control_mask,
				entity_to_control,
				attribute_ID,
				IntClassID,
				owner,
				false
			);
			break;

		case MouseButtonGroupID:
			Verify(static_cast<unsigned>(element) < ELEMENTS(mouseButtonGroup));
			mouseButtonGroup[element].Add(
				control_mask,
				entity_to_control,
				attribute_ID,
				IntClassID,
				owner,
				false
			);
			break;

		//
		//-----------------------------------
		// Add the keyboard 'button' mappings
		//-----------------------------------
		//
		case VirtualButtonGroupID:
			Verify(static_cast<unsigned>(element) < ELEMENTS(virtualButtonGroup));
			
			virtualButtonGroup[element].Add(
				control_mask,
				entity_to_control,
				attribute_ID,
				IntClassID,
				owner,
				false
			);
			
			ActivateButton(element);

			break;

		//
		//---------------------------------
		// Add the keyboard stream mappings
		//---------------------------------
		//
		case SystemKeyboardID:
			SPEW((0, "Direct mappings not advisable for keyboard!"));
			systemKeyboard.Add(
				control_mask,
				entity_to_control,
				attribute_ID,
				IntClassID,
				owner,
				false
			);
			break;

		default:
			STOP(("Unknown mapping group!\n"));
			break;
		}
	}

	//
	//-------------------------------------------------------------
	// Otherwise, it is an event mapping, so extract the message ID
	//-------------------------------------------------------------
	//
	else
	{
		//
		//--------------------------------------------------------------------
		// Figure out which group we will be creating the mapping from.  If it
		// is to a joystick group, make sure that the stick exists and has
		// sufficient capabilities
		//--------------------------------------------------------------------
		//
		Check_Object(receiver);
		switch (group)
		{
		case JoystickAxisGroupID:
			SPEW((0, "Event mappings not advisable for joystick axes!"));
			if (systemJoystick)
			{
				Check_Object(systemJoystick);
				if (
					static_cast<unsigned>(element) < Joystick::AxisCount
					 && systemJoystick->HasAxis(element)
				)
					joystickAxisGroup[element].Add(
						control_mask,
						receiver,
						message,
						owner
					);
			}
			break;

		case JoystickButtonGroupID:
			if (systemJoystick)
			{
				Check_Object(systemJoystick);
				if (static_cast<unsigned>(element) < systemJoystick->buttonCount)
					joystickButtonGroup[element].Add(
						control_mask,
						receiver,
						message,
						owner
					);
			}
			break;

		case JoystickHatID:
			if (systemJoystick)
			{
				Check_Object(systemJoystick);
				if (systemJoystick->HasHat())
				{
					Check_Object(joystickHat);
					if (static_cast<unsigned>(element) < 4)
						joystickHat[element].Add(
							control_mask,
							receiver,
							message,
							owner
						);
				}
			}
			break;

		//
		//-----------------------
		// Add the mouse mappings
		//-----------------------
		//
		case MousePosXID:
			mousePosX.Add(
				control_mask,
				receiver,
				message,
				owner
			);
			break;

		case MousePosYID:
			mousePosY.Add(
				control_mask,
				receiver,
				message,
				owner
			);
			break;

		case MouseDeltaXID:
			mouseDeltaX.Add(
				control_mask,
				receiver,
				message,
				owner
			);
			break;

		case MouseDeltaYID:
			mouseDeltaY.Add(
				control_mask,
				receiver,
				message,
				owner
			);
			break;

		case MouseWheelDeltaID:
			mouseWheelDelta.Add(
				control_mask,
				receiver,
				message,
				owner
			);
			break;

		case MouseButtonGroupID:
			Verify(static_cast<unsigned>(element) < ELEMENTS(mouseButtonGroup));
			mouseButtonGroup[element].Add(
				control_mask,
				receiver,
				message,
				owner
			);
			break;

		//
		//-----------------------------------
		// Add the keyboard 'button' mappings
		//-----------------------------------
		//
		case VirtualButtonGroupID:
			Verify(static_cast<unsigned>(element) < ELEMENTS(virtualButtonGroup));
			Verify(static_cast<unsigned>(element) > 0);
			virtualButtonGroup[element].Add(
				control_mask,
				receiver,
				message,
				owner
			);
			ActivateButton(element);
			break;

		//
		//---------------------------------
		// Add the keyboard stream mappings
		//---------------------------------
		//
		case SystemKeyboardID:
			systemKeyboard.Add(
				control_mask,
				receiver,
				message,
				owner
			);
			break;

		default:
			STOP(("Unknown mapping group!\n"));
			break;
		}
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void ControlsManager::ActivateButton(int button_num)
{
	Check_Object(this);
	Verify(static_cast<unsigned>(button_num) < ELEMENTS(virtualButtonGroup));
	ControlsUpdateManagerOf<int>* button = &virtualButtonGroup[button_num];
	Check_Object(button);

	//
	//-------------------------------------------------
	// Check to see if this button is already activated
	//-------------------------------------------------
	//
	if (!activeButtons.IsPlugMember(button))
		activeButtons.Add(button);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	ControlsManager::TestInstance()
{
	Verify(IsDerivedFrom(DefaultData));
}

