Exemplo n.º 1
0
        public static ushort GetPropertyRepIndex(IntPtr unrealStruct, string propertyName)
        {
            IntPtr property = FindField(unrealStruct, propertyName);

            return(property == IntPtr.Zero ? (ushort)0 : Native_UProperty.Get_RepIndex(property));
        }
Exemplo n.º 2
0
            private unsafe void HandleInvokeFunctionFromBP(IntPtr obj, FFrame stack, IntPtr result,
                                                           UFunction.FuncInvokerManaged managedFunctionInvoker)
            {
                // NOTE: ScriptCore.cpp uses PropertiesSize instead of ParamsSize. Is it ever any different? (it says alignment
                // may make them different) If it is different we should probably use PropertiesSize (including in generated code /
                // IL) as ScriptCore.cpp uses a memcpy of our memory.
                Debug.Assert(Native_UStruct.Get_PropertiesSize(stack.CurrentNativeFunction) ==
                             Native_UFunction.Get_ParmsSize(stack.CurrentNativeFunction));

                IntPtr function     = stack.CurrentNativeFunction;
                int    paramsSize   = Native_UFunction.Get_ParmsSize(function);
                int    numParams    = Native_UFunction.Get_NumParms(function);
                bool   hasOutParams = Native_UFunction.HasAnyFunctionFlags(function, EFunctionFlags.HasOutParms);

                IntPtr *outParamsBufferPtr = stackalloc IntPtr[numParams];

                byte * paramsBufferPtr = stackalloc byte[paramsSize];
                IntPtr paramsBuffer    = (IntPtr)paramsBufferPtr;

                // We could skip this memzero as stackalloc will (always?) zero memory even though the spec states
                // "The content of the newly allocated memory is undefined."
                // https://github.com/dotnet/coreclr/issues/1279
                FMemory.Memzero(paramsBuffer, paramsSize);

                if (hasOutParams)
                {
                    int paramIndex = 0;
                    foreach (IntPtr param in new NativeReflection.NativeFieldIterator(Runtime.Classes.UProperty, function, false))
                    {
                        // Not required but using for Debug.Assert() when getting the value
                        stack.MostRecentPropertyAddress = IntPtr.Zero;

                        stack.Step(stack.Object, paramsBuffer + Native_UProperty.GetOffset_ForUFunction(param));
                        outParamsBufferPtr[paramIndex] = stack.MostRecentPropertyAddress;

                        if (Native_UProperty.HasAnyPropertyFlags(param, EPropertyFlags.ReturnParm))
                        {
                            // This should be UObject::execEndFunctionParms which will just do "stack->Code--;" for allowing
                            // the caller to use PFINISH aftwards
                            outParamsBufferPtr[paramIndex] = result;
                        }

                        paramIndex++;
                    }
                }
                else
                {
                    foreach (IntPtr param in new NativeReflection.NativeFieldIterator(Runtime.Classes.UProperty, function, false))
                    {
                        stack.Step(stack.Object, paramsBuffer + Native_UProperty.GetOffset_ForUFunction(param));
                    }
                }
                stack.PFinish();// Skip EX_EndFunctionParms

                // Call the managed function invoker which will marshal the params from the native params buffer and then call the
                // target managed function
                managedFunctionInvoker(paramsBuffer, obj);

                // Copy out params from the temp buffer
                //if (hasOutParams) // 4.20 DestructorLink change (see below)
                {
                    int paramIndex = 0;
                    foreach (IntPtr paramProp in new NativeReflection.NativeFieldIterator(Runtime.Classes.UProperty, function, false))
                    {
                        EPropertyFlags paramFlags = Native_UProperty.GetPropertyFlags(paramProp);

                        if ((paramFlags & EPropertyFlags.OutParm) == EPropertyFlags.OutParm &&
                            (paramFlags & EPropertyFlags.ConstParm) != EPropertyFlags.ConstParm)
                        {
                            Debug.Assert(outParamsBufferPtr[paramIndex] != IntPtr.Zero);

                            // - See "REMOVING the DestroyValue call" below.
                            // Destroy the existing memory (this assumed the existing memory is valid or at least memzerod)
                            //Native_UProperty.DestroyValue(paramProp, outParamsBufferPtr[paramIndex]);

                            // A raw memcpy should be OK since the managed invoker should have set this memory appropriately.
                            FMemory.Memcpy(outParamsBufferPtr[paramIndex],
                                           paramsBuffer + Native_UProperty.GetOffset_ForUFunction(paramProp),
                                           Native_UProperty.Get_ElementSize(paramProp));// Should be ArrayDim*ElementSize but ArrayDim should always be 1 for params
                        }
                        else
                        {
                            // 4.20 the original DestructorLink code doesn't work as expected (did it ever work?). DestructorLink seems to only be
                            // used on delegate functions (e.g. /Script/Engine.ActorOnClickedSignature__DelegateSignature).
                            // - For now call destroy everything other than out params (is this safe?)
                            // - TODO: Replace this with custom Stack.Code stepping as described above?
                            Native_UProperty.DestroyValue_InContainer(paramProp, paramsBuffer);
                        }

                        paramIndex++;
                    }
                }

                // Parameters are copied when calling stack->Step(). We are responsible for destroying non-blittable types
                // which were copied (FString, TArray, etc). For C++ this works out well due to the copy constructors etc.
                //
                // Example where an FString is constructed from stack->Step():
                // UObject::execStringConst(...) { *(FString*)RESULT_PARAM = (ANSICHAR*)Stack.Code; }
                //
                // For C# it might be better if we reimplemented all of the IMPLEMENT_VM_FUNCTION functions to reduce the amount
                // of copying as we currently need ANOTHER copy to get it from the temp buffer into a C# type (which is done
                // inside the managedFunctionInvoker function)

                /*foreach (IntPtr paramProp in new NativeReflection.NativeFieldIterator(Runtime.Classes.UProperty, function,
                 *  EFieldIteratorType.Destructor, false))
                 * {
                 *  // When is this ever false? It seems to be checked in UObject::ProcessEvent()
                 *  // "Destroy local variables except function parameters." - used for BP locals?
                 *  Debug.Assert(Native_UProperty.IsInContainer(paramProp, paramsSize));
                 *
                 *  // Out params are copied to the memory maintained by the caller so only destroy "by value" parameters.
                 *  if (!Native_UProperty.HasAnyPropertyFlags(paramProp, EPropertyFlags.OutParm))
                 *  {
                 *      Native_UProperty.DestroyValue_InContainer(paramProp, paramsBuffer);
                 *  }
                 * }*/
            }
