Пример #1
0
        /// <summary>
        /// Checks if a key in the map matches the specified key
        /// </summary>
        /// <param name="inBaseAddress">The base address of the map</param>
        /// <param name="inKeyValue">The key to find within the map</param>
        /// <returns>True if the key is found, false otherwise</returns>
        public bool HasKey(IntPtr inBaseAddress, string inKeyValue)
        {
            for (int index = 0, itemsLeft = Num(); itemsLeft > 0; ++index)
            {
                if (IsValidIndex(index))
                {
                    --itemsLeft;

                    IntPtr pairPtr = GetPairPtr(index);
                    IntPtr keyPtr  = Native_UProperty.ContainerVoidPtrToValuePtr(keyProp, pairPtr, 0);

                    using (FStringUnsafe keyValueUnsafe = new FStringUnsafe())
                    {
                        if (keyPtr != inBaseAddress && Native_UProperty.ExportText_Direct(keyProp, ref keyValueUnsafe.Array,
                                                                                          keyPtr, keyPtr, IntPtr.Zero, 0, IntPtr.Zero))
                        {
                            // Should this be case insensitive? (FString by default is case insensitive)
                            if ((Native_UObjectBaseUtility.IsA(keyProp, Classes.UObjectProperty) &&
                                 keyValueUnsafe.Value.Contains(inKeyValue)) || inKeyValue == keyValueUnsafe.Value)
                            {
                                return(true);
                            }
                        }
                    }
                }
            }

            return(false);
        }
Пример #2
0
        public TScriptInterface(T value)
        {
            IntPtr interfaceClass = UClass.GetInterfaceClassAddress <T>();

            if (interfaceClass == IntPtr.Zero)
            {
                Base = default(FScriptInterface);
                return;
            }

            IntPtr objectPointer = value.GetAddress();

            if (objectPointer == IntPtr.Zero)
            {
                Base = default(FScriptInterface);
                return;
            }

            IntPtr interfacePointer = Native_UObjectBaseUtility.GetNativeInterfaceAddress(objectPointer, interfaceClass);

            if (interfacePointer == IntPtr.Zero)
            {
                Base = default(FScriptInterface);
                return;
            }

            Base = new FScriptInterface(objectPointer, interfacePointer);
        }
Пример #3
0
        private static bool IsValidInternal(IntPtr property)
        {
            if (Native_UObjectBaseUtility.IsA(property, Classes.UBoolProperty))
            {
                return(false);
            }

            if (Native_UObjectBaseUtility.IsA(property, Classes.UTextProperty))
            {
                return(false);
            }

            if (!Native_UObjectBaseUtility.IsA(property, Classes.UStructProperty))
            {
                // even object or class types can be hashed, no reason to investigate further
                return(true);
            }

            IntPtr unrealStruct = Native_UStructProperty.Get_Struct(property);

            if (unrealStruct != IntPtr.Zero && Native_UObjectBaseUtility.IsA(unrealStruct, Classes.UScriptStruct))
            {
                return(StructHasGetTypeHash(unrealStruct));
            }

            return(false);
        }
Пример #4
0
        /// <summary>
        /// Checks if an element has already been added to the set
        /// </summary>
        /// <param name="inBaseAddress">The base address of the set</param>
        /// <param name="inElementValue">The element value to check for</param>
        /// <returns>True if the element is found in the set, false otherwise</returns>
        public bool HasElement(IntPtr inBaseAddress, string inElementValue)
        {
            for (int index = 0, itemsLeft = Num(); itemsLeft > 0; ++index)
            {
                if (IsValidIndex(index))
                {
                    --itemsLeft;

                    IntPtr element = GetElementPtr(index);

                    using (FStringUnsafe keyValueUnsafe = new FStringUnsafe())
                    {
                        if (element != inBaseAddress && Native_UProperty.ExportText_Direct(elementProp, ref keyValueUnsafe.Array,
                                                                                           element, element, IntPtr.Zero, 0, IntPtr.Zero))
                        {
                            // Should this be case insensitive? (FString by default is case insensitive)
                            if ((Native_UObjectBaseUtility.IsA(elementProp, Classes.UObjectProperty) &&
                                 keyValueUnsafe.Value.Contains(inElementValue)) || inElementValue == keyValueUnsafe.Value)
                            {
                                return(true);
                            }
                        }
                    }
                }
            }

            return(false);
        }
