Files
firestorm/Gameleap/code/mw4/Libraries/Adept/Controls.hpp
T
Cyd 2b8ca921cb Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS
Complete disaster-recovery snapshot: engine/game source, game data assets,
VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive.
Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false,
no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
2026-06-24 21:28:16 -05:00

654 lines
16 KiB
C++

//===========================================================================//
// 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 <stlport\vector>
#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<Stuff::Plug*> 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 T> 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 <class T> EventControlsInstanceOf<T>::EventControlsInstanceOf(
int control_mask,
Receiver *receiver,
Receiver::MessageID message_id,
Stuff::Plug *dependant
):
EventControlsInstance(
DefaultData,
control_mask,
receiver,
message_id,
dependant
)
{}
template <class T> EventControlsInstanceOf<T>::~EventControlsInstanceOf()
{}
template <class T> void EventControlsInstanceOf<T>::Update(void *data_source)
{
Check_Object(this);
Check_Pointer(data_source);
ReceiverDataMessageOf<T>
update_message(
messageID,
sizeof(ReceiverDataMessageOf<T>),
-1,
ReceiverDataMessageOf<T>::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<ControlsInstance *> iterator(&instanceList);
ControlsInstance *plug = NULL;
while ((plug=iterator.GetCurrent()) != NULL)
{
iterator.Remove();
Unregister_Object(plug);
delete plug;
}
}
protected:
Stuff::ChainOf<ControlsInstance*> instanceList;
};
//#########################################################################
//######################### ControlsUpdateManagerOf #######################
//#########################################################################
template <class T> 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 <class T>
ControlsUpdateManagerOf<T>::ControlsUpdateManagerOf()
: ControlsMappingGroup()
{
}
template <class T> ControlsUpdateManagerOf<T>::~ControlsUpdateManagerOf()
{
}
template <class T> void
ControlsUpdateManagerOf<T>::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 <class T> void
ControlsUpdateManagerOf<T>::ForceUpdate(
T* source_pointer,
int control_mask
)
{
Check_Object(this);
Check_Pointer(source_pointer);
previousValue = *source_pointer;
ControlsMappingGroup::Update(source_pointer, control_mask);
}
template <class T> ControlsInstance*
ControlsUpdateManagerOf<T>::Add(
int control_mask,
Receiver *receiver_pointer,
Receiver::MessageID message_id,
Stuff::Plug *dependant
)
{
Check_Object(this);
Check_Object(receiver_pointer);
EventControlsInstanceOf<T> *instance =
new EventControlsInstanceOf<T>(
control_mask,
receiver_pointer,
message_id,
dependant
);
Register_Object(instance);
ControlsMappingGroup::Add(instance);
return instance;
}
template <class T> ControlsInstance*
ControlsUpdateManagerOf<T>::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<ControlData> m_AllMappings;
void SetJoystick (int id);
void JoyStickShift (int value);
bool m_ListChanged;
bool m_IgnoreCommands;
int m_JoyStickShiftButton;
Joystick *systemJoystick;
Adept::ControlsUpdateManagerOf<Stuff::Scalar> *joystickAxisGroup;
Adept::ControlsUpdateManagerOf<int> *joystickButtonGroup;
Adept::ControlsUpdateManagerOf<int> *joystickHat;
Adept::ControlsUpdateManagerOf<float> mousePosX,mousePosY;
Adept::ControlsUpdateManagerOf<float> mouseDeltaX,mouseDeltaY;
Adept::ControlsUpdateManagerOf<int> mouseWheelDelta;
Adept::ControlsUpdateManagerOf<int> mouseButtonGroup[5]; // new buttons
void CenterMouse (void);
void TowardsCenterMouse (Scalar amountx,Scalar amounty);
Adept::ControlsUpdateManagerOf<int> virtualButtonGroup[LAST_AXIS_MAPID];
Adept::ControlsUpdateManagerOf<int> 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<<PlainKeyMode,
ShiftFlag = 1<<ShiftMode,
CtrlFlag = 1<<CtrlMode,
AltFlag = 1<<AltMode,
CtrlShiftFlag = 1<<CtrlShiftMode,
ShiftAltFlag = 1<<ShiftAltMode,
CtrlAltFlag = 1<<CtrlAltMode,
CtrlShiftAltFlag = 1<<CtrlShiftAltMode,
AlwaysActive = 0xFFFF
};
int controlMask;
bool pressAnyKey;
bool m_ChatMode;
bool m_ClearingChatEnter;
bool m_ClearingChatEscape;
bool GetPressAnyKey()
{
return pressAnyKey;
}
void ClearPressAnyKey()
{
pressAnyKey = false;
}
SlotOf <Interface *> m_ChatInterface;
void EnterChatMode (Interface *dest);
void LeaveChatMode (void);
static bool
TestClass();
void
TestInstance();
protected:
Stuff::ChainOf< Adept::ControlsUpdateManagerOf<int>* >
activeButtons;
typedef
Stuff::ChainIteratorOf< Adept::ControlsUpdateManagerOf<int>* >
ButtonIterator;
};
}