Exemplo n.º 3
0
 /// <summary>
 /// Return offset of property from container base.
 /// </summary>
 /// <returns></returns>
 public int GetOffset_ForUFunction()
 {
     return(Native_UProperty.GetOffset_ForUFunction(Address));
 }
Exemplo n.º 4
0
 /// <summary>
 /// Returns the replication owner, which is the property itself, or NULL if this isn't important for replication.
 /// It is relevant if the property is a net relevant and not being run in the editor
 /// </summary>
 /// <returns></returns>
 public UProperty GetRepOwner()
 {
     return(GCHelper.Find <UProperty>(Native_UProperty.GetRepOwner(Address)));
 }
Exemplo n.º 5
0
 /// <summary>
 /// returns true, if Other is property of exactly the same type
 /// </summary>
 /// <param name="other"></param>
 /// <returns></returns>
 public bool SameType(UProperty other)
 {
     return(Native_UProperty.SameType(Address, other == null ? IntPtr.Zero : other.Address));
 }
Exemplo n.º 6
0
 /// <summary>
 /// Returns this property's propertyflags
 /// </summary>
 /// <returns></returns>
 public EPropertyFlags GetPropertyFlags()
 {
     return(Native_UProperty.GetPropertyFlags(Address));
 }
Exemplo n.º 7
0
 public void ClearPropertyFlags(EPropertyFlags newFlags)
 {
     Native_UProperty.ClearPropertyFlags(Address, newFlags);
 }
