Example #1
0
        /// <summary>
        /// Dynamically invokes the function
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public object DynamicInvoke(UObject obj, params object[] parameters)
        {
            if (parameters == null)
            {
                parameters = new object[0];
            }

            bool validParams = true;

            Dictionary <UProperty, Delegate> fromNativeParams = new Dictionary <UProperty, Delegate>();
            Dictionary <UProperty, Delegate> toNativeParams   = new Dictionary <UProperty, Delegate>();

            UProperty        returnValueProp = null;
            List <UProperty> paramProps      = new List <UProperty>();

            foreach (UProperty prop in GetProperties <UProperty>())
            {
                if (prop.HasAnyPropertyFlags(EPropertyFlags.Parm))
                {
                    if (prop.HasAnyPropertyFlags(EPropertyFlags.ReturnParm))
                    {
                        returnValueProp = prop;
                    }
                    else
                    {
                        paramProps.Add(prop);
                    }

                    Type paramType = UProperty.GetTypeFromProperty(prop);
                    if (paramType == null)
                    {
                        validParams = false;
                        break;
                    }

                    Delegate fromNative = MarshalingDelegateResolverSlow.GetFromNative(paramType);
                    Delegate toNative   = MarshalingDelegateResolverSlow.GetToNative(paramType);
                    if (fromNative == null || toNative == null)
                    {
                        validParams = false;
                        break;
                    }

                    fromNativeParams.Add(prop, fromNative);
                    toNativeParams.Add(prop, toNative);
                }
            }

            if (parameters.Length != paramProps.Count)
            {
                validParams = false;
            }

            if (!validParams)
            {
                return(null);
            }

            // Sort the parameters by offset, this is assumingly the correct thing to do?
            // - Otherwise we need to take the param names into this function. Or just not sort at all?
            //paramProps.Sort((x, y) => x.GetOffset_ForUFunction().CompareTo(y.GetOffset_ForUFunction()));

            object result = null;

            unsafe
            {
                int    paramsSize             = ParmsSize;
                byte * paramsBufferAllocation = stackalloc byte[ParmsSize];
                IntPtr paramsBuffer           = new IntPtr(paramsBufferAllocation);
                FMemory.Memzero(paramsBuffer, paramsSize);

                // Initialize default values for all parameters
                foreach (UProperty prop in GetProperties <UProperty>())
                {
                    if (prop.HasAnyPropertyFlags(EPropertyFlags.Parm))
                    {
                        Native.Native_UProperty.InitializeValue_InContainer(prop.Address, paramsBuffer);
                    }
                }

                // Copy the managed parameters to the buffer
                for (int i = 0; i < parameters.Length; i++)
                {
                    UProperty paramProp  = paramProps[i];
                    object    paramValue = parameters[i];
                    if (paramValue != null && (!paramProp.HasAnyPropertyFlags(EPropertyFlags.OutParm) ||
                                               paramProp.HasAnyPropertyFlags(EPropertyFlags.ReferenceParm)))
                    {
                        toNativeParams[paramProp].DynamicInvoke(
                            paramsBuffer + paramProp.GetOffset_ForUFunction(), (int)0, paramProp.Address, paramValue);
                    }
                }

                // Invoke the function
                NativeReflection.InvokeFunction(obj.Address, Address, paramsBuffer, paramsSize);

                // Copy parameters / return value from the buffer
                for (int i = 0; i < parameters.Length; i++)
                {
                    UProperty paramProp = paramProps[i];
                    if (paramProp.HasAnyPropertyFlags(EPropertyFlags.OutParm))
                    {
                        parameters[i] = fromNativeParams[paramProp].DynamicInvoke(
                            paramsBuffer + paramProp.GetOffset_ForUFunction(), (int)0, paramProp.Address);
                    }
                }
                if (returnValueProp != null)
                {
                    result = fromNativeParams[returnValueProp].DynamicInvoke(
                        paramsBuffer + returnValueProp.GetOffset_ForUFunction(), (int)0, returnValueProp.Address);
                }

                // Destroy the memory for all of the parameters
                foreach (UProperty prop in GetProperties <UProperty>())
                {
                    if (prop.HasAnyPropertyFlags(EPropertyFlags.Parm))
                    {
                        Native.Native_UProperty.DestroyValue_InContainer(prop.Address, paramsBuffer);
                    }
                }
            }

            return(result);
        }
Example #2
0
 public static void AssertIfInConstructor(UObject outer)
 {
     AssertIfInConstructor(outer == null ? IntPtr.Zero : outer.Address);
 }
Example #3
0
 /// <summary>
 /// Asserts with the specified message if code is executed inside UObject constructor
 /// </summary>
 public static void AssertIfInConstructor(UObject outer, string errorMessage)
 {
     AssertIfInConstructor(outer == null ? IntPtr.Zero : outer.Address, errorMessage);
 }
