//===========================================================================// // File: controls.hpp // //---------------------------------------------------------------------------// // Date Who Modification // // -------- --- -----------------------------------------------------------// // 12/12/94 CPB Initial coding. // // 01/25/95 CPB Major surgery! Removed Entities, added Receivers. // // 08/25/97 JMA Infrastructure changes // // 08/25/97 ECH Infrastructure changes // //---------------------------------------------------------------------------// // Copyright (C) 1995-97, FASA Interactive. All rights reserved // // PROPRIETARY and CONFIDENTIAL // //===========================================================================// #pragma once #include "Adept.hpp" #include "Receiver.hpp" #include "Entity.hpp" #pragma warning (push) #include #pragma warning (pop) namespace Adept { class Controls; class ControlsInstance; class ControlsMappingGroup; class ControlsManager; class Joystick; class Interface; enum { MOUSE_WHEEL_DOWN=512, MOUSE_WHEEL_UP, MOUSEX_LEFT, MOUSEX_RIGHT, MOUSEY_UP, MOUSEY_DOWN, JOYX_LEFT, JOYX_RIGHT, JOYY_UP, JOYY_DOWN, JOYRUDDER_LEFT, JOYRUDDER_RIGHT, JOYTHROTTLE_UP, JOYTHROTTLE_DOWN, HAT_LEFT, HAT_RIGHT, HAT_UP, HAT_DOWN, LAST_AXIS_MAPID }; struct ControlData { // MSL 5.05 MFD Comm enum { Move_Control, Fire_Control, Misc_Control, Lancemate_Control, Comm_Control }; enum { FirstDevice, Keyboard = FirstDevice, Mouse, Joystick, LastDevice = Joystick }; Entity::AttributeID attr_id; Receiver::MessageID mesg_id; Plug *owner; int control_mask; int group; int element; int nameresid; int control_type; bool invert; ControlData () { attr_id = 0; mesg_id = 0; owner = NULL; control_mask = group = element = nameresid = control_type = 0; invert = false; } ControlData (const Entity::AttributeID& p1,const Receiver::MessageID& p2,int p3,int p4,int p5,Plug *p6,bool p7,int p8,int p9) { attr_id = p1; mesg_id = p2; control_mask = p3; group = p4; element = p5; owner = p6; invert = p7; nameresid = p8; control_type = p9; } }; //######################################################################### //######################### ControlsInstance ############################## //######################################################################### // The ControlsInstance object exists to serve the ControlsMappingGroup // object. It maintains one instance of a mapping from a physical // input device to either an entity event message or a value. class _declspec(novtable) ControlsInstance : public Stuff::Plug { friend class ControlsMappingGroup; friend class ControlsManager; // required for testing friend class L4MappableButtonManager; public: static void InitializeClass(); static void TerminateClass(); public: ControlsInstance(ClassData *class_data,int control_mask,Stuff::Plug *dependant); ~ControlsInstance(); void TestInstance(); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class Data Support // public: static ClassData *DefaultData; int controlMask; // lots of objects (and templates) need access to this protected: virtual void Update(void *data_source)=0; Stuff::SlotOf dependantPlug; }; //######################################################################### //###################### DirectControlsInstance ########################### //######################################################################### class DirectControlsInstance: public ControlsInstance { friend class ControlsMappingGroup; friend class ControlsManager; // required for testing public: static void InitializeClass(); static void TerminateClass(); public: DirectControlsInstance( int control_mask, Entity *entity_to_control, Entity::AttributeID attribute_ID, RegisteredClass::ClassID attribute_type, Stuff::Plug *dependant, bool invert ); ~DirectControlsInstance(); void Update(void *data_source); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class Data Support // public: static ClassData *DefaultData; void TestInstance(); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Public Data // public: Entity *entity; AttributeEntry *attributeEntry; bool m_Invert; }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~EventControlsInstanceOf ~~~~~~~~~~~~~~~~~~ class EventControlsInstance: public ControlsInstance { friend class ControlsMappingGroup; friend class ControlsManager; // required for testing public: static void InitializeClass(); static void TerminateClass(); public: EventControlsInstance( ClassData *class_data, int control_mask, Receiver *receiver, Receiver::MessageID message_id, Stuff::Plug *dependant ); ~EventControlsInstance(); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class Data Support // public: static ClassData *DefaultData; void TestInstance(); Receiver *receiverPointer; Receiver::MessageID messageID; }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~EventControlsInstanceOf ~~~~~~~~~~~~~~~~~~ template class EventControlsInstanceOf: public EventControlsInstance { friend class ControlsMappingGroup; friend class ControlsManager; // required for testing public: EventControlsInstanceOf( int control_mask, Receiver *receiver, Receiver::MessageID message_id, Stuff::Plug *dependant ); ~EventControlsInstanceOf(); void Update(void *data_source); }; template EventControlsInstanceOf::EventControlsInstanceOf( int control_mask, Receiver *receiver, Receiver::MessageID message_id, Stuff::Plug *dependant ): EventControlsInstance( DefaultData, control_mask, receiver, message_id, dependant ) {} template EventControlsInstanceOf::~EventControlsInstanceOf() {} template void EventControlsInstanceOf::Update(void *data_source) { Check_Object(this); Check_Pointer(data_source); ReceiverDataMessageOf update_message( messageID, sizeof(ReceiverDataMessageOf), -1, ReceiverDataMessageOf::DefaultFlags, *Cast_Pointer(T*, data_source) ); Check_Object(receiverPointer); receiverPointer->Receive(&update_message); } //######################################################################### //######################### ControlsMappingGroup ########################## //######################################################################### // The ControlsMappingGroup object maintains a group of ControlInstances. // // ControlsMappingGroup.Update() will call ControlsInstance.Update() // for each instance in the group. class ControlsMappingGroup : public Stuff::Plug { friend class ControlsManager; // required for testing public: static void InitializeClass(); static void TerminateClass(); public: ControlsMappingGroup(); ~ControlsMappingGroup(); void TestInstance(); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class Data Support // public: static ClassData *DefaultData; void Add(ControlsInstance *mapping) { Check_Object(this); Check_Object(mapping); instanceList.Add(mapping); } virtual void Remove(int control_mask); virtual void Remove (const Entity::AttributeID& attr_id,const Receiver::MessageID& mesg_id); virtual void Update(void *value, int control_mask); bool CurrentFilterStatus(int control_mask); // returns true if at least one button active void RemoveAll() { ChainIteratorOf iterator(&instanceList); ControlsInstance *plug = NULL; while ((plug=iterator.GetCurrent()) != NULL) { iterator.Remove(); Unregister_Object(plug); delete plug; } } protected: Stuff::ChainOf instanceList; }; //######################################################################### //######################### ControlsUpdateManagerOf ####################### //######################################################################### template class ControlsUpdateManagerOf : public ControlsMappingGroup { public: ControlsUpdateManagerOf(); ~ControlsUpdateManagerOf(); virtual ControlsInstance* Add(int control_mask,Receiver *receiver_pointer,Receiver::MessageID id,Stuff::Plug *dependant); virtual ControlsInstance* Add(int control_mask,Entity *entity_to_control,Entity::AttributeID attribute_ID,RegisteredClass::ClassID attribute_type,Stuff::Plug *dependant,bool invert); enum { unmapped = 0, mappedByOthers = 1, mappedByMe = 2 }; virtual void Update(void *sourcePointer, int control_mask); void ForceUpdate(T *sourcePointer, int control_mask); T previousValue; }; template ControlsUpdateManagerOf::ControlsUpdateManagerOf() : ControlsMappingGroup() { } template ControlsUpdateManagerOf::~ControlsUpdateManagerOf() { } template void ControlsUpdateManagerOf::Update( void * source_pointer, int control_mask ) { Check_Object(this); Check_Pointer(source_pointer); if (previousValue != *Cast_Pointer(T*, source_pointer)) { ForceUpdate(Cast_Pointer(T*, source_pointer), control_mask); } } template void ControlsUpdateManagerOf::ForceUpdate( T* source_pointer, int control_mask ) { Check_Object(this); Check_Pointer(source_pointer); previousValue = *source_pointer; ControlsMappingGroup::Update(source_pointer, control_mask); } template ControlsInstance* ControlsUpdateManagerOf::Add( int control_mask, Receiver *receiver_pointer, Receiver::MessageID message_id, Stuff::Plug *dependant ) { Check_Object(this); Check_Object(receiver_pointer); EventControlsInstanceOf *instance = new EventControlsInstanceOf( control_mask, receiver_pointer, message_id, dependant ); Register_Object(instance); ControlsMappingGroup::Add(instance); return instance; } template ControlsInstance* ControlsUpdateManagerOf::Add( int control_mask, Entity *entity_to_control, Entity::AttributeID attribute_ID, RegisteredClass::ClassID attribute_type, Stuff::Plug *dependant, bool invert ) { Check_Object(this); DirectControlsInstance *instance = new DirectControlsInstance( control_mask, entity_to_control, attribute_ID, attribute_type, dependant, invert ); Register_Object(instance); ControlsMappingGroup::Add(instance); return instance; } //######################################################################### //############################ ControlsManager ############################ //######################################################################### //########################################################################## // The following classes must always be typedef'd or overriden by an // inheritor // typedef Receiver__ClassData ControlsManager__ClassData; typedef Receiver__Message ControlsManager__Message; class ControlsManager: public Receiver { public: friend class ControlsMappingGroup; // for access to groupEnable static void InitializeClass(); static void TerminateClass(); static ClassData *DefaultData; typedef ControlsManager__ClassData ClassData; typedef ControlsManager__Message Message; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Constructors // public: ControlsManager(); ~ControlsManager(); static ControlsManager *Instance; void Remove(int control_mask); int Remove(int group,int element,int control_mask); // return actual number removed int Remove (const Entity::AttributeID& attr_id,const MessageID& mesg_id); // return actual number removed void 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 ); // will remove old mapping and create a new one with this data, // all mappings refering to attribute_id, message, group, and element will be removed void RemoveAllMappings(); void Execute(); void CreateMapping( 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 ); //------------------------------------------------------------------- // Gauge support //------------------------------------------------------------------- void *activeDestination; Receiver *activeReceiver; Receiver::MessageID activeMessageID; Stuff::Plug *activeDependant; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Control Groups // public: enum { JoystickAxisGroupID, JoystickButtonGroupID, JoystickHatID, MousePosXID, MousePosYID, MouseDeltaXID, MouseDeltaYID, MouseWheelDeltaID, MouseButtonGroupID, VirtualButtonGroupID, SystemKeyboardID }; enum { JoystickButtonIDBase = 0x100 }; stlport::vector m_AllMappings; void SetJoystick (int id); void JoyStickShift (int value); bool m_ListChanged; bool m_IgnoreCommands; int m_JoyStickShiftButton; Joystick *systemJoystick; Adept::ControlsUpdateManagerOf *joystickAxisGroup; Adept::ControlsUpdateManagerOf *joystickButtonGroup; Adept::ControlsUpdateManagerOf *joystickHat; Adept::ControlsUpdateManagerOf mousePosX,mousePosY; Adept::ControlsUpdateManagerOf mouseDeltaX,mouseDeltaY; Adept::ControlsUpdateManagerOf mouseWheelDelta; Adept::ControlsUpdateManagerOf mouseButtonGroup[5]; // new buttons void CenterMouse (void); void TowardsCenterMouse (Scalar amountx,Scalar amounty); Adept::ControlsUpdateManagerOf virtualButtonGroup[LAST_AXIS_MAPID]; Adept::ControlsUpdateManagerOf systemKeyboard; void ActivateButton(int button); enum { PlainKeyMode, ShiftMode=1, CtrlMode=2, AltMode=4, CtrlShiftMode=ShiftMode|CtrlMode, ShiftAltMode=ShiftMode|AltMode, CtrlAltMode=CtrlMode|AltMode, CtrlShiftAltMode=ShiftMode|CtrlMode|AltMode }; enum { PlainFlag = 1< m_ChatInterface; void EnterChatMode (Interface *dest); void LeaveChatMode (void); static bool TestClass(); void TestInstance(); protected: Stuff::ChainOf< Adept::ControlsUpdateManagerOf* > activeButtons; typedef Stuff::ChainIteratorOf< Adept::ControlsUpdateManagerOf* > ButtonIterator; }; }