Scylla Framework
  • API Reference
Search Results for

    Show / Hide Table of Contents
    • Scylla.Input
      • AutoResolveChange
      • AutoResolveResult
      • BindingConflict
      • BindingStorageSettings
      • BindingStorageType
      • BridgeSettings
      • BufferedInput
      • ConfigActionEntry
      • ConfigActionGroup
      • ConfigBindingEntry
      • ConfigConflict
      • ConfigGroupExclusion
      • ConfigLayout
      • ConfigLayout.Builder
      • ConfigLayoutColumnDefinition
      • ConfigLayoutConflictScope
      • ConfigLayoutDefinition
      • ConfigLayoutExclusionDefinition
      • ConfigLayoutGroupDefinition
      • ConfigLayoutGroupMode
      • ConfigLayoutMemberReference
      • ConfigLayoutValidationMessage
      • ConfigLayoutValidationSeverity
      • ConfigSchemeGroup
      • ContextConflictScope
      • ContextValidationMessage
      • ContextValidationSeverity
      • ControlScheme
      • ControlSchemeChangedEvent
      • ControlSchemeManager
      • ControlSchemeType
      • GamepadButton
      • GamepadType
      • IBindingStorage
      • IControlSchemeManager
      • IInputActionManager
      • IInputBindingManager
      • IInputBridgeManager
      • IInputBufferManager
      • IInputConflictScope
      • IInputContextManager
      • IInputControlAliasResolver
      • IInputHintsManager
      • IInputListener
      • IInputRebindabilityProvider
      • IScyllaInputBridge
      • IdentityControlAliasResolver
      • InputActionCanceledEvent
      • InputActionManager
      • InputActionMapNode
      • InputActionMetadata
      • InputActionNode
      • InputActionPerformedEvent
      • InputActionStartedEvent
      • InputActionsDocument
      • InputActionsDocumentIO
      • InputActionsJSONKeys
      • InputAnnotation
      • InputAssetInfo
      • InputBindingGroups
      • InputBindingManager
      • InputBindingMetadata
      • InputBindingNode
      • InputBindingsLoadedEvent
      • InputBindingsSavedEvent
      • InputBridgeManager
      • InputBridgeQueryMode
      • InputBufferConsumedEvent
      • InputBufferManager
      • InputBufferedEvent
      • InputCodegenSettings
      • InputCompositeUtil
      • InputConflictEngine
      • InputConflictPair
      • InputConflictPolicy
      • InputConflictReason
      • InputConflictRecord
      • InputConflictRecordBuilder
      • InputConflictResolution
      • InputConflictSet
      • InputContext
      • InputContextChangedEvent
      • InputContextDefinition
      • InputContextExclusivity
      • InputContextManager
      • InputContextPoppedEvent
      • InputContextPushedEvent
      • InputControlAliasEntry
      • InputControlAliasResolver
      • InputControlAliasScope
      • InputControlPathUtil
      • InputControlSchemeNode
      • InputDeviceChangedEvent
      • InputDeviceConnectedEvent
      • InputDeviceDisconnectedEvent
      • InputDeviceType
      • InputDeviceUtil
      • InputDisabledEvent
      • InputEnabledEvent
      • InputEventType
      • InputHint
      • InputHintChangedEvent
      • InputHintsManager
      • InputIconSet
      • InputIconSet.IconMapping
      • InputIconSetChangedEvent
      • InputInteractionKind
      • InputInteractionResolver
      • InputInteractionSignature
      • InputJSONMember
      • InputJSONNode
      • InputJSONNodeReader
      • InputJSONNodeType
      • InputJSONNodeWriter
      • InputLoggingSettings
      • InputMapMetadata
      • InputMetadataRebindabilityProvider
      • InputMetadataReconciler
      • InputMetadataRecordKind
      • InputModifierMetadataUtil
      • InputOrphanRecord
      • InputRebindCancelledEvent
      • InputRebindCompletedEvent
      • InputRebindManager
      • InputRebindOperation
      • InputRebindStartedEvent
      • InputRebindUtils
      • InputRebindability
      • InputReconcileAction
      • InputReconcileOptions
      • InputReconcileReport
      • InputReconcileReport.Entry
      • InputSchemeDeviceNode
      • InputSchemeMetadata
      • JSONFileBindingStorage
      • ManagedRebindCancelledEvent
      • ManagedRebindCompletedEvent
      • ManagedRebindDataRefreshedEvent
      • ManagedRebindStartedEvent
      • PlayerPrefsBindingStorage
      • RebindMode
      • RebindSettings
      • ScyllaInput
      • ScyllaInput.Meta
      • ScyllaInputAction
      • ScyllaInputActionMap
      • ScyllaInputActionsMetadata
      • ScyllaInputActionsMetadataMigrator
      • ScyllaInputBinding
      • ScyllaInputConfiguration
      • ScyllaInputContextConfiguration
      • ScyllaKey
      • ScyllaKeyConverter
      • ScyllaModifier
      • UnityInputSystemBridge
    • Scylla.Input.Editor
      • DeviceStatusWidget
      • IconMappingDrawer
      • InputIconSetEditor
      • ScyllaInputActionsMetadataEditor
      • ScyllaInputConfigurationEditor
      • ScyllaInputContextConfigurationEditor
      • ScyllaInputDependencyProvider
      • ScyllaInputEditor
      • ScyllaInputGameProfile
      • ScyllaInputGameProfiles
      • ScyllaInputMenuItems
      • ScyllaInputWizard

    Class InputConflictRecordBuilder

    Turns live input actions into the flat snapshot InputConflictEngine reads.

    Inheritance
    object
    InputConflictRecordBuilder
    Inherited Members
    object.Equals(object)
    object.Equals(object, object)
    object.GetHashCode()
    object.GetType()
    object.MemberwiseClone()
    object.ReferenceEquals(object, object)
    object.ToString()
    Namespace: Scylla.Input
    Assembly: ScyllaInput.dll
    Syntax
    public static class InputConflictRecordBuilder
    Remarks

    This is where the cost moved to. The code this replaces recomputed a binding's modifier composite path, device prefix range and registered-scheme membership on every comparison, which meant walking the binding list twice per candidate pair. Here each is computed once per binding per snapshot.

    Records are emitted in action map declaration order, then action order, then binding order, and composite containers are omitted. That order is a contract: conflict results are deduplicated first-hit-wins, so it decides which rival gets named. Note that the maps must come from GetAllActionMaps and not GetAllActions, because the latter returns dictionary order and would make the reported map nondeterministic.

    Methods

    BuildFromActionManager(IInputActionManager, Func<string, string, string>, Func<ScyllaInputBinding, bool>, IInputControlAliasResolver, ref InputConflictRecord[])

    Builds a snapshot of every non-composite binding known to a live action manager.

    Declaration
    public static int BuildFromActionManager(IInputActionManager actionManager, Func<string, string, string> resolveScopeID, Func<ScyllaInputBinding, bool> isInRegisteredSchemes, IInputControlAliasResolver aliasResolver, ref InputConflictRecord[] buffer)
    Parameters
    Type Name Description
    IInputActionManager actionManager

    The action manager to read.

    Func<string, string, string> resolveScopeID

    Maps a map identifier and an action identifier to their scope key. Both are needed because an action name is only unique within its map.

    Func<ScyllaInputBinding, bool> isInRegisteredSchemes

    Reports whether a binding sits in a declared column.

    IInputControlAliasResolver aliasResolver

    Rewrites control paths so alternative spellings of one control compare equal. Pass Shared to compare paths verbatim.

    InputConflictRecord[] buffer

    Scratch array, grown in place as needed. Pass the same array across rebuilds so a refresh allocates nothing once it has settled.

    Returns
    Type Description
    int

    How many leading entries of the buffer were populated.

    Exceptions
    Type Condition
    ArgumentNullException

    Thrown when the action manager or any delegate is null.

    BuildFromDocument(InputActionsDocument, Func<string, string, string>, Func<InputBindingNode, bool>, IInputControlAliasResolver, ref InputConflictRecord[])

    Builds a snapshot from a parsed .inputactions document, with no live module.

    Declaration
    public static int BuildFromDocument(InputActionsDocument document, Func<string, string, string> resolveScopeID, Func<InputBindingNode, bool> isInRegisteredSchemes, IInputControlAliasResolver aliasResolver, ref InputConflictRecord[] buffer)
    Parameters
    Type Name Description
    InputActionsDocument document

    The parsed document.

    Func<string, string, string> resolveScopeID

    Maps a map name and an action name to their scope key. See CreateDocumentScopeResolver(InputActionsDocument, ConfigLayout).

    Func<InputBindingNode, bool> isInRegisteredSchemes

    Reports whether a binding sits in a declared column. See CreateDocumentSchemeFilter(IReadOnlyList<ConfigSchemeGroup>).

    IInputControlAliasResolver aliasResolver

    Rewrites control paths to their canonical spelling.

    InputConflictRecord[] buffer

    Scratch array, grown in place as needed.

    Returns
    Type Description
    int

    How many leading entries of the buffer were populated.

    Remarks

    The edit-time counterpart of BuildFromActionManager(IInputActionManager, Func<string, string, string>, Func<ScyllaInputBinding, bool>, IInputControlAliasResolver, ref InputConflictRecord[]). Both must produce identical records for the same asset, which is what lets an editor promise exactly the conflicts the game will enforce. The differential test in the Input suite is what holds that true.

    The binding index is the ordinal position within the map's binding array filtered to this action, in document order, counting composite containers. Unity numbers an action's bindings that way, so dropping the containers while numbering would shift every part that follows one.

    Bindings are gathered by matching the action name rather than by taking a contiguous range, because the format permits one action's bindings to be interleaved with another's. That is unusual, since Unity's own editor appends in blocks, but a hand-edited or generated asset is still valid and must not be misread. No assertion guards against interleaving for the same reason.

    Exceptions
    Type Condition
    ArgumentNullException

    Thrown when the document or any delegate is null.

    BuildLiveLookupCandidate(string, string, string, string, string, int, string, string, bool, in InputInteractionSignature)

    Builds one record for a caller that scans live Unity bindings under LiveBindingLookup.

    Declaration
    public static InputConflictRecord BuildLiveLookupCandidate(string actionID, string mapID, string scopeID, string schemeGroup, string partName, int bindingIndex, string rawPath, string normalizedPath, bool isComposite, in InputInteractionSignature interactionSignature)
    Parameters
    Type Name Description
    string actionID

    The owning action's name.

    string mapID

    The owning map's name.

    string scopeID

    The scope key, which for a context scope is the map name.

    string schemeGroup

    The binding's declared groups, or empty.

    string partName

    The composite part name, or empty.

    int bindingIndex

    Flat binding index within the action.

    string rawPath

    The path as authored or overridden.

    string normalizedPath

    The path with alternative spellings resolved.

    bool isComposite

    Whether this is a composite container.

    InputInteractionSignature interactionSignature

    What drives the binding. Deliberately required and undefaulted: it is the one field here that is not neutral, and a caller that could omit it would silently disable the interaction rule for this whole feed.

    Returns
    Type Description
    InputConflictRecord

    The record.

    Remarks

    The binding manager answers "what else is on this control" by walking the live Unity objects on every call, because the answer has to reflect an override Unity wrote moments ago and no notification of that reaches this module. It therefore cannot hold a snapshot, and builds one record at a time as it scans.

    Four fields are left neutral, and that is only sound under one policy. ModifierDepth is zero, IsModifierPart is false, CompositeSignature is empty and IsRebindable is false, because computing the first three needs a walk over the action's sibling bindings for every candidate on every call, which is exactly the per-comparison cost the record snapshot exists to avoid. That is safe only because LiveBindingLookup has ScopeByModifierDepth and ScopeByModifierComposite off, and because the engine never reads IsRebindable.

    If one of those flags is ever turned on, the fix is to give this caller a real snapshot, not to fabricate the fields here. Turning a flag on without doing that would not fail loudly: the rules would read the neutral values, compare zero against zero, and silently never fire. Policy_Presets_HaveTheExpectedFlags in the Input test suite exists to catch that edit.

    The interaction signature is not one of them. It is a required parameter, filled by the caller from the binding it already has in hand, which is what makes ScopeByInteraction honest on this feed rather than an example of the mistake above. It is the worked example of the paragraph before this one: the way to turn a rule on here is to supply the data, and the way to keep that true is to leave the parameter undefaulted so the compiler asks.

    BuildQuery(ScyllaInputAction, int, string, string, string, string, IInputControlAliasResolver)

    Builds the record for a binding the caller is asking about.

    Declaration
    public static InputConflictRecord BuildQuery(ScyllaInputAction action, int bindingIndex, string mapID, string scopeID, string schemeGroup, string path, IInputControlAliasResolver aliasResolver)
    Parameters
    Type Name Description
    ScyllaInputAction action

    The owning action.

    int bindingIndex

    Flat binding index within the action.

    string mapID

    The owning map's identifier.

    string scopeID

    The action's scope key.

    string schemeGroup

    The column being asked about.

    string path

    The control path to test.

    IInputControlAliasResolver aliasResolver

    Rewrites the path so alternative spellings compare equal. Must be the same resolver the candidate set was built with, or the query and the candidates disagree on what a path means and the comparison silently reports nothing.

    Returns
    Type Description
    InputConflictRecord

    The query record.

    Remarks

    The supplied path is used rather than the binding's own, because callers legitimately ask "what would collide if this binding were on that control". Everything else, including the part name and the modifier metadata, is read from the binding that actually sits at the index.

    A query is never scheme-filtered. The registered-scheme rule applies to candidates only, which is what lets a caller ask about a column the manager was not initialized with and get an empty answer rather than an error.

    Exceptions
    Type Condition
    ArgumentNullException

    Thrown when the resolver is null.

    CreateDocumentSchemeFilter(IReadOnlyList<ConfigSchemeGroup>)

    Builds the registered-column test a document feed needs, from a set of columns.

    Declaration
    public static Func<InputBindingNode, bool> CreateDocumentSchemeFilter(IReadOnlyList<ConfigSchemeGroup> schemeGroups)
    Parameters
    Type Name Description
    IReadOnlyList<ConfigSchemeGroup> schemeGroups

    The declared columns.

    Returns
    Type Description
    Func<InputBindingNode, bool>

    A delegate reporting whether a binding sits in a declared column.

    Remarks

    Reproduces ScyllaInputBinding.BelongsToGroup, and has to keep doing so: this is the editor's feed and that is the game's, so the two disagreeing means the window reports conflicts the running game does not have, or misses ones it does. Both are now a token-wise test through InputBindingGroups.Contains, so a column named Keyboard does not match a binding in Keyboard&Mouse.

    A binding declaring no group is in every column, because it belongs to no scheme and therefore always participates.

    CreateDocumentScopeResolver(InputActionsDocument, ConfigLayout)

    Builds the scope lookup a document feed needs, from a config layout.

    Declaration
    public static Func<string, string, string> CreateDocumentScopeResolver(InputActionsDocument document, ConfigLayout layout)
    Parameters
    Type Name Description
    InputActionsDocument document

    The parsed document.

    ConfigLayout layout

    The config layout declaring the groups.

    Returns
    Type Description
    Func<string, string, string>

    A delegate mapping a map name and an action name to their scope key.

    Remarks

    Reproduces the live manager's group membership rules exactly, because a document that resolved scopes differently would report different conflicts than the game. An action claimed by two groups throws, an action claimed by none lands in UNGROUPED_ID.

    Membership is keyed by map and action together, since an action name is only unique within its map. A group naming actions rather than maps claims a bare name in every map that declares it, and a "MapName/ActionName" name in just the one map, which is the same reading InputRebindManager applies.

    Maps named by a group are looked up by name only, never by identifier. The live manager keys maps by name, so accepting an identifier here would let a layout resolve at edit time and silently fail to at run time.

    Exceptions
    Type Condition
    ArgumentNullException

    Thrown when the document or the layout is null.

    ArgumentException

    Thrown when two groups claim the same action.

    See Also

    InputConflictSet
    InputConflictEngine
    In this article
    Back to top Scylla Framework - Input Module API Documentation