Пример #5
0
        private static bool StructHasGetTypeHash(IntPtr unrealStruct)
        {
            if (Native_UObjectBaseUtility.IsNative(unrealStruct))
            {
                IntPtr cppStructOps = Native_UScriptStruct.GetCppStructOps(unrealStruct);
                return(cppStructOps != IntPtr.Zero && Native_ICppStructOps.HasGetTypeHash(cppStructOps));
            }
            else
            {
                // if every member can be hashed (or is a UBoolProperty, which is specially
                // handled by UScriptStruct::GetStructTypeHash) then we can hash the struct:

                var fieldIterator = new NativeReflection.NativeFieldIterator(Classes.UProperty, unrealStruct);
                foreach (IntPtr property in fieldIterator)
                {
                    if (Native_UObjectBaseUtility.IsA(property, Classes.UBoolProperty))
                    {
                        continue;
                    }
                    else
                    {
                        if (!PropertyHasGetTypeHash(property))
                        {
                            return(false);
                        }
                    }
                }
                return(true);
            }
        }
Пример #6
0
        private void MoveToTransientPackage(IntPtr obj)
        {
            // Copy of UObjectBase.cpp UClassCompiledInDefer

            // Check if rooted?
            Native_UObjectBaseUtility.RemoveFromRoot(obj);
            Native_UObjectBaseUtility.ClearFlags(obj, EObjectFlags.Standalone | EObjectFlags.Public);

            IntPtr defaultObject = Native_UClass.GetDefaultObject(obj, false);

            if (defaultObject != IntPtr.Zero)
            {
                // Check if rooted?
                Native_UObjectBaseUtility.RemoveFromRoot(defaultObject);
                Native_UObjectBaseUtility.ClearFlags(defaultObject, EObjectFlags.Standalone | EObjectFlags.Public);
            }

            FName oldClassRename = NativeReflection.MakeUniqueObjectName(NativeReflection.GetTransientPackage(),
                                                                         Native_UObjectBase.GetClass(obj), new FName("USharpHotReload_" + Native_UObjectBase.GetFName(obj)));

            using (FStringUnsafe oldClassRenameUnsafe = new FStringUnsafe(oldClassRename.ToString()))
            {
                Native_UObject.Rename(obj, ref oldClassRenameUnsafe.Array, NativeReflection.GetTransientPackage(), ERenameFlags.None);
            }

            Native_UObjectBaseUtility.SetFlags(obj, EObjectFlags.Transient);
            Native_UObjectBaseUtility.AddToRoot(obj);
        }
Пример #7
0
            /// <summary>
            /// Finds the first native (non-managed) class for this managed class. This also caches the native parent
            /// class constructor for calling the parent constructor and setting it as the fallback constructor on hotreload.
            /// </summary>
            public void ResolveNativeParentClass()
            {
                NativeParentClassConstructor = IntPtr.Zero;
                if (Address == IntPtr.Zero)
                {
                    return;
                }

                // We could possibly update this code to do a deep search for the first non-C# class (e.g. C# : X : C# : X : UObject).
                // We aren't currently calling the parent constructor in a way which would allow this. If we supported it as-is the C#
                // constructors would get called multiple times when calling the parent constructor.

                IntPtr parentClass = Native_UClass.GetSuperClass(Address);

                while (parentClass != IntPtr.Zero)
                {
                    if (!Native_UObjectBaseUtility.IsA(parentClass, Runtime.Classes.USharpClass))
                    {
                        NativeParentClass            = parentClass;
                        NativeParentClassConstructor = Native_UClass.Get_ClassConstructor(parentClass);
                        break;
                    }
                    parentClass = Native_UClass.GetSuperClass(parentClass);
                }
                Debug.Assert(NativeParentClass != IntPtr.Zero);
            }