Example #4
0
 /// <summary>
 /// Create a component or subobject
 /// </summary>
 /// <typeparam name="T">class of return type, all overrides must be of this type</typeparam>
 /// <param name="outer">outer to construct the subobject in</param>
 /// <param name="subobjectName">name of the new component</param>
 /// <param name="transient">true if the component is being assigned to a transient property</param>
 /// <returns></returns>
 public T CreateDefaultSubobject <T>(UObject outer, FName subobjectName, bool transient = false) where T : UObject
 {
     return(CreateDefaultSubobject <T, T>(outer, subobjectName, transient));
 }
Example #5
0
 /// <summary>
 /// reate a component or subobject
 /// </summary>
 /// <typeparam name="TReturnType">class of return type, all overrides must be of this type </typeparam>
 /// <typeparam name="TClassToConstructByDefault">class to construct by default</typeparam>
 /// <param name="outer">outer to construct the subobject in </param>
 /// <param name="subobjectName">name of the new component </param>
 /// <param name="transient">true if the component is being assigned to a transient property</param>
 /// <returns></returns>
 public TReturnType CreateDefaultSubobject <TReturnType, TClassToConstructByDefault>(UObject outer, FName subobjectName, bool transient = false)
     where TReturnType : UObject
     where TClassToConstructByDefault : UObject
 {
     return(CreateDefaultSubobject(outer, subobjectName, UClass.GetClass <TReturnType>(),
                                   UClass.GetClass <TClassToConstructByDefault>(), true, transient) as TReturnType);
 }
Example #6
0
 public static UObject FindImportedObject(UProperty property, UObject ownerObject, UObject objectClass, UClass requiredMetaClass, string text, uint portFlags)
 {
     using (FStringUnsafe textUnsafe = new FStringUnsafe(text))
     {
         return(GCHelper.Find(Native_UObjectPropertyBase.FindImportedObject(
                                  property == null ? IntPtr.Zero : property.Address,
                                  ownerObject == null ? IntPtr.Zero : ownerObject.Address,
                                  objectClass == null ? IntPtr.Zero : objectClass.Address,
                                  requiredMetaClass == null ? IntPtr.Zero : requiredMetaClass.Address,
                                  ref textUnsafe.Array,
                                  portFlags)));
     }
 }
Example #7
0
 /// <summary>
 /// Parses a text buffer into an object reference.
 /// </summary>
 /// <param name="property">the property that the value is being importing to</param>
 /// <param name="ownerObject">the object that is importing the value; used for determining search scope.</param>
 /// <param name="requiredMetaClass">the meta-class for the object to find; if the object that is resolved is not of this class type, the result is NULL.</param>
 /// <param name="portFlags">bitmask of EPropertyPortFlags that can modify the behavior of the search</param>
 /// <param name="buffer">the text to parse; should point to a textual representation of an object reference.  Can be just the object name (either fully
 /// fully qualified or not), or can be formatted as a const object reference (i.e. SomeClass'SomePackage.TheObject')
 /// When the function returns, Buffer will be pointing to the first character after the object value text in the input stream.</param>
 /// <param name="resolvedValue">receives the object that is resolved from the input text.</param>
 /// <returns>true if the text is successfully resolved into a valid object reference of the correct type, false otherwise.</returns>
 public static bool ParseObjectPropertyValue(UProperty property, UObject ownerObject, UClass requiredMetaClass, uint portFlags, string buffer, out UObject resolvedValue)
 {
     using (FStringUnsafe bufferUnsafe = new FStringUnsafe(buffer))
     {
         IntPtr outResolvedValueAddress = IntPtr.Zero;
         bool   result = Native_UObjectPropertyBase.ParseObjectPropertyValue(
             property == null ? IntPtr.Zero : property.Address,
             ownerObject == null ? IntPtr.Zero : ownerObject.Address,
             requiredMetaClass == null ? IntPtr.Zero : requiredMetaClass.Address,
             portFlags,
             ref bufferUnsafe.Array,
             ref outResolvedValueAddress);
         resolvedValue = GCHelper.Find(outResolvedValueAddress);
         return(result);
     }
 }
Example #8
0
 public void SetObjectPropertyValue_InContainer(IntPtr propertyValueAddress, UObject value, int arrayIndex)
 {
     Native_UObjectPropertyBase.SetObjectPropertyValue_InContainer(Address, propertyValueAddress,
                                                                   value == null ? IntPtr.Zero : value.Address, arrayIndex);
 }
Example #9
0
 public void SetObjectPropertyValue(IntPtr propertyValueAddress, UObject value)
 {
     Native_UObjectPropertyBase.SetObjectPropertyValue(Address, propertyValueAddress, value == null ? IntPtr.Zero : value.Address);
 }
Example #10
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(UObject container, int arrayIndex = 0)
 {
     return(ContainerUObjectPtrToValuePtr(container == null ? IntPtr.Zero : container.Address, arrayIndex));
 }