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.
654 lines
16 KiB
C++
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;
|
|
};
|
|
|
|
}
|
|
|
|
|