Пример #8
0
 /// <summary>
 /// Returns the name of this object (with no path information)
 /// </summary>
 /// <returns>Name of the object.</returns>
 public string GetName()
 {
     using (FStringUnsafe resultUnsafe = new FStringUnsafe())
     {
         Native_UObjectBaseUtility.GetName(Address, ref resultUnsafe.Array);
         return(resultUnsafe.Value);
     }
 }
Пример #9
0
 /// <summary>
 /// Walks up the chain of packages until it reaches the top level, which it ignores.
 /// </summary>
 /// <param name="startWithOuter"></param>
 /// <returns></returns>
 public string GetFullGroupName(bool startWithOuter)
 {
     using (FStringUnsafe resultUnsafe = new FStringUnsafe())
     {
         Native_UObjectBaseUtility.GetFullGroupName(Address, startWithOuter, ref resultUnsafe.Array);
         return(resultUnsafe.Value);
     }
 }
Пример #10
0
 /// <summary>
 /// Returns the fully qualified pathname for this object, in the format:
 /// 'Outermost[.Outer].Name'
 /// </summary>
 /// <param name="stopOuter">if specified, indicates that the output string should be relative to this object.  if StopOuter
 /// does not exist in this object's Outer chain, the result would be the same as passing NULL.</param>
 /// <returns></returns>
 public string GetPathName(UObject stopOuter = null)
 {
     using (FStringUnsafe resultUnsafe = new FStringUnsafe())
     {
         Native_UObjectBaseUtility.GetPathName(Address, stopOuter == null ? IntPtr.Zero : stopOuter.Address, ref resultUnsafe.Array);
         return(resultUnsafe.Value);
     }
 }
Пример #11
0
        public static unsafe void HackVTable(UObject obj)
        {
            // This will swap out the vtable entry and store the old one in our managed UClass

            if (!Native_UObjectBaseUtility.IsA(obj.Address, Runtime.Classes.UClass))
            {
                UClass unrealClass = obj.GetClass();
                if (unrealClass.VTableOriginalFunctions == null)
                {
                    IntPtr *vtable = *(IntPtr **)obj.Address;

                    unrealClass.VTableOriginalFunctions = new Dictionary <int, UClass.VTableOriginalFunc>();
                    foreach (FunctionRedirect redirect in vtableRedirects)
                    {
                        if (!Native_UObjectBaseUtility.IsA(obj.Address, redirect.Class))
                        {
                            continue;
                        }

                        IntPtr originalFunctionAddress = vtable[redirect.VTableIndex];

                        if (originalFunctionAddress != redirect.NativeCallback)
                        {
                            IntPtr originalOwnerClassAddress = FindOriginalVTableOwner(
                                redirect.Class, unrealClass.Address, originalFunctionAddress, redirect.VTableIndex);

                            if (originalOwnerClassAddress != unrealClass.Address)
                            {
                                UClass originalOwnerClass = GCHelper.Find <UClass>(originalOwnerClassAddress);
                                if (originalOwnerClass.VTableOriginalFunctions == null)
                                {
                                    HackVTable(originalOwnerClass.GetDefaultObject());
                                }
                            }

                            IntPtr pageAlignedPtr = FMemory.PageAlignPointer((IntPtr)(&vtable[redirect.VTableIndex]));
                            FMemory.PageProtect(pageAlignedPtr, (IntPtr)IntPtr.Size, true, true);
                            *(&vtable[redirect.VTableIndex]) = redirect.NativeCallback;
                        }
                        else
                        {
                            // The VTable has already been swapped out. Find the original function address.
                            UClass superClass = unrealClass;
                            while ((superClass = superClass.GetSuperClass()) != null && superClass.VTableOriginalFunctions == null)
                            {
                            }

                            Debug.Assert(superClass != null && superClass.VTableOriginalFunctions != null &&
                                         superClass.VTableOriginalFunctions.ContainsKey(redirect.VTableIndex));

                            originalFunctionAddress = superClass.VTableOriginalFunctions[redirect.VTableIndex].FuncAddress;
                        }

                        unrealClass.VTableOriginalFunctions.Add(redirect.VTableIndex, new UClass.VTableOriginalFunc(originalFunctionAddress));
                    }
                }
            }
        }
