Exemple #1
0
        private InputControl AddChildControl(InputControlLayout layout, InternedString variant, InputControl parent,
                                             ReadOnlyArray <InputControl>?existingChildren, ref bool haveChildrenUsingStateFromOtherControls,
                                             ref InputControlLayout.ControlItem controlItem, ref int childIndex, string nameOverride = null)
        {
            var    name          = nameOverride ?? controlItem.name;
            var    nameLowerCase = name.ToLower();
            var    nameInterned  = new InternedString(name);
            string path          = null;

            ////REVIEW: can we check this in InputControlLayout instead?
            if (string.IsNullOrEmpty(controlItem.layout))
            {
                throw new Exception(string.Format("Layout has not been set on control '{0}' in '{1}'",
                                                  controlItem.name, layout.name));
            }

            // See if there is an override for the control.
            InputControlLayout.ControlItem?controlOverride = null;
            if (m_ChildControlOverrides != null)
            {
                path = string.Format("{0}/{1}", parent.path, name);
                var pathLowerCase = path.ToLower();

                InputControlLayout.ControlItem match;
                if (m_ChildControlOverrides.TryGetValue(pathLowerCase, out match))
                {
                    controlOverride = match;
                }
            }

            // Get name of layout to use for control.
            var layoutName = controlItem.layout;

            if (controlOverride != null && !controlOverride.Value.layout.IsEmpty())
            {
                layoutName = controlOverride.Value.layout;
            }

            // See if we have an existing control that we might be able to re-use.
            InputControl existingControl = null;

            if (existingChildren != null)
            {
                var existingChildCount = existingChildren.Value.Count;
                for (var n = 0; n < existingChildCount; ++n)
                {
                    var existingChild = existingChildren.Value[n];
                    if (existingChild.layout == layoutName &&
                        existingChild.name.ToLower() == nameLowerCase)
                    {
                        existingControl = existingChild;
                        break;
                    }
                }
            }

            // Create control.
            InputControl control;

            try
            {
                control = InstantiateLayout(layoutName, variant, nameInterned, parent, existingControl);
            }
            catch (InputControlLayout.LayoutNotFoundException exception)
            {
                // Throw better exception that gives more info.
                throw new Exception(
                          string.Format("Cannot find layout '{0}' used in control '{1}' of layout '{2}'",
                                        exception.layout, name, layout.name),
                          exception);
            }

            // Add to array.
            m_Device.m_ChildrenForEachControl[childIndex] = control;
            ++childIndex;

            // Set display name.
            control.m_DisplayNameFromLayout = controlItem.displayName;

            // Set flags.
            control.m_IsNoisy = controlItem.isNoisy;

            // Pass state block config on to control.
            var usesStateFromOtherControl = !string.IsNullOrEmpty(controlItem.useStateFrom);

            if (!usesStateFromOtherControl)
            {
                control.m_StateBlock.byteOffset = controlItem.offset;
                if (controlItem.bit != InputStateBlock.kInvalidOffset)
                {
                    control.m_StateBlock.bitOffset = controlItem.bit;
                }
                if (controlItem.sizeInBits != 0)
                {
                    control.m_StateBlock.sizeInBits = controlItem.sizeInBits;
                }
                if (controlItem.format != 0)
                {
                    SetFormat(control, controlItem);
                }
            }
            else
            {
                // Mark controls that don't have state blocks of their own but rather get their
                // blocks from other controls by setting their state size to kInvalidOffset.
                control.m_StateBlock.sizeInBits         = kSizeForControlUsingStateFromOtherControl;
                haveChildrenUsingStateFromOtherControls = true;
            }

            ////REVIEW: the constant appending to m_UsagesForEachControl and m_AliasesForEachControl may lead to a lot
            ////        of successive re-allocations

            // Add usages.
            var usages = controlOverride != null ? controlOverride.Value.usages : controlItem.usages;

            if (usages.Count > 0)
            {
                var usageCount = usages.Count;
                var usageIndex =
                    ArrayHelpers.AppendToImmutable(ref m_Device.m_UsagesForEachControl, usages.m_Array);
                control.m_UsagesReadOnly =
                    new ReadOnlyArray <InternedString>(m_Device.m_UsagesForEachControl, usageIndex, usageCount);

                ArrayHelpers.GrowBy(ref m_Device.m_UsageToControl, usageCount);
                for (var n = 0; n < usageCount; ++n)
                {
                    m_Device.m_UsageToControl[usageIndex + n] = control;
                }
            }

            // Add aliases.
            if (controlItem.aliases.Count > 0)
            {
                var aliasCount = controlItem.aliases.Count;
                var aliasIndex =
                    ArrayHelpers.AppendToImmutable(ref m_Device.m_AliasesForEachControl, controlItem.aliases.m_Array);
                control.m_AliasesReadOnly =
                    new ReadOnlyArray <InternedString>(m_Device.m_AliasesForEachControl, aliasIndex, aliasCount);
            }

            // Set parameters.
            if (controlItem.parameters.Count > 0)
            {
                SetParameters(control, controlItem.parameters);
            }

            // Add processors.
            if (controlItem.processors.Count > 0)
            {
                AddProcessors(control, ref controlItem, layout.name);
            }

            return(control);
        }