Exemplo n.º 8
0
 /// <summary>
 /// Copy the value for a single element of this property.
 /// </summary>
 /// <param name="dest">the address where the value should be copied to.  This should always correspond to the BASE + OFFSET + INDEX * SIZE, where
 ///     BASE = (for member properties) the address of the UObject which contains this data, (for locals/parameters) the address of the space allocated for the function's locals
 ///     OFFSET = the Offset of this UProperty
 ///     INDEX = the index that you want to copy.  for properties which are not arrays, this should always be 0
 ///     SIZE = the ElementSize of this UProperty</param>
 /// <param name="src">the address of the value to copy from. should be evaluated the same way as Dest</param>
 public void CopySingleValue(IntPtr dest, IntPtr src)
 {
     Native_UProperty.CopySingleValue(Address, dest, src);
 }
Exemplo n.º 9
0
 /// <summary>
 /// Return offset of property from container base.
 /// </summary>
 public int GetOffset_ForInternal()
 {
     return(Native_UProperty.GetOffset_ForInternal(Address));
 }
Exemplo n.º 10
0
 /// <summary>
 /// See if the offset of this property is below the supplied container size
 /// </summary>
 /// <param name="containerSize"></param>
 /// <returns></returns>
 public bool IsInContainer(int containerSize)
 {
     return(Native_UProperty.IsInContainer(Address, containerSize));
 }
Exemplo n.º 11
0
 /// <summary>
 /// See if the offset of this property is below the supplied container size
 /// </summary>
 /// <param name="containerClass"></param>
 /// <returns></returns>
 public bool IsInContainer(UStruct containerClass)
 {
     return(Native_UProperty.IsInContainerStruct(Address, containerClass.Address));
 }
Exemplo n.º 12
0
 public IntPtr ContainerPtrToValuePtrForDefaults(UStruct containerClass, IntPtr container, int arrayIndex = 0)
 {
     return(Native_UProperty.ContainerVoidPtrToValuePtrForDefaults(Address, containerClass.Address, container, arrayIndex));
 }
Exemplo n.º 13
0
 private static bool PropertyHasGetTypeHash(IntPtr property)
 {
     return(Native_UProperty.HasAllPropertyFlags(property, EPropertyFlags.HasGetValueTypeHash));
 }