Пример #12
0
        private static void SetAllMetaData(IntPtr obj, ManagedUnrealReflectionBase field, UMeta.Target target)
        {
            if (!FBuild.WithEditor || !metaDataEnabled || field == null || string.IsNullOrEmpty(field.Path))
            {
                return;
            }

            IntPtr outermost = Native_UObjectBaseUtility.GetOutermost(obj);
            IntPtr metadata  = outermost == IntPtr.Zero ? IntPtr.Zero : Native_UPackage.GetMetaData(outermost);

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

            Dictionary <FName, string> values = null;

            if (!metaDataMap.TryGetValue(field.Path.ToLower(), out values))
            {
                values = new Dictionary <FName, string>();
            }

            switch (target)
            {
            // Class / interface
            case UMeta.Target.Class:
            case UMeta.Target.Interface:
                // See GetMetadataKeyword (Engine\Source\Programs\UnrealHeaderTool\Private\BaseParser.cpp)
                // "NotBlueprintable" removes "NotBlueprintable" and adds "IsBlueprintBase=false"
                // "Blueprintable" and adds "IsBlueprintBase=true"
                // "BlueprintInternalUseOnly" adds "BlueprintType"

                if (!values.ContainsKey(UMeta.GetKeyName(MDClass.IsBlueprintBase)))
                {
                    if (values.ContainsKey(UMeta.GetKeyName(MDClass.Blueprintable)))
                    {
                        values[UMeta.GetKeyName(MDClass.IsBlueprintBase)] = "true";
                    }
                    else if (values.ContainsKey(UMeta.GetKeyName(MDClass.NotBlueprintable)))
                    {
                        values[UMeta.GetKeyName(MDClass.IsBlueprintBase)] = "false";
                    }
                }

                MetaDataMergeClassCategories(metadata, obj, values);
                break;
            }
            SetMetaDataBlueprintability(values, target, field as ManagedUnrealTypeInfo);

            using (TArrayUnsafe <FName> keysUnsafe = new TArrayUnsafe <FName>())
                using (TArrayUnsafe <string> valuesUnsafe = new TArrayUnsafe <string>())
                {
                    keysUnsafe.AddRange(values.Keys.ToArray());
                    valuesUnsafe.AddRange(values.Values.ToArray());
                    Native_UMetaData.SetObjectValues(metadata, obj, keysUnsafe.Address, valuesUnsafe.Address);
                }
        }
Пример #13
0
        private IntPtr FindFirstNonUSharpClassParentClass(IntPtr unrealClass)
        {
            IntPtr sharpStaticClass = Native_USharpClass.StaticClass();

            while (unrealClass != IntPtr.Zero && !Native_UObjectBaseUtility.IsA(unrealClass, sharpStaticClass))
            {
                unrealClass = Native_UClass.GetSuperClass(unrealClass);
            }
            return(unrealClass);
        }
Пример #14
0
        public bool IsA(Type type)
        {
            UClass unrealClass = UClass.GetClass(type);

            if (unrealClass == null)
            {
                return(false);
            }
            return(Native_UObjectBaseUtility.IsA(Address, unrealClass.Address));
        }
Пример #15
0
        private IntPtr FindFirstNativeParentClass(IntPtr unrealClass)
        {
            IntPtr sharpStaticClass = Native_USharpClass.StaticClass();

            while (unrealClass != IntPtr.Zero && (!Native_UClass.HasAnyClassFlags(unrealClass, EClassFlags.Native) ||
                                                  Native_UObjectBaseUtility.IsA(unrealClass, sharpStaticClass)))
            {
                unrealClass = Native_UClass.GetSuperClass(unrealClass);
            }
            return(unrealClass);
        }
