void FInputBindingManager::CreateInputCommand( const TSharedRef<FBindingContext>& InBindingContext, TSharedRef<FUICommandInfo> InCommandInfo ) { check( InCommandInfo->BindingContext == InBindingContext->GetContextName() ); // The command name should be valid check( InCommandInfo->CommandName != NAME_None ); // Should not have already created a chord for this command check( !InCommandInfo->ActiveChord->IsValidChord() ); const FName ContextName = InBindingContext->GetContextName(); FContextEntry& ContextEntry = ContextMap.FindOrAdd( ContextName ); // Our parent context must exist. check( InBindingContext->GetContextParent() == NAME_None || ContextMap.Find( InBindingContext->GetContextParent() ) != NULL ); FCommandInfoMap& CommandInfoMap = ContextEntry.CommandInfoMap; if( !ContextEntry.BindingContext.IsValid() ) { ContextEntry.BindingContext = InBindingContext; } if( InBindingContext->GetContextParent() != NAME_None ) { check( InBindingContext->GetContextName() != InBindingContext->GetContextParent() ); // Set a mapping from the parent of the current context to the current context ParentToChildMap.AddUnique( InBindingContext->GetContextParent(), InBindingContext->GetContextName() ); } if( InCommandInfo->DefaultChord.IsValidChord() ) { CheckForDuplicateDefaultChords( *InBindingContext, InCommandInfo ); } { TSharedPtr<FUICommandInfo> ExistingInfo = CommandInfoMap.FindRef( InCommandInfo->CommandName ); ensureMsgf( !ExistingInfo.IsValid(), TEXT("A command with name %s already exists in context %s"), *InCommandInfo->CommandName.ToString(), *InBindingContext->GetContextName().ToString() ); } // Add the command info to the list of known infos. It can only exist once. CommandInfoMap.Add( InCommandInfo->CommandName, InCommandInfo ); // See if there are user defined chords for this command FInputChord UserDefinedChord; bool bFoundUserDefinedChord = GetUserDefinedChord( ContextName, InCommandInfo->CommandName, UserDefinedChord ); if( !bFoundUserDefinedChord && InCommandInfo->DefaultChord.IsValidChord() ) { // Find any existing command with the same chord // This is for inconsistency between default and user defined chord. We need to make sure that if default chords are changed to a chord that a user set to a different command, that the default chord doesn't replace // the existing commands chord. Note: Duplicate default chords are found above in CheckForDuplicateDefaultChords FName ExisingCommand = ContextEntry.ChordToCommandInfoMap.FindRef( InCommandInfo->DefaultChord ); if( ExisingCommand == NAME_None ) { // No existing command has a user defined chord and no user defined chord is available for this command TSharedRef<FInputChord> NewChord = MakeShareable( new FInputChord( InCommandInfo->DefaultChord ) ); InCommandInfo->ActiveChord = NewChord; } } else if( bFoundUserDefinedChord ) { // Find any existing command with the same chord // This is for inconsistency between default and user defined chord. We need to make sure that if default chords are changed to a chord that a user set to a different command, that the default chord doesn't replace // the existing commands chord. FName ExisingCommandName = ContextEntry.ChordToCommandInfoMap.FindRef( UserDefinedChord ); if( ExisingCommandName != NAME_None ) { // Get the command with using the same chord TSharedPtr<FUICommandInfo> ExistingInfo = CommandInfoMap.FindRef( ExisingCommandName ); if( *ExistingInfo->ActiveChord != ExistingInfo->DefaultChord ) { // two user defined chords are the same within a context. If the keybinding editor was used this wont happen so this must have been directly a modified user setting file UE_LOG(LogSlate, Error, TEXT("Duplicate user defined chords found: [%s,%s]. Chord for %s being removed"), *InCommandInfo->GetLabel().ToString(), *ExistingInfo->GetLabel().ToString(), *ExistingInfo->GetLabel().ToString() ); } ContextEntry.ChordToCommandInfoMap.Remove( *ExistingInfo->ActiveChord ); // Remove the existing chord. ExistingInfo->ActiveChord = MakeShareable( new FInputChord() ); } TSharedRef<FInputChord> NewChord = MakeShareable( new FInputChord( UserDefinedChord ) ); // Set the active chord on the command info InCommandInfo->ActiveChord = NewChord; } // If the active chord is valid, map the chord to the map for fast lookup when processing bindings if( InCommandInfo->ActiveChord->IsValidChord() ) { checkSlow( !ContextEntry.ChordToCommandInfoMap.Contains( *InCommandInfo->GetActiveChord() ) ); ContextEntry.ChordToCommandInfoMap.Add( *InCommandInfo->GetActiveChord(), InCommandInfo->GetCommandName() ); } }