Files
firestorm/Gameleap/code/mw4/Libraries/Adept/control_mapping.cpp
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

1536 lines
39 KiB
C++

#include "AdeptHeaders.hpp"
#include "control_mapping.hpp"
#include "Tool.hpp"
#include "Joystick.hpp"
#include "interface.hpp"
#include "missionlang\resource.h"
extern int g_bUseOrgJoy; // jcem
namespace Adept
{
CControlMappingList *g_ControlList=NULL;
}
CControlMappingList::CControlMappingList (const char *filename,Entity::ClassData *classdata)
{
m_Mappings.clear ();
m_nCount = 0;
m_pcdHead = NULL;
m_fInvertJoyY = false;
m_fInvertMouseY = true;
m_Joystick = 0;
m_joyStickAllowed = true;
m_mouseAllowed = false;
m_joystickButtons = 0;
m_joyStickShiftValue = -1;
m_ForceFeedBack = true;
m_MouseSensitivity = 0.25f;
m_JoystickXAxisType = TURNING_AXIS;
m_JoystickRudderAxisType = TORSO_AXIS;
m_MouseXAxisType = TURNING_AXIS;
InitializeThrottleConstants();
LoadList (filename,classdata);
}
CControlMappingList::CControlMappingList (const ResourceID& control_stream)
{
m_Mappings.clear ();
m_nCount = 0;
m_pcdHead = NULL;
m_fInvertJoyY = false;
m_fInvertMouseY = true;
m_Joystick = 0;
m_joyStickAllowed = true;
m_mouseAllowed = false;
m_joystickButtons = 0;
m_joyStickShiftValue = -1;
m_ForceFeedBack = true;
m_MouseSensitivity = 0.25f;
m_JoystickXAxisType = TURNING_AXIS;
m_JoystickRudderAxisType = TORSO_AXIS;
m_MouseXAxisType = TURNING_AXIS;
InitializeThrottleConstants();
LoadList (control_stream);
}
CControlMappingList::CControlMappingList (void)
{
m_Mappings.clear ();
m_nCount = 0;
m_pcdHead = NULL;
m_fInvertJoyY = false;
m_fInvertMouseY = true;
m_Joystick = 0;
m_joyStickAllowed = true;
m_mouseAllowed = false;
m_joystickButtons = 0;
m_joyStickShiftValue = -1;
m_ForceFeedBack = true;
m_MouseSensitivity = 0.25f;
m_JoystickXAxisType = TURNING_AXIS;
m_JoystickRudderAxisType = TORSO_AXIS;
m_MouseXAxisType = TURNING_AXIS;
InitializeThrottleConstants();
}
CControlMappingList::~CControlMappingList (void)
{
if (m_pcdHead)
{
delete[] m_pcdHead;
m_pcdHead = NULL;
}
}
void CControlMappingList::SaveList (MemoryStream& resource_locker)
{
stlport::vector<ControlData>::iterator iter;
resource_locker << m_Joystick;
resource_locker << m_ForceFeedBack;
resource_locker << m_MouseSensitivity;
resource_locker << m_joyStickShiftValue;
resource_locker << m_mouseAllowed;
resource_locker << m_JoystickXAxisType;
resource_locker << m_JoystickRudderAxisType;
resource_locker << m_MouseXAxisType;
// Can't save in options.mw4 file, save in options.ini file instead
#if 0
resource_locker << m_joystick_throttle_center;
resource_locker << m_joystick_throttle_dead_low;
resource_locker << m_joystick_throttle_dead_high;
#else
NotationFile startup_ini("options.ini", NotationFile::Standard, true);
Stuff::Page *joypage = startup_ini.FindPage("joystick");
if (!joypage)
{
startup_ini.AddPage("joystick");
}
// if (g_bUseOrgJoy) { // jcem
if (Close_Enough(m_joystick_throttle_center, m_joystick_throttle_dead_low))
joypage->SetEntry("OneWayThrottle", true);
else
joypage->SetEntry("OneWayThrottle", false);
// }
startup_ini.Save();
#endif
resource_locker << m_Mappings.size ();
for (iter = m_Mappings.begin ();iter != m_Mappings.end ();iter++)
{
resource_locker.WriteBytes (&(*iter),sizeof (*iter));
}
}
void CControlMappingList::SaveList (const ResourceID& control_stream)
{
Check_Object (ControlsManager::Instance);
Resource resource_locker(control_stream);
SaveList (resource_locker);
}
void CControlMappingList::LoadList (MemoryStream& resource_locker)
{
m_Mappings.clear ();
gos_PushCurrentHeap(Adept::g_Heap);
int mapping_count;
resource_locker >> m_Joystick;
resource_locker >> m_ForceFeedBack;
resource_locker >> m_MouseSensitivity;
resource_locker >> m_joyStickShiftValue;
resource_locker >> m_mouseAllowed;
resource_locker >> m_JoystickXAxisType;
resource_locker >> m_JoystickRudderAxisType;
resource_locker >> m_MouseXAxisType;
// Load from options.ini file instead
#if 0
resource_locker >> m_joystick_throttle_center;
resource_locker >> m_joystick_throttle_dead_low;
resource_locker >> m_joystick_throttle_dead_high;
#else
NotationFile startup_ini("options.ini", NotationFile::Standard, true);
Stuff::Page *joypage = startup_ini.FindPage("joystick");
if (joypage)
{
bool bOneWay = false;
// if (g_bUseOrgJoy) { // jcem
joypage->GetEntry("OneWayThrottle", &bOneWay);
// }
if (bOneWay) {
joypage->GetEntry("OneThrottleCenter", &m_joystick_throttle_center);
joypage->GetEntry("OneThrottleCenter", &m_joystick_throttle_dead_low);
joypage->GetEntry("OneThrottleHigh", &m_joystick_throttle_dead_high);
}
else {
// if (g_bUseOrgJoy) { // jcem
joypage->GetEntry("BiThrottleCenter", &m_joystick_throttle_center);
joypage->GetEntry("BiThrottleLow", &m_joystick_throttle_dead_low);
joypage->GetEntry("BiThrottleHigh", &m_joystick_throttle_dead_high);
// } else { // jcem
// m_joystick_throttle_center = 0.3;
// m_joystick_throttle_dead_low = 0.025;
// m_joystick_throttle_dead_high = 0.025;
// }
}
}
#endif
if (m_Joystick >= gosJoystick_CountJoysticks (false))
{
m_Joystick = 0;
m_joystickButtons = 0;
}
if (m_joystickButtons == 0 && gosJoystick_CountJoysticks(false) > 0)
{
gosJoystick_Info ji;
memset(&ji,0,sizeof(ji));
gosJoystick_GetInfo(m_Joystick, &ji);
m_joystickButtons = ji.nButtons;
}
resource_locker >> mapping_count;
const ControlData *mapping = Cast_Pointer(const ControlData*,resource_locker.GetPointer());
m_Mappings.reserve (mapping_count);
for (int i=0; i<mapping_count; ++i, ++mapping)
{
#ifndef LAB_ONLY // in release build remove no string mapping command, these should only be debug command
if (mapping->nameresid == 0)
continue;
#endif
m_Mappings.push_back (*mapping);
}
gos_PopCurrentHeap();
GetInvertStateOfList();
}
void CControlMappingList::LoadList (const ResourceID& control_stream)
{
m_Mappings.clear ();
Resource resource_locker(control_stream);
LoadList (resource_locker);
}
void CControlMappingList::LoadDefault (void)
{
m_Joystick = 0;
m_mouseAllowed = false;
int count = gosJoystick_CountJoysticks (false);
if (count)
{
gosJoystick_Info info;
gosJoystick_GetInfo (m_Joystick,&info);
m_joyStickShiftValue = info.nButtons-1;
if (m_joyStickShiftValue < 8)
{
m_joyStickShiftValue = -1;
}
}
else
{
m_joyStickShiftValue = -1;
}
m_ForceFeedBack = true;
m_MouseSensitivity = 0.02f;
m_JoystickXAxisType = TURNING_AXIS;
m_JoystickRudderAxisType = TORSO_AXIS;
m_MouseXAxisType = TURNING_AXIS;
InitializeThrottleConstants();
m_Mappings.clear ();
gos_PushCurrentHeap(Adept::g_Heap);
FillDefault(m_Mappings);
gos_PopCurrentHeap();
// Resource res ("content\\Interfaces\\Common\\interface.control");
// res.LoadData ();
// Verify (res.DoesResourceExist ());
// LoadList (res);
}
int CControlMappingList::GetList(bool fRestoreDefaults)
{
if (fRestoreDefaults)
{
m_Mappings.clear ();
gos_PushCurrentHeap(Adept::g_Heap);
FillDefault(m_Mappings);
gos_PopCurrentHeap();
}
stlport::vector<ControlData>::iterator iter;
for (iter = m_Mappings.begin ();iter != m_Mappings.end ();iter++)
{
if (iter->mesg_id != 0)
{
if ((iter->group == ControlsManager::VirtualButtonGroupID) && ((iter->element == MOUSE_WHEEL_UP)||(iter->element == MOUSE_WHEEL_DOWN)))
iter->group = ControlsManager::MouseButtonGroupID;
}
}
// Calculate worst-case size of array
m_nCount = 0;
for (iter = m_Mappings.begin ();iter != m_Mappings.end (); iter++)
{
//
//If this is a Direct command (0 == mesg_id) then we ignore it, UI doesn't allow remapping axes...
//
if (iter->mesg_id && (iter->group == ControlsManager::JoystickButtonGroupID
|| iter->group == ControlsManager::MouseButtonGroupID
|| iter->group == ControlsManager::VirtualButtonGroupID
|| iter->group == ControlsManager::JoystickHatID) )
{
m_nCount++;
}
}
//
// Allocate and clear control array
// This is allocated to + 1 and cleared to zero to allow for an end-of-list object.
// It would be far better to maintain a new list size, but we're approaching ZBR, so I'll refrain from
// casual changes.
//
delete[] m_pcdHead;
m_pcdHead = new ControlDef[m_nCount + 1]; //BUGBUG:DAN - make this use constructor/destructor instead
memset(m_pcdHead, 0, (m_nCount + 1) * sizeof(ControlDef));
ControlDef *pcdPtr;
for (iter = m_Mappings.begin ();iter != m_Mappings.end (); iter++)
{
//
//If this is a Direct command (0 == mesg_id) then we ignore it, UI doesn't allow remapping axes...
//
if (iter->mesg_id)
{
//
//Search list of control defs to see if command with this mesg_id already exists. We do this
//because each command will have three entries in the vector, one for key/mouse/joy and the order
//these items are stored in the vector isn't guaranteed. The code that interacts with gosScript
//wants all the info for a particular command (unique mesg_id) in one place.
//
pcdPtr = m_pcdHead;
while (pcdPtr->mesg_id && pcdPtr->mesg_id != iter->mesg_id)
{
pcdPtr++;
}
//
//Determine type of command being iterated and save the key/joy/mouse id (iter->element)
//
bool skip = false;
switch (iter->group)
{
case ControlsManager::MouseButtonGroupID:
if (!pcdPtr->cd_mouse_valid)
{
pcdPtr->nMouse = iter->element;
pcdPtr->cd_mouse = *iter;
pcdPtr->cd_mouse_valid = true;
break;
}
skip = true;
break;
case ControlsManager::VirtualButtonGroupID:
if (!pcdPtr->cd_key_valid)
{
pcdPtr->nKey = iter->element;
pcdPtr->control_mask = iter->control_mask;
pcdPtr->cd_key = *iter;
pcdPtr->cd_key_valid = true;
break;
}
skip = true;
break;
case ControlsManager::JoystickButtonGroupID:
if (!pcdPtr->cd_joy_valid)
{
pcdPtr->nJoy = iter->element;
pcdPtr->cd_joy = *iter;
pcdPtr->cd_joy_valid = true;
break;
}
skip = true;
break;
case ControlsManager::JoystickHatID:
if (!pcdPtr->cd_joy_valid)
{
pcdPtr->nJoy = iter->element+10;
pcdPtr->cd_joy = *iter;
pcdPtr->cd_joy_valid = true;
break;
}
skip = true;
break;
default:
skip = true;
break;
}
if (!skip)
{
//
//If this is the first vector entry for this command, save the common info
//
if (!pcdPtr->mesg_id)
{
pcdPtr->mesg_id = iter->mesg_id;
pcdPtr->nameresid = iter->nameresid;
pcdPtr->control_type = iter->control_type;
}
}
}
}
//
// Determine the size of the new list by looking for the end-of-list object (mesg_id == 0)
//
int nWho = 0;
pcdPtr = m_pcdHead;
while (pcdPtr->mesg_id)
{
pcdPtr->nIdx = nWho++; // BUGBUG:DAN Adjust for category offset
pcdPtr++;
}
m_nCount = nWho; // actual size of used elements in array
return m_nCount;
}
void CControlMappingList::JoystickXAxis (int value, Plug* owner)
{
Verify (value>=0);
Verify (value < 3);
m_JoystickXAxisType = value;
if (owner)
ApplyList (owner);
}
void CControlMappingList::JoystickRudderAxis (int value, Plug* owner)
{
Verify (value>=0);
Verify (value < 3);
m_JoystickRudderAxisType = value;
if (owner)
ApplyList (owner);
}
void CControlMappingList::MouseXAxis (int value, Plug* owner)
{
Verify (value>=0);
Verify (value < 3);
m_MouseXAxisType = value;
if (owner)
ApplyList (owner);
}
void CControlMappingList::ForceFeedBack (bool value, Plug* owner)
{
m_ForceFeedBack = value;
if (owner)
ApplyList (owner);
}
void CControlMappingList::MouseSensitivity (Scalar value, Plug* owner)
{
m_MouseSensitivity = value;
if (owner)
ApplyList (owner);
}
void CControlMappingList::Joystick(int id, Plug* owner)
{
m_Joystick = id;
gosJoystick_Info ji;
memset(&ji,0,sizeof(ji));
gosJoystick_GetInfo(id, &ji);
m_joystickButtons = ji.nButtons;
if (owner)
ApplyList(owner);
}
void CControlMappingList::SetJoyYInvert(bool b, Plug* owner)
{
m_fInvertJoyY = b;
SetInvertStateOfList();
if (owner)
ApplyList(owner);
}
void CControlMappingList::SetMouseYInvert(bool b, Plug* owner)
{
m_fInvertMouseY = b;
SetInvertStateOfList();
if (owner)
ApplyList(owner);
}
void CControlMappingList::SetMouseAllowed(bool b, Plug* owner)
{
m_mouseAllowed = b;
if (owner)
ApplyList(owner);
}
void CControlMappingList::SetJoyStickAllowed(bool b, Plug* owner)
{
m_joyStickAllowed = b;
if (owner)
ApplyList(owner);
}
int CControlMappingList::SetJoyStickShiftAllowed(bool b, Plug* owner, int* pIndex1, int* pIndex2)
{
int retCount = 0;
if (b)
{
int count = gosJoystick_CountJoysticks (false);
if (count)
{
gosJoystick_Info info;
gosJoystick_GetInfo (m_Joystick,&info);
m_joyStickShiftValue = info.nButtons-1;
if (m_joyStickShiftValue < 8)
{
m_joyStickShiftValue = -1;
}
}
else
{
m_joyStickShiftValue = -1;
}
retCount = SetJoyStickShiftValue(m_joyStickShiftValue, owner, pIndex1, pIndex2);
}
else
{
m_joyStickShiftValue = -1;
}
if (owner)
ApplyList(owner);
return retCount;
}
int CControlMappingList::SetJoyStickShiftValue(int n, Plug* owner, int* pChangeIndex1, int* pChangeIndex2)
{
m_joyStickShiftValue = n;
if (m_pcdHead == NULL)
GetList(false);
// Looking to unmap any use of this button (shifted or non-shifted)
int returnIndex[2];
int returnCount = 0;
for (int i = 0; i < m_nCount; i++)
{
if (m_pcdHead[i].cd_joy_valid && m_pcdHead[i].nJoy == m_joyStickShiftValue)
{
returnIndex[returnCount] = i;
returnCount++;
m_pcdHead[i].nJoy = 0;
m_pcdHead[i].cd_joy_valid = false;
m_pcdHead[i].cd_joy.element = 0;
m_pcdHead[i].cd_joy.control_mask = 0;
}
}
gosASSERT(returnCount <= 2);
SetList(owner);
*pChangeIndex1 = returnIndex[0];
*pChangeIndex2 = returnIndex[1];
return returnCount;
}
void CControlMappingList::JoyStickThrottleCenter(Stuff::Scalar s, Plug* owner)
{
m_joystick_throttle_center = s;
if (owner)
ApplyList(owner);
}
void CControlMappingList::JoyStickThrottleLow(Stuff::Scalar s, Plug* owner)
{
m_joystick_throttle_dead_low = s;
if (owner)
ApplyList(owner);
}
void CControlMappingList::JoyStickThrottleHigh(Stuff::Scalar s, Plug* owner)
{
m_joystick_throttle_dead_high = s;
if (owner)
ApplyList(owner);
}
void CControlMappingList::SetInvertStateOfList()
{
//
//Iterate vector and set correct inversion state for any joystick or mouse Y axes
//
stlport::vector<ControlData>::iterator iter;
for (iter = m_Mappings.begin (); iter != m_Mappings.end (); iter++)
{
if (0 == iter->mesg_id)
{
switch (iter->group)
{
case ControlsManager::JoystickAxisGroupID:
if (Joystick::YAxis == iter->element)
{
iter->invert = m_fInvertJoyY;
}
break;
case ControlsManager::MousePosYID:
case ControlsManager::MouseDeltaYID:
iter->invert = m_fInvertMouseY;
break;
}
}
}
}
void CControlMappingList::GetInvertStateOfList()
{
//
//Iterate vector and set correct inversion state for any joystick or mouse Y axes
//
stlport::vector<ControlData>::iterator iter;
bool joyInvertFound = false;
bool mouseInvertFound = false;
for (iter = m_Mappings.begin (); iter != m_Mappings.end (); iter++)
{
if (0 == iter->mesg_id)
{
switch (iter->group)
{
case ControlsManager::JoystickAxisGroupID:
if (Joystick::YAxis == iter->element)
{
m_fInvertJoyY = iter->invert;
joyInvertFound = true;
if (mouseInvertFound)
return;
}
break;
case ControlsManager::MousePosYID:
case ControlsManager::MouseDeltaYID:
{
m_fInvertMouseY = iter->invert;
mouseInvertFound = true;
if (joyInvertFound)
return;
}
break;
}
}
}
gosASSERT(mouseInvertFound);
gosASSERT(joyInvertFound);
}
void CControlMappingList::SetList(Plug* owner)
{
gosASSERT(m_pcdHead != NULL);
if (m_pcdHead == NULL)
GetList(false);
//
//Put everything that's not already in our mapping list into the dest list
//
stlport::vector<ControlData>::iterator sIter;
stlport::vector<ControlData> newList;
for (sIter = m_Mappings.begin ();sIter != m_Mappings.end (); ++sIter)
{
//
if (sIter->mesg_id == 0)
newList.push_back(*sIter);
else if (sIter->group != ControlsManager::JoystickButtonGroupID
&& sIter->group != ControlsManager::MouseButtonGroupID
&& sIter->group != ControlsManager::VirtualButtonGroupID
&& sIter->group != ControlsManager::JoystickHatID)
{
newList.push_back(*sIter);
}
}
//
// Now put everything in our mapping list into the ControlData form and add it to the new list
//
ControlDef* pcdPtr = m_pcdHead;
for (int i = 0; i < m_nCount; ++i)
{
if (pcdPtr->cd_key_valid || (!pcdPtr->cd_mouse_valid && !pcdPtr->cd_joy_valid))
{
newList.push_back(pcdPtr->cd_key);
}
if (pcdPtr->cd_mouse_valid)
{
newList.push_back(pcdPtr->cd_mouse);
}
if (pcdPtr->cd_joy_valid)
{
newList.push_back(pcdPtr->cd_joy);
}
pcdPtr++;
}
//
// Now copy the new temp list to the final m_Mappings position
//
m_Mappings = newList;
SetInvertStateOfList();
if (owner)
ApplyList(owner);
}
void CControlMappingList::FillDefault (stlport::vector<ControlData>& list)
{
HKL hkl;
char *str;
int index;
hkl = GetKeyboardLayout (0);
index = PRIMARYLANGID (LOWORD (hkl));
switch (index)
{
case LANG_FRENCH:
str = "content\\Interfaces\\Common\\freinterface.control";
break;
case LANG_GERMAN:
str = "content\\Interfaces\\Common\\gerinterface.control";
break;
case LANG_SPANISH:
str = "content\\Interfaces\\Common\\spainterface.control";
break;
case LANG_JAPANESE:
str = "content\\Interfaces\\Common\\japinterface.control";
break;
case LANG_KOREAN:
str = "content\\Interfaces\\Common\\korinterface.control";
break;
case LANG_CHINESE:
str = "content\\Interfaces\\Common\\chiinterface.control";
break;
case LANG_ITALIAN:
str = "content\\Interfaces\\Common\\itainterface.control";
break;
case LANG_PORTUGUESE:
str = "content\\Interfaces\\Common\\porinterface.control";
break;
case LANG_DANISH:
str = "content\\Interfaces\\Common\\daninterface.control";
break;
case LANG_NORWEGIAN:
str = "content\\Interfaces\\Common\\norinterface.control";
break;
case LANG_SWEDISH:
str = "content\\Interfaces\\Common\\sweinterface.control";
break;
case LANG_FINNISH:
str = "content\\Interfaces\\Common\\fininterface.control";
break;
default:
str = "content\\Interfaces\\Common\\interface.control";
break;
}
Resource res (str);
res.LoadData ();
Verify (res.DoesResourceExist ());
int mapping_count;
res >> m_Joystick;
res >> m_ForceFeedBack;
res >> m_MouseSensitivity;
res >> m_joyStickShiftValue;
res >> m_mouseAllowed;
res >> m_JoystickXAxisType;
res >> m_JoystickRudderAxisType;
res >> m_MouseXAxisType;
res >> mapping_count;
const ControlData *mapping = Cast_Pointer(const ControlData*,res.GetPointer());
list.reserve (mapping_count);
for (int i=0; i<mapping_count; ++i, ++mapping)
{
#ifndef LAB_ONLY // in release build remove no string mapping command, these should only be debug command
if (mapping->nameresid == 0)
continue;
#endif
list.push_back (*mapping);
}
GetInvertStateOfList();
}
void CControlMappingList::ApplyList (Plug *owner)
{
Verify (owner);
ControlsManager::Instance->SetJoystick (m_Joystick);
if (IsJoyStickShiftAllowed())
ControlsManager::Instance->JoyStickShift (m_joyStickShiftValue);
else
ControlsManager::Instance->JoyStickShift (-1);
if (owner->IsDerivedFrom (Interface::DefaultData))
{
Interface *inter;
inter = Cast_Object (Interface *,owner);
inter->ForceFeedBack (m_ForceFeedBack);
inter->MouseSensitivity (m_MouseSensitivity);
inter->MouseAllowed (m_mouseAllowed);
inter->JoystickXAxisType (m_JoystickXAxisType);
inter->JoystickRudderAxisType (m_JoystickRudderAxisType);
inter->MouseXAxisType (m_MouseXAxisType);
inter->JoyStickThrottleCenter(m_joystick_throttle_center);
inter->JoyStickThrottleLow(m_joystick_throttle_dead_low);
inter->JoyStickThrottleHigh(m_joystick_throttle_dead_high);
}
ControlsManager::Instance->RemoveAllMappings ();
ControlsManager::Instance->CreateMapping( // need to add the escape key
NULL,
0,
Application::GetInstance(),
Application::PauseGameMessageID,
Application::GetInstance(),
-1,
ControlsManager::VirtualButtonGroupID,
KEY_ESCAPE,
false,
1,
1
);
stlport::vector<ControlData>::iterator iter;
for (iter = m_Mappings.begin ();iter != m_Mappings.end ();iter++)
{
if (iter->mesg_id != 0)
{
if ((iter->group == ControlsManager::MouseButtonGroupID) && ((iter->element == MOUSE_WHEEL_UP)||(iter->element == MOUSE_WHEEL_DOWN)))
iter->group = ControlsManager::VirtualButtonGroupID;
}
}
for (iter = m_Mappings.begin ();iter != m_Mappings.end ();iter++)
{
//
//----------------------
// Connect mapping to us
//----------------------
//
Entity *entity = Cast_Object (Entity *,owner);
Check_Object(entity);
//
//-------------------------------------------------------
// If this is a direct mapping, find the attribute to use
//-------------------------------------------------------
//
if (iter->mesg_id == 0)
{
if (!AxisButtonUsed (iter->group,iter->element))
{
ControlsManager::Instance->CreateMapping(entity,iter->attr_id,NULL,0,owner,iter->control_mask,iter->group,iter->element,iter->invert,iter->nameresid,iter->control_type);
}
}
else
{
if ((iter->group == ControlsManager::MouseButtonGroupID) && ((iter->element == MOUSE_WHEEL_UP)||(iter->element == MOUSE_WHEEL_DOWN)))
iter->group = ControlsManager::VirtualButtonGroupID;
if (!((iter->group == ControlsManager::VirtualButtonGroupID) && ((iter->element == 0)||(iter->element >= LAST_AXIS_MAPID))))
ControlsManager::Instance->CreateMapping(NULL,0,entity,iter->mesg_id,owner,iter->control_mask,iter->group,iter->element,false,iter->nameresid,iter->control_type);
}
}
}
bool CControlMappingList::AxisButtonUsed (int group,int element)
{
int value1=-1,value2=-1,value3=-1,value4=-1; // there is no -1, so a comparison against this will fail
switch (group)
{
case ControlsManager::JoystickAxisGroupID:
switch (element)
{
case Joystick::XAxis:
value1 = JOYX_LEFT;
value2 = JOYX_RIGHT;
break;
case Joystick::YAxis:
value1 = JOYY_UP;
value2 = JOYY_DOWN;
break;
case Joystick::ThrottleAxis:
value1 = JOYTHROTTLE_UP;
value2 = JOYTHROTTLE_DOWN;
break;
case Joystick::RudderAxis:
value1 = JOYRUDDER_LEFT;
value2 = JOYRUDDER_RIGHT;
break;
}
break;
case ControlsManager::JoystickHatID:
value1 = HAT_LEFT;
value2 = HAT_RIGHT;
value3 = HAT_UP;
value4 = HAT_DOWN;
break;
case ControlsManager::MousePosXID:
case ControlsManager::MouseDeltaXID:
value1 = MOUSEX_LEFT;
value2 = MOUSEX_RIGHT;
break;
case ControlsManager::MousePosYID:
case ControlsManager::MouseDeltaYID:
value1 = MOUSEY_UP;
value2 = MOUSEY_DOWN;
break;
case ControlsManager::MouseWheelDeltaID:
value1 = MOUSE_WHEEL_UP;
value2 = MOUSE_WHEEL_DOWN;
break;
default:
return false;
}
stlport::vector<ControlData>::iterator iter;
for (iter = m_Mappings.begin ();iter != m_Mappings.end ();iter++)
{
if (iter->group == ControlsManager::VirtualButtonGroupID)
{
if (iter->element == value1)
return true;
if (iter->element == value2)
return true;
if (iter->element == value3)
return true;
if (iter->element == value4)
return true;
}
}
return false;
}
stlport::vector<ControlData>::iterator CControlMappingList::StartList (void)
{
return m_Mappings.begin ();
}
stlport::vector<ControlData>::iterator CControlMappingList::EndList (void)
{
return m_Mappings.end ();
}
void CControlMappingList::ReplaceList (stlport::vector<ControlData>::iterator start,stlport::vector<ControlData>::iterator end)
{
}
void CControlMappingList::LoadList (const char *filename,Entity::ClassData *classdata)
{
//-------------------------
// Open up the mapping file
//-------------------------
//
Tool *tool = Tool::Instance;
Check_Object(tool);
//
//--------------------------------------------------------
// Create a list of all the control mappings, one per page
//--------------------------------------------------------
//
m_Mappings.clear ();
NotationFile mapping_file (filename);
NotationFile::PageIterator *mappings = mapping_file.MakePageIterator();
Check_Object(mappings);
int mapping_count = mappings->GetSize();
if (!mapping_count)
STOP(("%s: Empty file!", mapping_file.GetFileName()));
//
//----------------------------------
// For each page, create one mapping
//----------------------------------
//
Page *mapping;
while ((mapping = mappings->ReadAndNext()) != NULL)
{
ControlData data;
//
//-------------------
// Get the IO Mapping
//-------------------
//
const char *control_name,*page_name = mapping->GetName();
mapping->GetEntry("IOMapping", &control_name, true);
if (
!tool->FindControlGroupAndElement(
&data.group,
&data.element,
control_name
)
)
STOP((
"%s: {[%s]IOMapping=%s}: Unknown control name!",
mapping_file.GetFileName(),
page_name,
control_name
));
//
//----------------------------------
// Find out who this mapping goes to
//----------------------------------
//
Entity::ClassData *class_data = classdata;
//
//---------------------------------------
// If there is a modemask entry, parse it
//---------------------------------------
//
data.control_mask = ControlsManager::PlainFlag;
const char *control_mask;
if (mapping->GetEntry("ControlMask", &control_mask))
{
//
//----------------------------------
// Initialize the string for parsing
//----------------------------------
//
data.control_mask = 0;
int len = strlen(control_mask) + 1;
char *modes = new char[len];
Register_Pointer(modes);
Mem_Copy(modes, control_mask, len, len);
char *mode_copy = modes;
while (*modes)
{
//
//---------------------
// Skip any white space
//---------------------
//
while (*modes == ' ' || *modes == '\t' || *modes == '|')
++modes;
if (!*modes)
break;
//
//----------------------------
// Isolate the string we found
//----------------------------
//
char *mode = modes;
while (
*modes != ' '
&& *modes != '\t'
&& *modes != '|'
&& *modes
)
{
++modes;
}
if (*modes)
*modes++ = '\0';
//
//--------------------------
// Parse the isolated string
//--------------------------
//
int new_mode;
if (!_stricmp(mode, "Plain"))
new_mode = ControlsManager::PlainFlag;
else if (!_stricmp(mode, "Shift"))
new_mode = ControlsManager::ShiftFlag;
else if (!_stricmp(mode, "Ctrl"))
new_mode = ControlsManager::CtrlFlag;
else if (!_stricmp(mode, "Alt"))
new_mode = ControlsManager::AltFlag;
else if (!_stricmp(mode, "JoyShift"))
new_mode = ControlsManager::ShiftFlag;
else if (!_stricmp(mode, "CtrlShift"))
new_mode = ControlsManager::CtrlShiftFlag;
else if (!_stricmp(mode, "ShiftAlt"))
new_mode = ControlsManager::ShiftAltFlag;
else if (!_stricmp(mode, "CtrlAlt"))
new_mode = ControlsManager::CtrlAltFlag;
else if (!_stricmp(mode, "CtrlShiftAlt"))
new_mode = ControlsManager::CtrlShiftAltFlag;
else if (!_stricmp(mode, "AlwaysActive"))
new_mode = ControlsManager::AlwaysActive;
else
{
STOP((
"%s: {[%s]ControlMask=%s}: %s is an unknown control mode!",
mapping_file.GetFileName(),
page_name,
control_mask,
mode
));
new_mode = 0;
}
data.control_mask |= new_mode;
}
if (!data.control_mask)
data.control_mask = ControlsManager::PlainFlag;
Unregister_Pointer(mode_copy);
delete mode_copy;
}
//
//------------------------------------
// Find the type of connection to make
//------------------------------------
//
const char *type;
mapping->GetEntry("Type", &type, true);
//
//----------------------------------------------------------------------
// If this is an event mapping, we have to have a message ID. How do we
// check a message name against an unknown message list?
//----------------------------------------------------------------------
//
if (!_stricmp(type, "EventMapping"))
{
// mapping_request->mappingType = ControlsMappingRequest::EventMapping;
const char *message;
mapping->GetEntry("MessageID", &message, true);
if (class_data)
{
Check_Object(class_data);
const Receiver::MessageEntry *entry =
class_data->FindMessageEntry(message);
if (!entry)
STOP((
"%s: {[%s]MessageID=%s}: Unknown message ID!",
mapping_file.GetFileName(),
page_name,
message
));
data.mesg_id = entry->messageID;
}
}
//
//----------------------------------------------------------------------
// If this is a direct mapping, we have to have an attribute ID. How do
// we find an unknown attribute of an unknown subsystem?
//----------------------------------------------------------------------
//
else if (!_stricmp(type, "DirectMapping"))
{
// mapping_request->mappingType = ControlsMappingRequest::DirectMapping;
const char *attribute;
mapping->GetEntry("AttributeID", &attribute, true);
bool invert=false;
mapping->GetEntry("Invert",&invert,false);
data.invert = invert;
if (class_data)
{
Check_Object(class_data);
AttributeEntry *entry =
Cast_Pointer(Entity::ClassData*,class_data)
->attributeTable.GetAttributeEntry(attribute);
if (!entry)
{
STOP((
"%s: {[%s]AttributeID=%s}: Unknown attribute ID!",
mapping_file.GetFileName(),
page_name,
attribute
));
}
Check_Object(entry);
data.attr_id = entry->attributeID;
}
}
else
{
STOP((
"%s: {[%s]Type=%s}: Unknown mapping type!",
mapping_file.GetFileName(),
page_name,
type
));
}
// MSL 5.05 MFD Comm
int nameid=0;
mapping->GetEntry("NameResID", &nameid, false);
data.nameresid = nameid;
type = "FIRE_COMMAND";
mapping->GetEntry("Area",&type,false);
if (!_stricmp(type, "FIRE_COMMAND"))
data.control_type = ControlData::Fire_Control;
else if (!_stricmp(type, "MOVE_COMMAND"))
data.control_type = ControlData::Move_Control;
else if (!_stricmp(type, "MISC_COMMAND"))
data.control_type = ControlData::Misc_Control;
else if (!_stricmp(type, "LANCEMATE_COMMAND"))
data.control_type = ControlData::Lancemate_Control;
else if (!_stricmp(type, "COMM_COMMAND"))
data.control_type = ControlData::Comm_Control;
else
{
STOP(("%s: {[%s]Control Area=%s}: Unknown Control Area!",mapping_file.GetFileName(),page_name,type));
}
m_Mappings.push_back (data);
}
Check_Object(mappings);
delete mappings;
}
int CControlMappingList::compareControls(const void *elem1, const void *elem2)
{
ControlDef *pcd1 = (ControlDef *) elem1;
ControlDef *pcd2 = (ControlDef *) elem2;
return pcd1->control_type - pcd2->control_type;
}
int CControlMappingList::AssignControlKey(Plug* owner, int nRow, int newKey, int newModifier)
{
gosASSERT(nRow < m_nCount);
gosASSERT(newKey != 0);
//
//Look for event collisions so we can unmap re-used events...
//
int returnIndex = nRow;
ControlData cd;
for (int i = 0; i < m_nCount; i++)
{
if (m_pcdHead[i].nKey == newKey && m_pcdHead[i].control_mask == newModifier)
{
if (i != nRow)
{
returnIndex = i;
m_pcdHead[i].nKey = 0;
m_pcdHead[i].control_mask = 0;
m_pcdHead[i].cd_key.element = 0;
m_pcdHead[i].cd_key.control_mask = 0;
}
break;
}
}
// Init properties that change from old settings
cd = m_pcdHead[nRow].cd_key;
cd.control_mask = newModifier;
cd.element = newKey;
gosASSERT(cd.group == ControlsManager::VirtualButtonGroupID);
m_pcdHead[nRow].nKey = newKey;
m_pcdHead[nRow].control_mask = newModifier;
m_pcdHead[nRow].cd_key = cd;
m_pcdHead[nRow].cd_key_valid = true;
SetList(owner);
return returnIndex;
}
int CControlMappingList::AssignControlJoy(Plug* owner, int nRow, int newJoy, int shift)
{
gosASSERT(nRow < m_nCount);
//
//Look for event collisions so we can unmap re-used events...
//
int returnIndex = nRow;
ControlData cd;
for (int i = 0; i < m_nCount; i++)
{
if (m_pcdHead[i].cd_joy_valid && m_pcdHead[i].nJoy == newJoy && m_pcdHead[i].cd_joy.control_mask == shift)
{
if (i != nRow)
{
returnIndex = i;
m_pcdHead[i].nJoy = 0;
gosASSERT(m_pcdHead[i].cd_joy_valid);
m_pcdHead[i].cd_joy_valid = false;
m_pcdHead[i].cd_joy.element = 0;
m_pcdHead[i].cd_joy.control_mask = 0;
}
break;
}
}
cd = m_pcdHead[nRow].cd_key;
// Init properties that change from old settings
if (newJoy<10) {
cd.group = ControlsManager::JoystickButtonGroupID;
cd.element = newJoy;
cd.control_mask = shift;
cd.mesg_id = m_pcdHead[nRow].mesg_id;
cd.nameresid = m_pcdHead[nRow].nameresid;
}
else {
cd.group = ControlsManager::JoystickHatID;
cd.element = newJoy-10;
cd.control_mask = shift;
cd.mesg_id = m_pcdHead[nRow].mesg_id;
cd.nameresid = m_pcdHead[nRow].nameresid;
}
m_pcdHead[nRow].nJoy = newJoy;
m_pcdHead[nRow].cd_joy = cd;
m_pcdHead[nRow].cd_joy_valid = true;
SetList(owner);
return returnIndex;
}
int CControlMappingList::AssignControlMouse(Plug* owner, int nRow, int newMouse)
{
gosASSERT(nRow < m_nCount);
//
//Look for event collisions so we can unmap re-used events...
//
int returnIndex = m_pcdHead[nRow].nIdx;
ControlData cd;
for (int i = 0; i < m_nCount; i++)
{
if (m_pcdHead[i].cd_mouse_valid && m_pcdHead[i].nMouse == newMouse)
{
if (i != nRow)
{
returnIndex = i; //m_pcdHead[i]->nIdx;
m_pcdHead[i].nMouse = 0;
gosASSERT(m_pcdHead[i].cd_mouse_valid);
m_pcdHead[i].cd_mouse_valid = false;
m_pcdHead[i].cd_mouse.element = 0;
}
break;
}
}
cd = m_pcdHead[nRow].cd_key;
cd.group = ControlsManager::MouseButtonGroupID;
// Init properties that change from old settings
cd.element = newMouse;
cd.mesg_id = m_pcdHead[nRow].mesg_id;
cd.nameresid = m_pcdHead[nRow].nameresid;
m_pcdHead[nRow].nMouse = newMouse;
m_pcdHead[nRow].cd_mouse = cd;
m_pcdHead[nRow].cd_mouse_valid = true;
SetList(owner);
return returnIndex;
}
CControlMappingList::ControlDef::ControlDef()
{
mesg_id = 0;
nameresid = 0;
control_type = 0;
control_mask = 0;
nKey = 0;
nMouse = 0;
nJoy = 0;
nIdx = 0;
cd_mouse_valid = false;
cd_joy_valid = false;
cd_key_valid = false;
}
CControlMappingList::ControlDef::~ControlDef()
{
}
static char buffer[200];
const char* CControlMappingList::ControlDef::KeyName() const
{
const int MyCtrl = 1;
const int MyShift = 2;
const int MyAlt = 4;
buffer[0] = 0;
if (nKey == 0)
return buffer;
int flag = 0;
switch(control_mask)
{
case ControlsManager::AlwaysActive:
case ControlsManager::PlainFlag:
break;
case ControlsManager::ShiftFlag:
flag = MyShift;
break;
case ControlsManager::CtrlFlag:
flag = MyCtrl;
break;
case ControlsManager::AltFlag:
flag = MyAlt;
break;
case ControlsManager::CtrlShiftFlag:
flag = MyCtrl | MyShift;
break;
case ControlsManager::ShiftAltFlag:
flag = MyAlt | MyShift;
break;
case ControlsManager::CtrlAltFlag:
flag = MyAlt | MyCtrl;
break;
case ControlsManager::CtrlShiftAltFlag:
flag = MyShift | MyCtrl | MyAlt;
break;
default:
gosASSERT(!"Unknown control data type");
break;
}
// Now composite each modifier present into one long string
buffer[0] = 0;
if (flag & MyShift)
{
strcpy(buffer, gos_DescribeKey(KEY_LSHIFT << 8));
strcat(buffer, " ");
}
if (flag & MyCtrl)
{
strcat(buffer, gos_DescribeKey(KEY_LCONTROL << 8));
strcat(buffer, " ");
}
if (flag & MyAlt)
{
strcat(buffer, gos_DescribeKey(KEY_LMENU << 8));
strcat(buffer, " ");
}
strcat(buffer, gos_DescribeKey(nKey << 8));
return buffer;
}
const char* CControlMappingList::ControlDef::JoyName() const
{
char buffer2[200];
buffer2[0] = 0;
buffer[0] = 0;
if (cd_joy.control_mask == ControlsManager::ShiftFlag)
{
strcpy(buffer, gos_DescribeKey(KEY_LSHIFT << 8));
strcat(buffer, " ");
}
if (cd_joy_valid && nJoy < 10)
sprintf(buffer2, "%d", nJoy + 1);
else if (cd_joy_valid)
strcat(buffer, Application::GetInstance()->GetLocString(IDS_CONTROL_HATLEFT+nJoy-10));
else
buffer2[0] = 0;
strcat(buffer, buffer2);
return buffer;
}
const char* CControlMappingList::ControlDef::MouseName() const
{
if (cd_mouse_valid)
sprintf(buffer, "%d", nMouse + 1);
else
buffer[0] = 0;
return buffer;
}
void CControlMappingList::InitializeThrottleConstants()
{
bool bNeedToSave = false;
NotationFile startup_ini("options.ini", NotationFile::Standard, true);
Stuff::Page *joypage = startup_ini.FindPage("joystick");
if (!joypage)
{
joypage = startup_ini.AddPage("joystick");
bNeedToSave = true;
}
Stuff::Scalar temp;
if (!joypage->GetEntry("BiThrottleCenter", &temp)) {
joypage->AppendEntry("BiThrottleCenter", 0.30f);
bNeedToSave = true;
}
if (!joypage->GetEntry("BiThrottleLow", &temp)) {
joypage->AppendEntry("BiThrottleLow", 0.25f);
bNeedToSave = true;
}
if (!joypage->GetEntry("BiThrottleHigh", &temp)) {
joypage->AppendEntry("BiThrottleHigh", 0.06f);
bNeedToSave = true;
}
if (!joypage->GetEntry("OneThrottleCenter", &temp)) {
joypage->AppendEntry("OneThrottleCenter", 0.30f);
bNeedToSave = true;
}
if (!joypage->GetEntry("OneThrottleHigh", &temp)) {
joypage->AppendEntry("OneThrottleHigh", 0.06f);
bNeedToSave = true;
}
if (bNeedToSave)
startup_ini.Save();
joypage->GetEntry("BiThrottleCenter", &m_joystick_throttle_center);
joypage->GetEntry("BiThrottleLow", &m_joystick_throttle_dead_low);
joypage->GetEntry("BiThrottleHigh", &m_joystick_throttle_dead_high);
}