Пример #16
0
        private IntPtr CreateProperty(IntPtr outer, PropertyInfo propertyInfo)
        {
            // Note that HeaderParser.cpp and UObjectGlobals.cpp use "new" instead of NewObject for creating properties
            // KismetCompilerMisc.cpp uses NewObject
            // The "new" initialization sets the offset and adds the property to the owner which in the case of UStruct
            // does the following:
            // void UStruct::AddCppProperty(UProperty* Property) { Property->Next = Children; Children = Property; }

            USharpPathAttribute pathAttribute = propertyInfo.GetCustomAttribute <USharpPathAttribute>();

            if (pathAttribute == null)
            {
                return(IntPtr.Zero);
            }

            string root, directory, moduleName, typeName, propertyName;

            FPackageName.GetPathInfo(pathAttribute.Path, out root, out directory, out moduleName, out typeName, out propertyName);
            if (string.IsNullOrEmpty(propertyName))
            {
                return(IntPtr.Zero);
            }

            IntPtr property = CreateProperty(outer, propertyInfo.PropertyType, propertyName, pathAttribute.PropertyType,
                                             pathAttribute.InnerPropertyType1, pathAttribute.InnerPropertyType2);

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

            if (FBuild.WithMetaData)
            {
                IntPtr outermost = Native_UObjectBaseUtility.GetOutermost(property);
                IntPtr metadata  = outermost == IntPtr.Zero ? IntPtr.Zero : Native_UPackage.GetMetaData(outermost);

                if (metadata != IntPtr.Zero)
                {
                    string categoryName = null;
                    //propertyInfo.GetCustomAttribute

                    if (string.IsNullOrEmpty(categoryName))
                    {
                        categoryName = "Default";
                    }

                    SetMetaData(metadata, property, "Category", categoryName);
                }
            }

            return(property);
        }
Пример #17
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;

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

                fields.Clear();

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

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

                return(fields.TryGetValue(fieldName, out fieldInfo));
            }
        }
Пример #18
0
        private void Constructor(IntPtr objectInitializerPtr)
        {
            Native_UClass.Call_ClassConstructor(ParentClass, objectInitializerPtr);
            FObjectInitializer objectInitializer = new FObjectInitializer(objectInitializerPtr);

            IntPtr sharpStaticClass = Native_USharpClass.StaticClass();
            IntPtr unrealClass      = Native_FObjectInitializer.GetClass(objectInitializerPtr);
            IntPtr sharpClass       = unrealClass;

            while (sharpClass != IntPtr.Zero && !Native_UObjectBaseUtility.IsA(sharpClass, sharpStaticClass))
            {
                sharpClass = Native_UClass.GetSuperClass(sharpClass);
            }

            System.Diagnostics.Debug.Assert(sharpClass != IntPtr.Zero);
        }
Пример #19
0
        /// <summary>
        /// Returns true if this object is of the template type.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns>true if this object is of the template type.</returns>
        public bool IsA <T>() where T : UObject
        {
            // NOTE: Removing this check for now as it hides logic where IsChildOf should be used instead of IsA and as such
            //       the native could would return false here.
            // First do a managed check rather than resolving the UClass and doing a native IsA call
            //if (this is T)
            //{
            //    return true;
            //}

            UClass unrealClass = UClass.GetClass <T>();

            if (unrealClass == null)
            {
                return(false);
            }
            return(Native_UObjectBaseUtility.IsA(Address, unrealClass.Address));
        }
