#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::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; inameresid == 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::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::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::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::iterator sIter; stlport::vector 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& 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; inameresid == 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::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::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::iterator CControlMappingList::StartList (void) { return m_Mappings.begin (); } stlport::vector::iterator CControlMappingList::EndList (void) { return m_Mappings.end (); } void CControlMappingList::ReplaceList (stlport::vector::iterator start,stlport::vector::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); }