Beispiel #1
0
 private static void SetFormat(InputControl control, InputControlLayout.ControlItem controlItem)
 {
     control.m_StateBlock.format = controlItem.format;
     if (controlItem.sizeInBits == 0)
     {
         var primitiveFormatSize = InputStateBlock.GetSizeOfPrimitiveFormatInBits(controlItem.format);
         if (primitiveFormatSize != -1)
         {
             control.m_StateBlock.sizeInBits = (uint)primitiveFormatSize;
         }
     }
 }
Beispiel #2
0
 private static void SetFormat(InputControl control, InputTemplate.ControlTemplate controlTemplate)
 {
     control.m_StateBlock.format = controlTemplate.format;
     if (controlTemplate.sizeInBits == 0)
     {
         var primitiveFormatSize = InputStateBlock.GetSizeOfPrimitiveFormatInBits(controlTemplate.format);
         if (primitiveFormatSize != -1)
         {
             control.m_StateBlock.sizeInBits = (uint)primitiveFormatSize;
         }
     }
 }
Beispiel #3
0
        private static void ComputeStateLayout(InputControl control)
        {
            var children = control.children;

            // If the control has a format but no size specified and the format is a
            // primitive format, just set the size automatically.
            if (control.m_StateBlock.sizeInBits == 0 && control.m_StateBlock.format != 0)
            {
                var sizeInBits = InputStateBlock.GetSizeOfPrimitiveFormatInBits(control.m_StateBlock.format);
                if (sizeInBits != -1)
                {
                    control.m_StateBlock.sizeInBits = (uint)sizeInBits;
                }
            }

            // If state size is not set, it means it's computed from the size of the
            // children so make sure we actually have children.
            if (control.m_StateBlock.sizeInBits == 0 && children.Count == 0)
            {
                throw new InvalidOperationException(
                          $"Control '{control.path}' with layout '{control.layout}' has no size set and has no children to compute size from");
            }

            // If there's no children, our job is done.
            if (children.Count == 0)
            {
                return;
            }

            // First deal with children that want fixed offsets. All the other ones
            // will get appended to the end.
            var firstUnfixedByteOffset = 0u;

            foreach (var child in children)
            {
                Debug.Assert(child.m_StateBlock.sizeInBits != 0, "Size of state block not set on child");

                // Skip children using state from other controls.
                if (child.m_StateBlock.sizeInBits == kSizeForControlUsingStateFromOtherControl)
                {
                    continue;
                }

                // Make sure the child has a valid size set on it.
                var childSizeInBits = child.m_StateBlock.sizeInBits;
                if (childSizeInBits == 0 || childSizeInBits == InputStateBlock.InvalidOffset)
                {
                    throw new InvalidOperationException(
                              $"Child '{child.name}' of '{control.name}' has no size set!");
                }

                // Skip children that don't have fixed offsets.
                if (child.m_StateBlock.byteOffset == InputStateBlock.InvalidOffset ||
                    child.m_StateBlock.byteOffset == InputStateBlock.AutomaticOffset)
                {
                    continue;
                }

                // At this point, if the child has no valid bit offset, put it at #0 now.
                if (child.m_StateBlock.bitOffset == InputStateBlock.InvalidOffset)
                {
                    child.m_StateBlock.bitOffset = 0;
                }

                // See if the control bumps our fixed layout size.
                var endOffset =
                    MemoryHelpers.ComputeFollowingByteOffset(child.m_StateBlock.byteOffset, child.m_StateBlock.bitOffset + childSizeInBits);
                if (endOffset > firstUnfixedByteOffset)
                {
                    firstUnfixedByteOffset = endOffset;
                }
            }

            ////TODO: this doesn't support mixed automatic and fixed layouting *within* bitfields;
            ////      I think it's okay not to support that but we should at least detect it

            // Now assign an offset to every control that wants an
            // automatic offset. For bitfields, we need to delay advancing byte
            // offsets until we've seen all bits in the fields.
            // NOTE: Bit addressing controls using automatic offsets *must* be consecutive.
            var          runningByteOffset       = firstUnfixedByteOffset;
            InputControl firstBitAddressingChild = null;
            var          bitfieldSizeInBits      = 0u;

            foreach (var child in children)
            {
                // Skip children with fixed offsets.
                if (child.m_StateBlock.byteOffset != InputStateBlock.InvalidOffset &&
                    child.m_StateBlock.byteOffset != InputStateBlock.AutomaticOffset)
                {
                    continue;
                }

                // Skip children using state from other controls.
                if (child.m_StateBlock.sizeInBits == kSizeForControlUsingStateFromOtherControl)
                {
                    continue;
                }

                // See if it's a bit addressing control.
                var isBitAddressingChild = (child.m_StateBlock.sizeInBits % 8) != 0;
                if (isBitAddressingChild)
                {
                    // Remember start of bitfield group.
                    if (firstBitAddressingChild == null)
                    {
                        firstBitAddressingChild = child;
                    }

                    // Keep a running count of the size of the bitfield.
                    if (child.m_StateBlock.bitOffset == InputStateBlock.InvalidOffset ||
                        child.m_StateBlock.bitOffset == InputStateBlock.AutomaticOffset)
                    {
                        // Put child at current bit offset.
                        child.m_StateBlock.bitOffset = bitfieldSizeInBits;

                        bitfieldSizeInBits += child.m_StateBlock.sizeInBits;
                    }
                    else
                    {
                        // Child already has bit offset. Keep it but make sure we're accounting for it
                        // in the bitfield size.
                        var lastBit = child.m_StateBlock.bitOffset + child.m_StateBlock.sizeInBits;
                        if (lastBit > bitfieldSizeInBits)
                        {
                            bitfieldSizeInBits = lastBit;
                        }
                    }
                }
                else
                {
                    // Terminate bitfield group (if there was one).
                    if (firstBitAddressingChild != null)
                    {
                        runningByteOffset       = MemoryHelpers.ComputeFollowingByteOffset(runningByteOffset, bitfieldSizeInBits);
                        firstBitAddressingChild = null;
                    }

                    if (child.m_StateBlock.bitOffset == InputStateBlock.InvalidOffset)
                    {
                        child.m_StateBlock.bitOffset = 0;
                    }
                }

                ////FIXME: seems like this should take bitOffset into account
                child.m_StateBlock.byteOffset = runningByteOffset;

                if (!isBitAddressingChild)
                {
                    runningByteOffset =
                        MemoryHelpers.ComputeFollowingByteOffset(runningByteOffset, child.m_StateBlock.sizeInBits);
                }
            }

            // Compute total size.
            // If we ended on a bitfield, account for its size.
            if (firstBitAddressingChild != null)
            {
                runningByteOffset = MemoryHelpers.ComputeFollowingByteOffset(runningByteOffset, bitfieldSizeInBits);
            }
            var totalSizeInBytes = runningByteOffset;

            // Set size. We force all parents to the combined size of their children.
            control.m_StateBlock.sizeInBits = totalSizeInBytes * 8;
        }