Exemple #2
0
        private InputControl AddChildControl(InputControlLayout layout, InternedString variants, InputControl parent,
                                             ref bool haveChildrenUsingStateFromOtherControls,
                                             InputControlLayout.ControlItem controlItem,
                                             int childIndex, string nameOverride = null)
        {
            var name         = nameOverride ?? controlItem.name;
            var nameInterned = new InternedString(name);

            ////REVIEW: can we check this in InputControlLayout instead?
            if (string.IsNullOrEmpty(controlItem.layout))
            {
                throw new InvalidOperationException($"Layout has not been set on control '{controlItem.name}' in '{layout.name}'");
            }

            // See if there is an override for the control.
            if (m_ChildControlOverrides != null)
            {
                var path          = $"{parent.path}/{name}";
                var pathLowerCase = path.ToLower();

                if (m_ChildControlOverrides.TryGetValue(pathLowerCase, out var controlOverride))
                {
                    controlItem = controlOverride.Merge(controlItem);
                }
            }

            // Get name of layout to use for control.
            var layoutName = controlItem.layout;

            // Create control.
            InputControl control;

            try
            {
                control = InstantiateLayout(layoutName, variants, nameInterned, parent);
            }
            catch (InputControlLayout.LayoutNotFoundException exception)
            {
                // Throw better exception that gives more info.
                throw new InputControlLayout.LayoutNotFoundException(
                          $"Cannot find layout '{exception.layout}' used in control '{name}' of layout '{layout.name}'",
                          exception);
            }

            // Add to array.
            // NOTE: AddChildControls and InstantiateLayout take care of growing the array and making
            //       room for the immediate children of each control.
            m_Device.m_ChildrenForEachControl[childIndex] = control;

            // Set flags and misc things.
            control.noisy     = controlItem.isNoisy;
            control.synthetic = controlItem.isSynthetic;
            if (control.noisy)
            {
                m_Device.noisy = true;
            }

            // Remember the display names from the layout. We later do a proper pass once we have
            // the full hierarchy to set final names.
            control.m_DisplayNameFromLayout      = controlItem.displayName;
            control.m_ShortDisplayNameFromLayout = controlItem.shortDisplayName;

            // Set default value.
            control.m_DefaultState = controlItem.defaultState;
            if (!control.m_DefaultState.isEmpty)
            {
                m_Device.hasControlsWithDefaultState = true;
            }

            // Set min and max value. Don't just overwrite here as the control's constructor may
            // have set a default value.
            if (!controlItem.minValue.isEmpty)
            {
                control.m_MinValue = controlItem.minValue;
            }
            if (!controlItem.maxValue.isEmpty)
            {
                control.m_MaxValue = controlItem.maxValue;
            }

            // Pass state block config on to control.
            var usesStateFromOtherControl = !string.IsNullOrEmpty(controlItem.useStateFrom);

            if (!usesStateFromOtherControl)
            {
                control.m_StateBlock.byteOffset = controlItem.offset;
                control.m_StateBlock.bitOffset  = controlItem.bit;
                if (controlItem.sizeInBits != 0)
                {
                    control.m_StateBlock.sizeInBits = controlItem.sizeInBits;
                }
                if (controlItem.format != 0)
                {
                    SetFormat(control, controlItem);
                }
            }
            else
            {
                // Mark controls that don't have state blocks of their own but rather get their
                // blocks from other controls by setting their state size to InvalidOffset.
                control.m_StateBlock.sizeInBits         = kSizeForControlUsingStateFromOtherControl;
                haveChildrenUsingStateFromOtherControls = true;
            }

            ////REVIEW: the constant appending to m_UsagesForEachControl and m_AliasesForEachControl may lead to a lot
            ////        of successive re-allocations

            // Add usages.
            var usages = controlItem.usages;

            if (usages.Count > 0)
            {
                var usageCount = usages.Count;
                var usageIndex =
                    ArrayHelpers.AppendToImmutable(ref m_Device.m_UsagesForEachControl, usages.m_Array);
                control.m_UsageStartIndex = usageIndex;
                control.m_UsageCount      = usageCount;

                ArrayHelpers.GrowBy(ref m_Device.m_UsageToControl, usageCount);
                for (var n = 0; n < usageCount; ++n)
                {
                    m_Device.m_UsageToControl[usageIndex + n] = control;
                }
            }

            // Add aliases.
            if (controlItem.aliases.Count > 0)
            {
                var aliasCount = controlItem.aliases.Count;
                var aliasIndex =
                    ArrayHelpers.AppendToImmutable(ref m_Device.m_AliasesForEachControl, controlItem.aliases.m_Array);
                control.m_AliasStartIndex = aliasIndex;
                control.m_AliasCount      = aliasCount;
            }

            // Set parameters.
            if (controlItem.parameters.Count > 0)
            {
                NamedValue.ApplyAllToObject(control, controlItem.parameters);
            }

            // Add processors.
            if (controlItem.processors.Count > 0)
            {
                AddProcessors(control, ref controlItem, layout.name);
            }

            return(control);
        }