Exemplo n.º 14
0
        private IntPtr CreateProperty(IntPtr outer, Type type, string propertyName, EPropertyType propertyType,
                                      EPropertyType innerPropertyType1, EPropertyType innerPropertyType2)
        {
            propertyType = ManagedUnrealTypes.GetPropertyType(type, propertyType);

            IntPtr propertyClass = ManagedUnrealTypes.GetPropertyClass(propertyType);

            if (propertyClass == IntPtr.Zero)
            {
                return(IntPtr.Zero);
            }

            EObjectFlags objectFlags = EObjectFlags.Public | EObjectFlags.Transient | EObjectFlags.MarkAsNative;
            IntPtr       property    = NativeReflection.NewObject(outer, propertyClass, new FName(propertyName), objectFlags);

            Native_UProperty.SetPropertyFlags(property, EPropertyFlags.BlueprintVisible | EPropertyFlags.BlueprintAssignable | EPropertyFlags.Edit);

            // Set type specific information
            switch (propertyType)
            {
            case EPropertyType.Array:
                if (!firstRun)
                {
                    Native_UArrayProperty.Set_Inner(property,
                                                    CreateProperty(property, typeof(int), propertyName, innerPropertyType1));
                }
                else
                {
                    Native_UArrayProperty.Set_Inner(property,
                                                    CreateProperty(property, type.GenericTypeArguments[0], propertyName, innerPropertyType1));
                }
                break;

            case EPropertyType.Set:
                Native_USetProperty.Set_ElementProp(property,
                                                    CreateProperty(property, type.GenericTypeArguments[0], propertyName, innerPropertyType1));
                break;

            case EPropertyType.Map:
                Native_UMapProperty.Set_KeyProp(property,
                                                CreateProperty(property, type.GenericTypeArguments[0], propertyName, innerPropertyType1));
                Native_UMapProperty.Set_ValueProp(property,
                                                  CreateProperty(property, type.GenericTypeArguments[1], propertyName, innerPropertyType2));
                break;

            case EPropertyType.Class:
                Native_UClassProperty.SetMetaClass(property, UClass.GetClass(type.GenericTypeArguments[0]).Address);
                break;

            case EPropertyType.Object:
                var v1 = ManagedUnrealTypes.GetStaticClass(type);
                var v2 = ManagedUnrealTypes.GetStaticClass(typeof(UObject));
                Native_UObjectPropertyBase.SetPropertyClass(property, v1 == IntPtr.Zero ? v2 : v1);
                break;

            case EPropertyType.LazyObject:
            case EPropertyType.WeakObject:
            case EPropertyType.SoftObject:
                Native_UObjectPropertyBase.SetPropertyClass(property, UClass.GetClass(type.GenericTypeArguments[0]).Address);
                break;

            case EPropertyType.SoftClass:
                Native_USoftClassProperty.SetMetaClass(property, UClass.GetClass(type.GenericTypeArguments[0]).Address);
                break;

            case EPropertyType.Enum:
                Native_UEnumProperty.SetEnum(property, ManagedUnrealTypes.GetEnum(type));
                break;

            case EPropertyType.Delegate:
                //Native_UDelegateProperty.Set_SignatureFunction(property, ManagedUnrealTypes.GetSignatureFunction(type));
                break;

            case EPropertyType.MulticastDelegate:
                //Native_UMulticastDelegateProperty.Set_SignatureFunction(property, ManagedUnrealTypes.GetSignatureFunction(type));
                break;
            }

            Native_UField.AddCppProperty(outer, property);

            return(property);
        }
Exemplo n.º 15
0
 public int GetSize()
 {
     return(Native_UProperty.GetSize(Address));
 }
Exemplo n.º 16
0
 /// <summary>
 /// Return offset of property from container base.
 /// </summary>
 /// <returns></returns>
 public int GetOffset_ReplaceWith_ContainerPtrToValuePtr()
 {
     return(Native_UProperty.GetOffset_ReplaceWith_ContainerPtrToValuePtr(Address));
 }
Exemplo n.º 17
0
 /// <summary>
 /// Determines whether this property value is eligible for copying when duplicating an object
 /// </summary>
 /// <returns>true if this property value should be copied into the duplicate object</returns>
 public bool ShouldDuplicateValue()
 {
     return(Native_UProperty.ShouldDuplicateValue(Address));
 }
Exemplo n.º 18
0
 /// <summary>
 /// Get the pointer to property value in a supplied 'container'.
 /// You can _only_ call this function on a UObject* or a uint8*. If the property you want is a 'top level' UObject property, you _must_
 /// call the function passing in a UObject* and not a uint8*. There are checks inside the function to vertify this.
 /// </summary>
 /// <param name="container">UObject* or uint8* to container of property value</param>
 /// <param name="arrayIndex">In array case, index of array element we want</param>
 /// <returns></returns>
 public IntPtr ContainerPtrToValuePtr(IntPtr container, int arrayIndex = 0)
 {
     return(Native_UProperty.ContainerVoidPtrToValuePtr(Address, container, arrayIndex));
 }
Exemplo n.º 19
0
 public void SetPropertyFlags(EPropertyFlags newFlags)
 {
     Native_UProperty.SetPropertyFlags(Address, newFlags);
 }
Exemplo n.º 20
0
 public uint GetValueTypeHash(IntPtr src)
 {
     return(Native_UProperty.GetValueTypeHash(Address, src));
 }