Пример #20
0
        public static unsafe void Unload()
        {
            foreach (FunctionRedirect redirect in vtableRedirects)
            {
                using (FStringUnsafe dummyNameUnsafe = new FStringUnsafe(redirect.DummyName))
                {
                    Native_VTableHacks.Set_VTableCallback(ref dummyNameUnsafe.Array, IntPtr.Zero);
                }
            }

            // Restore the old vtable entry on hotreload. This is important as otherwise we would lose the original function address
            // which is stored in the managed UClass (which gets destroyed on hotreload)
            foreach (IntPtr objAddress in new NativeReflection.NativeObjectIterator(Runtime.Classes.UObject, EObjectFlags.NoFlags))
            {
                foreach (FunctionRedirect redirect in vtableRedirects)
                {
                    if (!Native_UObjectBaseUtility.IsA(objAddress, redirect.Class))
                    {
                        continue;
                    }

                    IntPtr *vtable = *(IntPtr **)objAddress;
                    if (vtable[redirect.VTableIndex] == redirect.NativeCallback)
                    {
                        UObject obj = GCHelper.Find(objAddress);
                        Debug.Assert(obj != null);

                        UClass unrealClass = obj.GetClass();
                        Debug.Assert(unrealClass != null);

                        UClass.VTableOriginalFunc originalFunc;
                        if (unrealClass.VTableOriginalFunctions != null &&
                            unrealClass.VTableOriginalFunctions.TryGetValue(redirect.VTableIndex, out originalFunc))
                        {
                            IntPtr pageAlignedPtr = FMemory.PageAlignPointer((IntPtr)(&vtable[redirect.VTableIndex]));
                            FMemory.PageProtect(pageAlignedPtr, (IntPtr)IntPtr.Size, true, true);
                            *(&vtable[redirect.VTableIndex]) = originalFunc.FuncAddress;
                        }
                    }
                }
            }
        }
Пример #21
0
        /// <summary>
        /// Validates that the given property exists and matches the given UProperty class (e.g. UBoolProperty::StaticClass())
        /// </summary>
        /// <param name="unrealStruct">The address of the structure which owns the property</param>
        /// <param name="propertyName">The name of the property</param>
        /// <param name="propertyClass">The expected UProperty class of the property</param>
        /// <returns></returns>
        public static bool ValidatePropertyClass(IntPtr unrealStruct, string propertyName, IntPtr propertyClass)
        {
            IntPtr field = FindField(unrealStruct, propertyName);

            if (field == IntPtr.Zero || !Native_UObjectBaseUtility.IsA(field, Classes.UProperty))
            {
                return(false);
            }
            IntPtr actualClass = Native_UObjectBase.GetClass(field);

            if (actualClass == propertyClass)
            {
                return(true);
            }
            if (actualClass != IntPtr.Zero && propertyClass == Classes.UEnumProperty &&
                Native_UStruct.IsChildOf(actualClass, Classes.UNumericProperty))
            {
                return(Native_UNumericProperty.IsEnum(field));
            }
            return(false);
        }
Пример #22
0
 /// <summary>
 /// Returns whether this component was instanced from a component/subobject template, or if it is a component/subobject template.
 /// This is based on a name comparison with the outer class instance lookup table
 /// </summary>
 /// <returns>true if this component was instanced from a template.  false if this component was created manually at runtime.</returns>
 public bool IsDefaultSubobject()
 {
     return(Native_UObjectBaseUtility.IsDefaultSubobject(Address));
 }
Пример #23
0
 /// <summary>
 /// Returns a pointer to the I* native interface object that this object implements.
 /// Returns NULL if this object does not implement InterfaceClass, or does not do so natively.
 /// </summary>
 /// <param name="interfaceClass"></param>
 /// <returns></returns>
 public IntPtr GetNativeInterfaceAddress(UClass interfaceClass)
 {
     return(Native_UObjectBaseUtility.GetNativeInterfaceAddress(Address, interfaceClass == null ? IntPtr.Zero : interfaceClass.Address));
 }
Пример #24
0
 /// <summary>
 /// Finds the most-derived class which is a parent of both TestClass and this object's class.
 /// </summary>
 /// <param name="testClass"></param>
 /// <returns>the class to find the common base for</returns>
 public UClass FindNearestCommonBaseClass(UClass testClass)
 {
     return(GCHelper.Find <UClass>(Native_UObjectBaseUtility.FindNearestCommonBaseClass(Address, testClass == null ? IntPtr.Zero : testClass.Address)));
 }