Exemple #3
0
        private InputControl AddChildControl(InputTemplate template, InternedString variant, InputControl parent,
                                             ReadOnlyArray <InputControl>?existingChildren, ref bool haveChildrenUsingStateFromOtherControls,
                                             ref InputTemplate.ControlTemplate controlTemplate, ref int childIndex, string nameOverride = null)
        {
            var name          = nameOverride ?? controlTemplate.name;
            var nameLowerCase = nameOverride != null?nameOverride.ToLower() : controlTemplate.name.ToLower();

            var nameInterned = nameOverride != null ? new InternedString(nameOverride) : controlTemplate.name;

            ////REVIEW: can we check this in InputTemplate instead?
            if (string.IsNullOrEmpty(controlTemplate.template))
            {
                throw new Exception(string.Format("Template has not been set on control '{0}' in '{1}'",
                                                  controlTemplate.name, template.name));
            }

            // See if we have an existing control that we might be able to re-use.
            InputControl existingControl = null;

            if (existingChildren != null)
            {
                var existingChildCount = existingChildren.Value.Count;
                for (var n = 0; n < existingChildCount; ++n)
                {
                    var existingChild = existingChildren.Value[n];
                    if (existingChild.template == controlTemplate.template &&
                        existingChild.name.ToLower() == nameLowerCase)
                    {
                        existingControl = existingChild;
                        break;
                    }
                }
            }

            // Create control.
            InputControl control;

            try
            {
                control = AddControl(controlTemplate.template, variant, nameInterned, parent, existingControl);
            }
            catch (InputTemplate.TemplateNotFoundException exception)
            {
                // Throw better exception that gives more info.
                throw new Exception(
                          string.Format("Cannot find template '{0}' used in control '{1}' of template '{2}'",
                                        exception.template, controlTemplate.name, template.name),
                          exception);
            }

            // Add to array.
            m_Device.m_ChildrenForEachControl[childIndex] = control;
            ++childIndex;

            // Set display name.
            control.m_DisplayNameFromTemplate = controlTemplate.displayName;

            // Pass state block config on to control.
            var usesStateFromOtherControl = !string.IsNullOrEmpty(controlTemplate.useStateFrom);

            if (!usesStateFromOtherControl)
            {
                control.m_StateBlock.byteOffset = controlTemplate.offset;
                if (controlTemplate.bit != InputStateBlock.kInvalidOffset)
                {
                    control.m_StateBlock.bitOffset = controlTemplate.bit;
                }
                if (controlTemplate.sizeInBits != 0)
                {
                    control.m_StateBlock.sizeInBits = controlTemplate.sizeInBits;
                }
                if (controlTemplate.format != 0)
                {
                    SetFormat(control, controlTemplate);
                }
            }
            else
            {
                // Mark controls that don't have state blocks of their own but rather get their
                // blocks from other controls by setting their state size to kInvalidOffset.
                control.m_StateBlock.sizeInBits         = kSizeForControlUsingStateFromOtherControl;
                haveChildrenUsingStateFromOtherControls = true;
            }

            ////REVIEW: the constant appending to m_UsagesForEachControl and m_AliasesForEachControl may lead to a lot
            ////        of successive re-allocations

            // Add usages.
            if (controlTemplate.usages.Count > 0)
            {
                var usageCount = controlTemplate.usages.Count;
                var usageIndex =
                    ArrayHelpers.AppendToImmutable(ref m_Device.m_UsagesForEachControl, controlTemplate.usages.m_Array);
                control.m_UsagesReadOnly =
                    new ReadOnlyArray <InternedString>(m_Device.m_UsagesForEachControl, usageIndex, usageCount);

                ArrayHelpers.GrowBy(ref m_Device.m_UsageToControl, usageCount);
                for (var n = 0; n < usageCount; ++n)
                {
                    m_Device.m_UsageToControl[usageIndex + n] = control;
                }
            }

            // Add aliases.
            if (controlTemplate.aliases.Count > 0)
            {
                var aliasCount = controlTemplate.aliases.Count;
                var aliasIndex =
                    ArrayHelpers.AppendToImmutable(ref m_Device.m_AliasesForEachControl, controlTemplate.aliases.m_Array);
                control.m_AliasesReadOnly =
                    new ReadOnlyArray <InternedString>(m_Device.m_AliasesForEachControl, aliasIndex, aliasCount);
            }

            // Set parameters.
            if (controlTemplate.parameters.Count > 0)
            {
                SetParameters(control, controlTemplate.parameters);
            }

            // Add processors.
            if (controlTemplate.processors.Count > 0)
            {
                AddProcessors(control, ref controlTemplate, template.name);
            }

            return(control);
        }