Exemplo n.º 21
0
 /// <summary>
 /// Used to safely check whether all of the passed in flags are set. This is required
 /// as PropertyFlags currently is a 64 bit data type and bool is a 32 bit data type so
 /// simply using PropertyFlags&CPF_MyFlagBiggerThanMaxInt won't work correctly when
 /// assigned directly to an bool.
 /// </summary>
 /// <param name="flagsToCheck">Object flags to check for</param>
 /// <returns>true if all of the passed in flags are set (including no flags passed in), false otherwise</returns>
 public bool HasAllPropertyFlags(EPropertyFlags flagsToCheck)
 {
     return(Native_UProperty.HasAllPropertyFlags(Address, flagsToCheck));
 }
Exemplo n.º 22
0
 public bool ShouldPort(uint portFlags)
 {
     return(Native_UProperty.ShouldPort(Address, portFlags));
 }
Exemplo n.º 23
0
 /// <summary>
 /// Editor-only properties are those that only are used with the editor is present or cannot be removed from serialisation.
 /// Editor-only properties include: EditorOnly properties
 /// Properties that cannot be removed from serialisation are:
 ///     Boolean properties (may affect GCC_BITFIELD_MAGIC computation)
 ///     Native properties (native serialisation)
 /// </summary>
 /// <returns></returns>
 public bool IsEditorOnlyProperty()
 {
     return(Native_UProperty.IsEditorOnlyProperty(Address));
 }
Exemplo n.º 24
0
 public int GetMinAlignment()
 {
     return(Native_UProperty.GetMinAlignment(Address));
 }
Exemplo n.º 25
0
        public bool Update(IntPtr address)
        {
            if (Address != address)
            {
                Address             = address;
                Size                = 0;
                ArrayDim            = 0;
                IsEditConst         = false;
                IsBlueprintReadOnly = false;
                GenericArg1Address  = IntPtr.Zero;
                GenericArg1Size     = 0;
                GenericArg1ArrayDim = 0;
                GenericArg2Address  = IntPtr.Zero;
                GenericArg2Size     = 0;
                GenericArg2ArrayDim = 0;
                PropertyType        = EPropertyType.Unknown;

                if (address == IntPtr.Zero)
                {
                    return(true);
                }

                EPropertyType propertyType = NativeReflection.GetPropertyType(address);
                if (propertyType != EPropertyType.Unknown)
                {
                    PropertyType = propertyType;

                    Size     = Native_UProperty.Get_ElementSize(address);
                    ArrayDim = Native_UProperty.Get_ArrayDim(address);

                    IsEditConst         = Native_UProperty.HasAnyPropertyFlags(address, EPropertyFlags.EditConst);
                    IsBlueprintReadOnly = Native_UProperty.HasAnyPropertyFlags(address, EPropertyFlags.BlueprintReadOnly);

                    switch (propertyType)
                    {
                    case EPropertyType.Array:
                        GenericArg1Address = Native_UArrayProperty.Get_Inner(address);
                        if (GenericArg1Address != IntPtr.Zero)
                        {
                            GenericArg1Size     = Native_UProperty.Get_ElementSize(GenericArg1Address);
                            GenericArg1ArrayDim = Native_UProperty.Get_ArrayDim(GenericArg1Address);
                        }
                        break;

                    case EPropertyType.Map:
                        GenericArg1Address = Native_UMapProperty.Get_KeyProp(address);
                        if (GenericArg1Address != IntPtr.Zero)
                        {
                            GenericArg1Size     = Native_UProperty.Get_ElementSize(GenericArg1Address);
                            GenericArg1ArrayDim = Native_UProperty.Get_ArrayDim(GenericArg1Address);
                        }
                        GenericArg2Address = Native_UMapProperty.Get_ValueProp(address);
                        if (GenericArg2Address != IntPtr.Zero)
                        {
                            GenericArg2Size     = Native_UProperty.Get_ElementSize(GenericArg2Address);
                            GenericArg2ArrayDim = Native_UProperty.Get_ArrayDim(GenericArg2Address);
                        }
                        break;

                    case EPropertyType.Set:
                        GenericArg1Address = Native_USetProperty.Get_ElementProp(address);
                        if (GenericArg1Address != IntPtr.Zero)
                        {
                            GenericArg1Size     = Native_UProperty.Get_ElementSize(GenericArg1Address);
                            GenericArg1ArrayDim = Native_UProperty.Get_ArrayDim(GenericArg1Address);
                        }
                        break;
                    }
                }

                return(true);
            }
            return(false);
        }