Пример #25
0
 /// <summary>
 /// Returns true if this object is of the given type.
 /// </summary>
 /// <param name="someBaseClass"></param>
 /// <returns>true if this object is of the given type.</returns>
 public bool IsA(UClass someBaseClass)
 {
     return(Native_UObjectBaseUtility.IsA(Address, someBaseClass == null ? IntPtr.Zero : someBaseClass.Address));
 }
Пример #26
0
 /// <summary>
 /// Returns true if the specified object appears somewhere in this object's outer chain.
 /// </summary>
 /// <param name="someOuter"></param>
 /// <returns></returns>
 public bool IsIn(UObject someOuter)
 {
     return(Native_UObjectBaseUtility.IsIn(Address, someOuter == null ? IntPtr.Zero : someOuter.Address));
 }
Пример #27
0
 /// <summary>
 /// Traverses the outer chain searching for the next object of a certain type.  (T must be derived from UObject)
 /// </summary>
 /// <param name="target">class to search for</param>
 /// <returns>a pointer to the first object in this object's Outer chain which is of the correct type.</returns>
 public UObject GetTypedOuter(UClass target)
 {
     return(GCHelper.Find(Native_UObjectBaseUtility.GetTypedOuter(Address, target == null ? IntPtr.Zero : target.Address)));
 }
Пример #28
0
        /// <summary>
        /// Checks if the given UScriptStruct address is POD and has a zero constructor (initializes to zero).
        ///
        /// NOTE: A struct could be PlainOldData but unsafe to zero initialize due to having a non-zero constructor / EForceInit constructor.
        /// </summary>
        internal static bool IsPODZeroInit(IntPtr unrealStruct)
        {
            if (unrealStruct != IntPtr.Zero && Native_UObjectBaseUtility.IsA(unrealStruct, Classes.UScriptStruct))
            {
                EStructFlags structFlags = Native_UScriptStruct.Get_StructFlags(unrealStruct);

                IntPtr cppStructOps = Native_UScriptStruct.GetCppStructOps(unrealStruct);
                if (cppStructOps != IntPtr.Zero)
                {
                    bool isPlainOldData     = Native_ICppStructOps.IsPlainOldData(cppStructOps);
                    bool hasZeroConstructor = Native_ICppStructOps.HasZeroConstructor(cppStructOps);
                    bool hasNoopConstructor = Native_ICppStructOps.HasNoopConstructor(cppStructOps);

                    if (!hasZeroConstructor && structFlags.HasFlag(EStructFlags.ZeroConstructor))
                    {
                        // This struct flag could have been set in the zero constructor check in UScriptStruct::PrepareCppStructOps
                        hasZeroConstructor = true;
                    }

                    if (isPlainOldData && hasZeroConstructor && !hasNoopConstructor)
                    {
                        return(true);
                    }

                    if (isPlainOldData && !hasZeroConstructor)
                    {
                        if (hasNoopConstructor)
                        {
                            // The struct has a no-op constructor and takes EForceInit to init
                            return(false);
                        }

                        // This is a copy of a check made in UScriptStruct::PrepareCppStructOps to check if the struct constructs to zero
                        // if (CppStructOps->IsPlainOldData() && !CppStructOps->HasZeroConstructor()) { ... }

                        int    size   = Native_ICppStructOps.GetSize(cppStructOps);
                        IntPtr buffer = FMemory.Malloc(size);
                        FMemory.Memzero(buffer, size);
                        Native_ICppStructOps.Construct(cppStructOps, buffer);
                        Native_ICppStructOps.Construct(cppStructOps, buffer);// slightly more like to catch "internal counters" if we do this twice

                        bool isZeroConstruct = true;
                        unsafe
                        {
                            byte *bufferPtr = (byte *)buffer;
                            for (int i = 0; i < size; i++)
                            {
                                if (bufferPtr[i] != 0)
                                {
                                    isZeroConstruct = false;
                                    break;
                                }
                            }
                        }

                        FMemory.Free(buffer);

                        if (isZeroConstruct)
                        {
                            // "Native struct %s has DISCOVERED zero construction. Size = %d"
                            System.Diagnostics.Debugger.Break();
                            return(true);
                        }
                    }
                    return(false);
                }
                else
                {
                    // Only treat it as blittable if it is POD and has a zero constructor
                    return(structFlags.HasFlag(EStructFlags.IsPlainOldData | EStructFlags.ZeroConstructor));
                }
            }
            return(false);
        }
