Esempio n. 1
0
        ////TODO: pass state ptr *NOT* value ptr (it's confusing)
        // We don't allow custom default values for state so all zeros indicates
        // default states for us.
        // NOTE: The given argument should point directly to the value *not* to the
        //       base state to which the state block offset has to be added.
        internal unsafe bool CheckStateIsAllZeros(IntPtr valuePtr = new IntPtr())
        {
            if (valuePtr == IntPtr.Zero)
            {
                valuePtr = new IntPtr(currentStatePtr.ToInt64() + (int)m_StateBlock.byteOffset);
            }

            // Bitfield value.
            if (m_StateBlock.sizeInBits % 8 != 0 || m_StateBlock.bitOffset != 0)
            {
                if (m_StateBlock.sizeInBits > 1)
                {
                    throw new NotImplementedException("multi-bit zero check");
                }

                return(BitfieldHelpers.ReadSingleBit(valuePtr, m_StateBlock.bitOffset) == false);
            }

            // Multi-byte value.
            var ptr      = (byte *)valuePtr;
            var numBytes = m_StateBlock.alignedSizeInBytes;

            for (var i = 0; i < numBytes; ++i, ++ptr)
            {
                if (*ptr != 0)
                {
                    return(false);
                }
            }

            return(true);
        }
Esempio n. 2
0
 public KeyboardState(params Key[] pressedKeys)
 {
     fixed(byte *keysPtr = keys)
     {
         UnsafeUtility.MemClear(new IntPtr(keysPtr), kSizeInBytes);
         for (var i = 0; i < pressedKeys.Length; ++i)
         {
             BitfieldHelpers.WriteSingleBit(new IntPtr(keysPtr), (uint)pressedKeys[i], true);
         }
     }
 }
Esempio n. 3
0
        private unsafe string ReadRawValueAsString(InputControl control)
        {
            fixed(byte *state = stateBuffer)
            {
                var ptr    = state + control.m_StateBlock.byteOffset - m_RootControl.m_StateBlock.byteOffset;
                var format = control.m_StateBlock.format;

                if (format == InputStateBlock.kTypeBit)
                {
                    if (BitfieldHelpers.ReadSingleBit(new IntPtr(ptr), control.m_StateBlock.bitOffset))
                    {
                        return("1");
                    }
                    return("0");
                }

                if (format == InputStateBlock.kTypeByte)
                {
                    return((*ptr).ToString());
                }

                if (format == InputStateBlock.kTypeShort)
                {
                    return((*((short *)ptr)).ToString());
                }

                if (format == InputStateBlock.kTypeInt)
                {
                    return((*((int *)ptr)).ToString());
                }

                if (format == InputStateBlock.kTypeFloat)
                {
                    return((*((float *)ptr)).ToString());
                }

                if (format == InputStateBlock.kTypeDouble)
                {
                    return((*((double *)ptr)).ToString());
                }

                return(null);
            }
        }
Esempio n. 4
0
        // Read a floating-point value from the given state. Automatically checks
        // the state format of the control and performs conversions.
        // NOTE: Throws if the format set on 'stateBlock' is not of integer, floating-point,
        //       or bitfield type.
        protected override unsafe float ReadRawValueFrom(IntPtr statePtr)
        {
            float value;
            var   valuePtr = new IntPtr(statePtr.ToInt64() + (int)m_StateBlock.byteOffset);

            var format = m_StateBlock.format;

            if (format == InputStateBlock.kTypeFloat)
            {
                value = *(float *)valuePtr;
            }
            else if (format == InputStateBlock.kTypeBit)
            {
                if (m_StateBlock.sizeInBits != 1)
                {
                    throw new NotImplementedException("Cannot yet convert multi-bit fields to floats");
                }

                value = BitfieldHelpers.ReadSingleBit(valuePtr, m_StateBlock.bitOffset) ? 1.0f : 0.0f;
            }
            // If a control with an integer-based representation does not use the full range
            // of its integer size (e.g. only goes from [0..128]), processors or the parameters
            // above have to be used to re-process the resulting float values.
            else if (format == InputStateBlock.kTypeShort)
            {
                value = *((short *)valuePtr) / 65535.0f;
            }
            else if (format == InputStateBlock.kTypeByte)
            {
                value = *((byte *)valuePtr) / 255.0f;
            }
            else
            {
                throw new Exception(string.Format("State format '{0}' is not supported as state for {1}",
                                                  m_StateBlock.format, GetType().Name));
            }

            return(Preprocess(value));
        }
Esempio n. 5
0
        private static void ComputeStateLayout(InputControl control)
        {
            var children = control.m_ChildrenReadOnly;

            // 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 Exception(
                          string.Format(
                              "Control '{0}' with template '{1}' has no size set but has no children to compute size from",
                              control.path, control.template));
            }

            // 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);

                // 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)
                {
                    throw new Exception(
                              string.Format("Child '{0}' of '{1}' has no size set!", child.name, control.name));
                }

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

                var endOffset =
                    BitfieldHelpers.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.kInvalidOffset)
                {
                    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.kInvalidOffset)
                    {
                        bitfieldSizeInBits += child.m_StateBlock.sizeInBits;
                    }
                    else
                    {
                        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       = BitfieldHelpers.ComputeFollowingByteOffset(runningByteOffset, bitfieldSizeInBits);
                        firstBitAddressingChild = null;
                    }
                }

                child.m_StateBlock.byteOffset = runningByteOffset;

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

            // Compute total size.
            // If we ended on a bitfield, account for its size.
            if (firstBitAddressingChild != null)
            {
                runningByteOffset = BitfieldHelpers.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;
        }