Exemplo n.º 26
0
 /// <summary>
 /// Returns true if this property, or in the case of e.g. array or struct properties any sub- property, contains a
 /// weak UObject reference.
 /// </summary>
 /// <returns>true if property (or sub- properties) contain a weak UObject reference, false otherwise</returns>
 public bool ContainsWeakObjectReference()
 {
     return(Native_UProperty.ContainsWeakObjectReference(Address));
 }
Exemplo n.º 27
0
 public bool PassCPPArgsByRef()
 {
     return(Native_UProperty.PassCPPArgsByRef(Address));
 }
Exemplo n.º 28
0
 /// <summary>
 /// Returns true if this property, or in the case of e.g. array or struct properties any sub- property, contains a
 /// UObject reference that is marked CPF_NeedCtorLink (i.e. instanced keyword).
 /// </summary>
 /// <returns>true if property (or sub- properties) contain a UObjectProperty that is marked CPF_NeedCtorLink, false otherwise</returns>
 public bool ContainsInstancedObjectProperty()
 {
     return(Native_UProperty.ContainsInstancedObjectProperty(Address));
 }
Exemplo n.º 29
0
 /// <summary>
 /// Return offset of property from container base.
 /// </summary>
 /// <returns></returns>
 public int GetOffset_ForGC()
 {
     return(Native_UProperty.GetOffset_ForGC(Address));
 }
Exemplo n.º 30
0
        private static bool FindFieldInfo(IntPtr typeClass, IntPtr unrealStruct, string fieldName, out CachedFieldInfo fieldInfo)
        {
            if (typeClass == IntPtr.Zero || unrealStruct == IntPtr.Zero || string.IsNullOrEmpty(fieldName))
            {
                fieldInfo = default(CachedFieldInfo);
                return(false);
            }

            if (unrealStruct == lastUnrealStruct)
            {
                return(lastUnrealStructChildren.TryGetValue(fieldName, out fieldInfo));
            }
            else if (unrealStruct == lastUnrealFunction)
            {
                return(lastUnrealFunctionChildren.TryGetValue(fieldName, out fieldInfo));
            }
            else
            {
                Dictionary <string, CachedFieldInfo> fields = null;

                // For structs we want to get all fields in the hierarchy as we can't struct inheritance in C#
                // (C++ structs can have inheritance, if we skip checking the hierarchy we wont get all the fields we want)
                bool isScriptStruct = false;

                if (Native_UObjectBaseUtility.IsA(unrealStruct, Classes.UFunction))
                {
                    fields             = lastUnrealFunctionChildren;
                    lastUnrealFunction = unrealStruct;
                }
                else
                {
                    isScriptStruct   = Native_UObjectBaseUtility.IsA(unrealStruct, Classes.UScriptStruct);
                    fields           = lastUnrealStructChildren;
                    lastUnrealStruct = unrealStruct;
                }

                fields.Clear();



                foreach (IntPtr field in new NativeReflection.NativeFieldIterator(
                             EClassCastFlags.UFunction | EClassCastFlags.UProperty, unrealStruct, false, isScriptStruct))
                {
                    Native_UObjectBaseUtility.GetNameOut(field, ref nameUnsafe.Array);
                    string name = nameUnsafe.Value;

                    // Temporary check for debugging purposes. There shouldn't be any duplicate fields as we aren't looking in the hierarchy.
                    if (System.Diagnostics.Debugger.IsAttached)
                    {
                        System.Diagnostics.Debug.Assert(!fields.ContainsKey(name));
                    }

                    fields[name] = new CachedFieldInfo()
                    {
                        Address = field,
                        Offset  = Native_UProperty.GetOffset_ForInternal(field)
                    };
                }

                return(fields.TryGetValue(fieldName, out fieldInfo));
            }
        }