Пример #29
0
        private static unsafe IntPtr OnAdd(IntPtr native)
        {
            UObjectRef objRef = null;
            int        objectInternalIndex = *(int *)(native + objectInternalIndexOffset);

#if ARRAY_GC
            while (References.Count <= objectInternalIndex)
            {
                References.Add(null);
            }
            if (References[objectInternalIndex] == null)
#else
            if (!References.TryGetValue(native, out objRef))
#endif
            {
                bool isKnownType;
                Type type = UClass.GetFirstKnownType(native, out isKnownType, false);
                if (type == null)
                {
                    // This probably means the given address is not valid (check IsValid/IsValidLowLevel/IsValidLowLevelFast ?)
                    string className = string.Empty;
                    string fullName  = string.Empty;
                    try
                    {
                        using (FStringUnsafe classNameUnsafe = new FStringUnsafe())
                        {
                            Native_UObjectBaseUtility.GetName(Native_UObjectBase.GetClass(native), ref classNameUnsafe.Array);
                            className = classNameUnsafe.Value;
                        }
                    }
                    catch
                    {
                    }
                    try
                    {
                        using (FStringUnsafe fullNameUnsafe = new FStringUnsafe())
                        {
                            Native_UObjectBaseUtility.GetFullName(native, IntPtr.Zero, ref fullNameUnsafe.Array);
                            fullName = fullNameUnsafe.Value;
                        }
                    }
                    catch
                    {
                    }
                    // Get a smaller stack snippet
                    StackTrace stack = null;
                    try
                    {
                        stack = new StackTrace(4);
                    }
                    catch
                    {
                    }
                    string error = string.Format("[GCHelper-Error] Couldn't find type for requested UObject. Address: {0} (0x{1}) Name: \"{2}\" FullName: \"{3}\" Stack:\r\n{4}",
                                                 native.ToInt32(), native.ToInt32().ToString("X8"), className, fullName, stack);
                    FMessage.Log(ELogVerbosity.Error, error);
                    Debug.Assert(false, error);
                    return(IntPtr.Zero);
                }
                if (type.IsInterface)
                {
                    // Validate that we are getting a UInterface and we aren't doing something very wrong.
                    Debug.Assert(Native_UObjectBaseUtility.IsA(native, UClass.GetClassAddress(type)));

                    // This should be a UInterface instance. We might want to do something more complex here
                    // where interfaces inherit from other interfaces.
                    type = typeof(UInterface);
                }
                objRef = objRefPool.New(native, type, isKnownType, objectInternalIndex);
#if ARRAY_GC
                References[objectInternalIndex] = objRef;
#else
                References.Add(native, objRef);
#endif
                return(GCHandle.ToIntPtr(objRef.ManagedHandle));
            }
            return(GCHandle.ToIntPtr(objRef.ManagedHandle));
        }
Пример #30
0
 /// <summary>
 /// Checks whether this object's top-most package has any of the specified flags
 /// </summary>
 /// <param name="checkFlagMask">a bitmask of EPackageFlags values to check for</param>
 /// <returns></returns>
 public bool RootPackageHasAnyFlags(EPackageFlags checkFlagMask)
 {
     return(Native_UObjectBaseUtility.RootPackageHasAnyFlags(Address, checkFlagMask));
 }