// ============================================================================= // KEYBINDS MENU // ============================================================================= function ControlsMenuDefaultsButton::onClick(%this) { //For this to work with module-style, we have to figure that somewhere, we'll set where our default keybind script is at. //This can be hardcoded in your actual project. //exec($KeybindPath); //ControlsMenu.reload(); } function getMapDisplayName( %device, %action ) { if ( %device $= "keyboard" ) return( %action ); else if ( strstr( %device, "mouse" ) != -1 ) { // Substitute "mouse" for "button" in the action string: %pos = strstr( %action, "button" ); if ( %pos != -1 ) { %mods = getSubStr( %action, 0, %pos ); %object = getSubStr( %action, %pos, 1000 ); %instance = getSubStr( %object, strlen( "button" ), 1000 ); return( %mods @ "mouse" @ ( %instance + 1 ) ); } else error( "Mouse input object other than button passed to getDisplayMapName!" ); } else if ( strstr( %device, "joystick" ) != -1 ) { // Substitute "joystick" for "button" in the action string: %pos = strstr( %action, "button" ); if ( %pos != -1 ) { %mods = getSubStr( %action, 0, %pos ); %object = getSubStr( %action, %pos, 1000 ); %instance = getSubStr( %object, strlen( "button" ), 1000 ); return( %mods @ "joystick" @ ( %instance + 1 ) ); } else { %pos = strstr( %action, "pov" ); if ( %pos != -1 ) { %wordCount = getWordCount( %action ); %mods = %wordCount > 1 ? getWords( %action, 0, %wordCount - 2 ) @ " " : ""; %object = getWord( %action, %wordCount - 1 ); switch$ ( %object ) { case "upov": %object = "POV1 up"; case "dpov": %object = "POV1 down"; case "lpov": %object = "POV1 left"; case "rpov": %object = "POV1 right"; case "upov2": %object = "POV2 up"; case "dpov2": %object = "POV2 down"; case "lpov2": %object = "POV2 left"; case "rpov2": %object = "POV2 right"; default: %object = ""; } return( %mods @ %object ); } else error( "Unsupported Joystick input object passed to getDisplayMapName!" ); } } else if ( strstr( %device, "gamepad" ) != -1 ) { return %action; %pos = strstr( %action, "button" ); if ( %pos != -1 ) { %mods = getSubStr( %action, 0, %pos ); %object = getSubStr( %action, %pos, 1000 ); %instance = getSubStr( %object, strlen( "button" ), 1000 ); return( %mods @ "joystick" @ ( %instance + 1 ) ); } else { %pos = strstr( %action, "thumb" ); if ( %pos != -1 ) { //%instance = getSubStr( %action, strlen( "thumb" ), 1000 ); //return( "thumb" @ ( %instance + 1 ) ); return %action; } else error( "Unsupported gamepad input object passed to getDisplayMapName!" ); } } return( "" ); } function buildFullMapString( %index, %actionMap, %deviceType ) { %name = $RemapName[%index]; %cmd = $RemapCmd[%index]; %temp = %actionMap.getBinding( %cmd ); if ( %temp $= "" ) return %name TAB ""; %mapString = ""; %count = getFieldCount( %temp ); for ( %i = 0; %i < %count; %i += 2 ) { if ( %mapString !$= "" ) continue; //%mapString = %mapString @ ", "; %device = getField( %temp, %i + 0 ); %object = getField( %temp, %i + 1 ); if (startsWith(%device,"mouse")) %deviceType = "mouse"; if(%deviceType !$= "" && !startsWith(%device, %deviceType)) continue; %mapString = %mapString @ getMapDisplayName( %device, %object ); } return %name TAB %mapString; } function fillRemapList() { %device = $remapListDevice; OptionsMenuSettingsList.clear(); //build out our list of action maps %actionMapCount = ActionMapGroup.getCount(); %actionMapList = ""; for(%i=0; %i < %actionMapCount; %i++) { %actionMap = ActionMapGroup.getObject(%i); if(%actionMap == GlobalActionMap.getId()) continue; %actionMapName = %actionMap.humanReadableName $= "" ? %actionMap.getName() : %actionMap.humanReadableName; if(%actionMapList $= "") %actionMapList = %actionMapName; else %actionMapList = %actionMapList TAB %actionMapName; } //If we didn't find any valid actionMaps, then just exit out if(%actionMapList $= "") return; if($activeRemapControlSet $= "") $activeRemapControlSet = getField(%actionMapList, 0); OptionsMenuSettingsList.addOptionRow("Control Set", "$activeRemapControlSet", %actionMapList, false, "controlSetChanged", true, "Which keybind control set to edit", $activeRemapControlSet); for ( %i = 0; %i < $RemapCount; %i++ ) { if(%device !$= "" && %device !$= $RemapDevice[%i]) continue; %actionMapName = $RemapActionMap[%i].humanReadableName $= "" ? $RemapActionMap[%i].getName() : $RemapActionMap[%i].humanReadableName; if($activeRemapControlSet !$= %actionMapName) continue; %keyMap = buildFullMapString( %i, $RemapActionMap[%i], %device ); %description = $RemapDescription[%i]; %buttonImageAsset = getButtonBitmap(%device, getField(%keyMap, 1)); OptionsMenuSettingsList.addKeybindRow(getField(%keyMap, 0), %buttonImageAsset, "doKeyRemap", true, %description); } //OptionsMenuSettingsList.refresh(); //OptionsMenu.addRow( %i, %this.buildFullMapString( %i ) ); } function controlSetChanged() { $activeRemapControlSet = OptionsMenuSettingsList.getCurrentOption(); fillRemapList(); } function doKeyRemap( %rowIndex ) { %rowIndex--; //Offset the rowIndex to account for controlset option %name = $RemapName[%rowIndex]; RemapDlg-->OptRemapText.setValue( "Re-bind \"" @ %name @ "\" to..." ); OptRemapInputCtrl.index = %rowIndex; Canvas.pushDialog( RemapDlg ); //Let the options menu know %actionMap = $RemapActionMap[%rowIndex]; OptionsMenu.onKeybindChanged(%actionMap, %name); } function ControlsMenuRebindButton::onClick(%this) { %name = $RemapName[%this.keybindIndex]; RemapDlg-->OptRemapText.setValue( "Re-bind \"" @ %name @ "\" to..." ); OptRemapInputCtrl.index = %this.keybindIndex; OptRemapInputCtrl.optionIndex = %this.optionIndex; Canvas.pushDialog( RemapDlg ); } function OptRemapInputCtrl::onInputEvent( %this, %device, %action ) { //error( "** onInputEvent called - device = " @ %device @ ", action = " @ %action @ " **" ); Canvas.popDialog( RemapDlg ); // Test for the reserved keystrokes: if ( %device $= "keyboard" ) { // Cancel... if ( %action $= "escape" ) { // Do nothing... return; } } %cmd = $RemapCmd[%this.index]; %name = $RemapName[%this.index]; %actionMap = $RemapActionMap[%this.index]; // Grab the friendly display name for this action // which we'll use when prompting the user below. %mapName = getMapDisplayName( %device, %action ); // Get the current command this action is mapped to. %prevMap = %actionMap.getCommand( %device, %action ); //TODO: clear all existant keybinds to a command and then bind it so we only have a single one at all times unbindExtraActions( %cmd, %actionMap, 0 ); unbindExtraActions( %cmd, %actionMap, 1 ); // If nothing was mapped to the previous command // mapping then it's easy... just bind it. if ( %prevMap $= "" ) { //unbindExtraActions( %cmd, %actionMap, 1 ); %actionMap.bind( %device, %action, %cmd ); fillRemapList(); return; } // If the previous command is the same as the // current then they hit the same input as what // was already assigned. if ( %prevMap $= %cmd ) { //unbindExtraActions( %cmd, %actionMap, 0 ); %actionMap.bind( %device, %action, %cmd ); fillRemapList(); return; } // Look for the index of the previous mapping. %prevMapIndex = findRemapCmdIndex( %prevMap ); // If we get a negative index then the previous // mapping was to an item that isn't included in // the mapping list... so we cannot unmap it. if ( %prevMapIndex == -1 ) { MessageBoxOK( "Remap Failed", "\"" @ %mapName @ "\" is already bound to a non-remappable command!" ); return; } // Setup the forced remapping callback command. %callback = "redoMapping(" @ %device @ ", " @ %actionMap @ ", \"" @ %action @ "\", \"" @ %cmd @ "\", " @ %prevMapIndex @ ", " @ %this.index @ ");"; // Warn that we're about to remove the old mapping and // replace it with another. %prevCmdName = $RemapName[%prevMapIndex]; Canvas.pushDialog( RemapConfirmDlg ); RemapConfirmationText.setText("\"" @ %mapName @ "\" is already bound to \"" @ %prevCmdName @ "\"! Do you wish to replace this mapping?"); RemapConfirmationYesButton.command = "redoMapping(" @ %device @ ", " @ %actionMap @ ", \"" @ %action @ "\", \"" @ %cmd @ "\", " @ %prevMapIndex @ ", " @ %this.index @ "); Canvas.popDialog();"; RemapConfirmationNoButton.command = "Canvas.popDialog();"; /*MessageBoxYesNo( "Warning", "\"" @ %mapName @ "\" is already bound to \"" @ %prevCmdName @ "\"!\nDo you wish to replace this mapping?", %callback, "" );*/ } function findRemapCmdIndex( %command ) { for ( %i = 0; %i < $RemapCount; %i++ ) { if ( %command $= $RemapCmd[%i] ) return( %i ); } return( -1 ); } /// This unbinds actions beyond %count associated to the /// particular actionMap %commmand. function unbindExtraActions( %command, %actionMap, %count ) { %temp = %actionMap.getBinding( %command ); if ( %temp $= "" ) return; %count = getFieldCount( %temp ) - ( %count * 2 ); for ( %i = 0; %i < %count; %i += 2 ) { %device = getField( %temp, %i + 0 ); %action = getField( %temp, %i + 1 ); %actionMap.unbind( %device, %action ); } } function redoMapping( %device, %actionMap, %action, %cmd, %oldIndex, %newIndex ) { //%actionMap.bind( %device, %action, $RemapCmd[%newIndex] ); %actionMap.bind( %device, %action, %cmd ); fillRemapList(); }