/// <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); }
public static void AssertIfInConstructor(UObject outer) { AssertIfInConstructor(outer == null ? IntPtr.Zero : outer.Address); }
/// <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); }
/// <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)); }
/// <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); }
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))); } }
/// <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); } }
public void SetObjectPropertyValue_InContainer(IntPtr propertyValueAddress, UObject value, int arrayIndex) { Native_UObjectPropertyBase.SetObjectPropertyValue_InContainer(Address, propertyValueAddress, value == null ? IntPtr.Zero : value.Address, arrayIndex); }
public void SetObjectPropertyValue(IntPtr propertyValueAddress, UObject value) { Native_UObjectPropertyBase.SetObjectPropertyValue(Address, propertyValueAddress, value == null ? IntPtr.Zero : value.Address); }
/// <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)); }