public T GetSubsystem <T>() where T : USubsystem { UClass uclass = UClass.GetClass(typeof(T)); IntPtr system = Native_FSubsystemCollection.GetSubsystem(this.Address, uclass.Address); return(GCHelper.Find <T>(system)); }
/// <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, false, transient) as TReturnType); }
/// <summary> /// Gets all objects, including class default objects. /// </summary> public static FObjectIterator GetObjectsEx <T>( bool onlyGCedObjects = false, EObjectFlags additionalExclusionFlags = EObjectFlags.NoFlags, EInternalObjectFlags internalExclusionFlags = EInternalObjectFlags.None) where T : UObject { return(GetObjectsEx(UClass.GetClass <T>(), onlyGCedObjects, additionalExclusionFlags, internalExclusionFlags)); }
private static T FindOrLoadObject <T>(string pathName) where T : UObject { if (typeof(T) == typeof(UPackage)) { return(FindOrLoadPackage(pathName) as T); } // If there is no dot, add a dot and repeat the object name. int packageDelimPos = pathName.IndexOf('.'); if (packageDelimPos == -1) { int objectNameStart = pathName.LastIndexOf('/'); if (objectNameStart != -1) { pathName += "." + pathName.Substring(objectNameStart + 1); } } UClass unrealClass = UClass.GetClass <T>(); if (unrealClass != null) { unrealClass.GetDefaultObject();// force the CDO to be created if it hasn't already T obj = UObject.LoadObject <T>(null, pathName); if (obj != null) { obj.AddToRoot(); } return(obj); } return(null); }
/// <summary> /// Returns the class UClass if it is loaded. It is not possible to load the class if it is unloaded since we only have the short name. /// </summary> /// <returns></returns> public UClass GetClass() { if (!IsValid) { return(null); } return(UClass.GetClass(AssetClass.ToString())); }
/// <summary> /// Returns true if this objects class implements the given IInterface derived type /// (call this on UObject instances; if you are working with a UClass call ImplementsInterface() instead).<para/> /// This is the equivalent of UKismetSystemLibrary::DoesImplementInterface(). /// This is also the same as obj.GetClass().ImplementsInterface(). /// </summary> /// <param name="type">The IInterface derived type</param> /// <returns>True if this objects class implements the given IInterface derived type</returns> public bool DoesImplementInterface(Type type) { UClass interfaceClass = UClass.GetClass(type); if (interfaceClass != null && interfaceClass.ClassFlags.HasFlag(EClassFlags.Interface)) { return(Native_UClass.ImplementsInterface(Native_UObjectBase.GetClass(Address), interfaceClass.Address)); } return(false); }
public FClassFinder(string classToFind) { CheckIfIsInConstructor(classToFind); string pathName = classToFind; StripObjectClass(ref pathName, true); Class = FindOrLoadClass(pathName, UClass.GetClass <T>()); ValidateObject(Class.Value, pathName, classToFind); }
/// <summary> /// Traverses the outer chain searching for the next object of a certain type. (T must be derived from UObject) /// </summary> /// <typeparam name="T">class to search for</typeparam> /// <returns>a pointer to the first object in this object's Outer chain which is of the correct type.</returns> public UObject GetTypedOuter <T>() where T : UObject { UClass unrealClass = UClass.GetClass <T>(); if (unrealClass != null) { return(GetTypedOuter(unrealClass)); } return(null); }
/// <summary> /// Invokes a UFunction of the given name using the CDO (class default object) /// </summary> public static object DynamicInvokeStatic <T>(string functionName, object[] parameters) where T : UObject { UClass unrealClass = UClass.GetClass <T>(); if (unrealClass != null) { return(DynamicInvokeStatic(unrealClass, functionName, parameters)); } return(null); }
/// <summary> /// Constructs a gameplay object /// </summary> /// <typeparam name="T">the object type</typeparam> /// <param name="outer">the outer for the new object. If not specified, object will be created in the transient package.</param> /// <param name="name">the name for the new object. If not specified, the object will be given a transient name via MakeUniqueObjectName</param> /// <param name="flags">the object flags to apply to the new object</param> /// <param name="template">the object to use for initializing the new object. If not specified, the class's default object will be used</param> /// <param name="copyTransientsFromClassDefaults">if true, copy transient from the class defaults instead of the pass in archetype ptr (often these are the same)</param> /// <param name="instanceGraph">contains the mappings of instanced objects and components to their templates</param> /// <returns>a pointer of type T to a new object of the specified class</returns> public static T NewObject <T>( ObjectOuter outer, FName name = default(FName), EObjectFlags flags = EObjectFlags.NoFlags, UObject template = null, bool copyTransientsFromClassDefaults = false, IntPtr instanceGraph = default(IntPtr)) where T : UObject { return(NewObject <T>(false, outer, UClass.GetClass <T>(), name, flags, template, copyTransientsFromClassDefaults, instanceGraph)); }
/// <summary> /// Get default object of a class. /// </summary> public static T GetDefault <T>() where T : UObject { UClass unrealClass = UClass.GetClass <T>(); if (unrealClass != null) { return(unrealClass.GetDefaultObject() as T); } return(null); }
public bool IsA(Type type) { UClass unrealClass = UClass.GetClass(type); if (unrealClass == null) { return(false); } return(Native_UObjectBaseUtility.IsA(Address, unrealClass.Address)); }
/// <summary> /// Find an object without asserting on GIsSavingPackage or IsGarbageCollecting() /// </summary> public static T FindObjectSafe <T>(ObjectOuter outer, string name, bool exactClass = false) where T : UObject { UClass unrealClass = UClass.GetClass <T>(); using (FStringUnsafe nameUnsafe = new FStringUnsafe(name)) { return(GCHelper.Find <T>(Native_UObjectGlobals.StaticFindObjectSafe( unrealClass == null ? IntPtr.Zero : unrealClass.Address, outer.Address, ref nameUnsafe.Array, exactClass))); } }
/// <summary> /// Load a class object. /// </summary> public static UClass LoadClass <T>(ObjectOuter outer, string name, string filename, ELoadFlags loadFlags = ELoadFlags.None) { UClass unrealClass = UClass.GetClass <T>(); using (FStringUnsafe nameUnsafe = new FStringUnsafe(name)) using (FStringUnsafe filenameUnsafe = new FStringUnsafe(filename)) { return(GCHelper.Find <UClass>(Native_UObjectGlobals.StaticLoadClass( unrealClass == null ? IntPtr.Zero : unrealClass.Address, outer.Address, ref nameUnsafe.Array, ref filenameUnsafe.Array, loadFlags, IntPtr.Zero))); } }
/// <summary> /// Find an optional object, relies on the name being unqualified /// </summary> public static T FindObjectFast <T>( ObjectOuter outer, FName name, bool exactClass = false, bool anyPackage = false, EObjectFlags exclusiveFlags = EObjectFlags.NoFlags, EInternalObjectFlags exclusiveInternalFlags = EInternalObjectFlags.None) where T : UObject { UClass unrealClass = UClass.GetClass <T>(); return(GCHelper.Find <T>(Native_UObjectGlobals.StaticFindObjectFast( unrealClass == null ? IntPtr.Zero : unrealClass.Address, outer.Address, ref name, exactClass, anyPackage, exclusiveFlags, exclusiveInternalFlags))); }
public FObjectIterator(UClass unrealClass, bool onlyGCedObjects = false, EObjectFlags additionalExclusionFlags = EObjectFlags.NoFlags, EInternalObjectFlags internalExclusionFlags = EInternalObjectFlags.None) { objectArrayPtr = Native_FUObjectArray.GetGUObjectArray(); index = -1; this.unrealClass = unrealClass; this.exclusionFlags = additionalExclusionFlags; this.internalExclusionFlags = internalExclusionFlags; if (this.unrealClass == UClass.GetClass <UObject>()) { // Set to null to avoid additional UClass checks if this already the UObject class this.unrealClass = null; } }
public TFieldIterator(UStruct unrealStruct, EFieldIteratorType iteratorType, bool includeSuper = true, bool includeDeprecated = true, bool includeInterface = false) { typeClass = UClass.GetClass <T>(); targetStruct = unrealStruct; this.iteratorType = iteratorType; this.unrealStruct = unrealStruct; field = GetField(unrealStruct); interfaceIndex = -1; this.includeSuper = includeSuper; this.includeDeprecated = includeDeprecated; this.includeInterface = includeInterface && unrealStruct as UClass != null; first = true; }
private static T NewObject <T>( bool checkClass, ObjectOuter outer, UClass unrealClass, FName name = default(FName), EObjectFlags flags = EObjectFlags.NoFlags, UObject template = null, bool copyTransientsFromClassDefaults = false, IntPtr instanceGraph = default(IntPtr)) where T : UObject { if (unrealClass == null) { return(null); } if (!outer.IsAnyPackage && outer.Object == null) { outer.Object = GetTransientPackage(); } if (name == FName.None) { FObjectInitializer.AssertIfInConstructor(outer.Object); } if (checkClass) { // DO_CHECK // Class was specified explicitly, so needs to be validated if (Native_UObjectGlobals.CheckIsClassChildOf_Internal != null) { UClass parentClass = UClass.GetClass <T>(); Native_UObjectGlobals.CheckIsClassChildOf_Internal( parentClass == null ? IntPtr.Zero : parentClass.Address, unrealClass == null ? IntPtr.Zero : unrealClass.Address); } } return(GCHelper.Find <T>(Native_UObjectGlobals.StaticConstructObject_Internal( unrealClass == null ? IntPtr.Zero : unrealClass.Address, outer.Address, ref name, flags, EInternalObjectFlags.None, template == null ? IntPtr.Zero : template.Address, copyTransientsFromClassDefaults, instanceGraph))); }
/// <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)); }
private void GenerateCodeForModule(UnrealModuleInfo module) { List <UStruct> structs = new List <UStruct>(); List <UEnum> enums = new List <UEnum>(); List <UFunction> globalFunctions = new List <UFunction>(); foreach (UStruct unrealStruct in new TObjectIterator <UStruct>()) { if (!unrealStruct.IsA <UFunction>() && unrealStruct.IsIn(module.Package) && CanExportStruct(unrealStruct) && IsAvailableType(unrealStruct)) { structs.Add(unrealStruct); } } foreach (UEnum unrealEnum in new TObjectIterator <UEnum>()) { if (unrealEnum.IsIn(module.Package) && CanExportEnum(unrealEnum) && IsAvailableType(unrealEnum)) { enums.Add(unrealEnum); } } UClass packageClass = UClass.GetClass <UPackage>(); foreach (UFunction function in new TObjectIterator <UFunction>()) { UObject outer = function.GetOuter(); if (outer == null || outer.GetClass() != packageClass) { continue; } if (function.HasAnyFunctionFlags(EFunctionFlags.Delegate | EFunctionFlags.MulticastDelegate) && function.IsIn(module.Package)) { globalFunctions.Add(function); } } SlowTaskSetModuleCount(1); SlowTaskBeginModule(FPackageName.GetShortName(module.Package), structs.Count + enums.Count + globalFunctions.Count); GenerateCodeForModule(module, structs.ToArray(), enums.ToArray(), globalFunctions.ToArray()); }
private void UpdateAvailableTypes() { availableTypes.Clear(); if (Settings.ExportMode == CodeGeneratorSettings.CodeExportMode.All) { return; } foreach (UStruct unrealStruct in UObject.GetObjects <UStruct>()) { if (!unrealStruct.IsA <UFunction>() && IsBlueprintVisibleStruct(unrealStruct)) { UpdateAvailableTypes(unrealStruct); } } foreach (UEnum unrealEnum in UObject.GetObjects <UEnum>()) { if (CanExportEnum(unrealEnum) && IsBlueprintVisibleEnum(unrealEnum)) { UpdateAvailableTypes(unrealEnum); } } // cache UPackage class UClass packageClass = UClass.GetClass <UPackage>(); if (Settings.ExportMode == CodeGeneratorSettings.CodeExportMode.Referenced) { // Get struct refs from global functions (delegates) // - Should we check if the delegate is even referenced? foreach (UFunction function in UObject.GetObjects <UFunction>()) { bool isGlobal = function.GetOuter().GetClass() == packageClass; if (isGlobal && function.HasAnyFunctionFlags(EFunctionFlags.Delegate | EFunctionFlags.MulticastDelegate)) { UpdateAvailableTypes(function); } } } }
/// <summary> /// Returns an array of classes that were derived from the specified class. /// </summary> /// <typeparam name="T">The parent class of the classes to return.</typeparam> /// <param name="recursive">If true, the results will include children of the children classes, recursively. Otherwise, only direct decedents will be included.</param> /// <returns></returns> public static UClass[] GetDerivedClasses <T>(bool recursive = true) { return(GetDerivedClasses(UClass.GetClass <T>(), recursive)); }
/// <summary> /// Returns an array of objects of a specific class. Optionally, results can include objects of derived classes as well. /// </summary> /// <typeparam name="T">Class of the objects to return.</typeparam> /// <param name="includeDerivedClasses">If true, the results will include objects of child classes as well.</param> /// <param name="additionalExcludeFlags">Objects with any of these flags will be excluded from the results.</param> /// <param name="exclusionInternalFlags">Specifies internal flags to use as a filter for which objects to return</param> /// <returns></returns> public static UObject[] GetObjectsOfClass <T>(bool includeDerivedClasses = true, EObjectFlags additionalExcludeFlags = EObjectFlags.ClassDefaultObject, EInternalObjectFlags exclusionInternalFlags = EInternalObjectFlags.None) { return(GetObjectsOfClass(UClass.GetClass <T>(), includeDerivedClasses, additionalExcludeFlags, exclusionInternalFlags)); }
public void GenerateCodeForBlueprints(AssetLoadMode loadMode, bool clearAssetCache, bool skipLevels) { BeginGenerateModules(); string projectPath = FPaths.ProjectFilePath; string projectName = FPaths.GetBaseFilename(projectPath); UnrealModuleInfo module = new UnrealModuleInfo(null, projectName, projectPath); BeginGenerateModule(module); UClass worldClass = GCHelper.Find <UClass>(Classes.UWorld); AssetCache assetCache = new AssetCache(this); if (!clearAssetCache) { assetCache.Load(); } List <string> assetBlacklist = LoadAssetBlacklist(); AssetLogClear(); AssetLogLine("Load assets {0}", DateTime.Now); bool registeredCrashHandler = false; if (Settings.CatchCrashOnAssetLoading) { FCoreDelegates.OnHandleSystemError.Bind(OnAssetLoadingCrash); registeredCrashHandler = true; } using (FARFilter filter = new FARFilter()) { filter.RecursiveClasses = true; filter.ClassNames.Add(UClass.GetClass <UBlueprint>().GetFName()); filter.ClassNames.Add(UClass.GetClass <UBlueprintGeneratedClass>().GetFName()); filter.ClassNames.Add(UClass.GetClass <UUserDefinedStruct>().GetFName()); filter.ClassNames.Add(UClass.GetClass <UUserDefinedEnum>().GetFName()); if (!skipLevels && worldClass != null) { filter.ClassNames.Add(worldClass.GetFName()); } List <FAssetData> assets = FAssetData.Load(filter); SlowTaskSetModuleCount(1); SlowTaskBeginModule("Blueprints", assets.Count); foreach (FAssetData asset in assets) { SlowTaskStep(null); string assetFileName, assetFileNameError; if (!asset.TryGetFilename(out assetFileName, out assetFileNameError)) { FMessage.Log(string.Format("FAssetData.TryGetFilename failed. ObjectPath:'{0}' reason:'{1}'", asset.ObjectPath.ToString(), assetFileNameError)); continue; } bool isEngineAsset = FPaths.IsSameOrSubDirectory(FPaths.EngineContentDir, FPaths.GetPath(assetFileName)); if (loadMode != AssetLoadMode.All) { if ((isEngineAsset && loadMode != AssetLoadMode.Engine) || (!isEngineAsset && loadMode != AssetLoadMode.Game)) { continue; } } if (!assetCache.HasAssetChanged(asset, assetFileName)) { if (Settings.LogAssetLoadingVerbose) { AssetLogLine("'{0}' unchanged", assetFileName); } continue; } // Log that we are loading this asset so we know which assets crash on load AssetLog("'{0}' - ", asset.ObjectPath.ToString()); if (assetBlacklist.Contains(asset.ObjectPath.ToString())) { AssetLogLine("blacklisted"); continue; } loadingAsset = asset.ObjectPath.ToString(); UObject obj = asset.GetAsset(); loadingAsset = null; UClass unrealClass = asset.GetClass(); if (obj == null || unrealClass == null) { AssetLogLine("null"); continue; } AssetLogLine("done"); if (unrealClass.IsChildOf <UBlueprint>()) { UBlueprint blueprint = obj as UBlueprint; if (blueprint != null) { UBlueprintGeneratedClass blueprintGeneratedClass = blueprint.GeneratedClass as UBlueprintGeneratedClass; if (blueprintGeneratedClass != null) { GenerateCodeForStruct(module, blueprintGeneratedClass); } } } else if (unrealClass.IsChildOf <UBlueprintGeneratedClass>()) { UBlueprintGeneratedClass blueprintGeneratedClass = obj as UBlueprintGeneratedClass; if (blueprintGeneratedClass != null) { GenerateCodeForStruct(module, blueprintGeneratedClass); } } else if (unrealClass.IsChildOf <UUserDefinedStruct>()) { UUserDefinedStruct unrealStruct = obj as UUserDefinedStruct; if (unrealStruct != null) { GenerateCodeForStruct(module, unrealStruct); } } else if (unrealClass.IsChildOf <UUserDefinedEnum>()) { UUserDefinedEnum unrealEnum = obj as UUserDefinedEnum; if (unrealEnum != null) { GenerateCodeForEnum(module, unrealEnum); } } else if (unrealClass.IsChildOf(worldClass)) { TArrayUnsafeRef <UObject> levels = new TArrayUnsafeRef <UObject>(Native.Native_UWorld.GetLevels(obj.Address)); foreach (UObject level in levels) { using (TArrayUnsafe <UBlueprint> levelBlueprints = new TArrayUnsafe <UBlueprint>()) { Native.Native_ULevel.GetLevelBlueprints(level.Address, levelBlueprints.Address); foreach (UBlueprint blueprint in levelBlueprints) { UBlueprintGeneratedClass blueprintGeneratedClass = blueprint.GeneratedClass as UBlueprintGeneratedClass; if (blueprintGeneratedClass != null) { //GenerateCodeForStruct(blueprintGeneratedClass); } } } } } } } if (registeredCrashHandler) { FCoreDelegates.OnHandleSystemError.Unbind(OnAssetLoadingCrash); } assetCache.Save(); EndGenerateModule(module); EndGenerateModules(); }
private void GenerateCodeForStruct(UnrealModuleInfo module, UStruct unrealStruct) { bool isBlueprintType = unrealStruct.IsA <UUserDefinedStruct>() || unrealStruct.IsA <UBlueprintGeneratedClass>(); StructInfo structInfo = GetStructInfo(unrealStruct, isBlueprintType); string typeName = GetTypeName(unrealStruct); UnrealModuleType moduleAssetType; string currentNamespace = GetModuleNamespace(unrealStruct, out moduleAssetType); List <string> namespaces = GetDefaultNamespaces(); CSharpTextBuilder builder = new CSharpTextBuilder(Settings.IndentType); if (!string.IsNullOrEmpty(currentNamespace)) { builder.AppendLine("namespace " + currentNamespace); builder.OpenBrace(); } string accessSpecifier = "public"; StringBuilder modifiers = new StringBuilder(accessSpecifier); if (Settings.UseAbstractTypes && structInfo.IsClass && structInfo.Class.HasAnyClassFlags(EClassFlags.Abstract)) { modifiers.Append(" abstract"); } StringBuilder baseTypeStr = new StringBuilder(); UStruct parentStruct = unrealStruct.GetSuperStruct(); if (parentStruct != null && parentStruct != UClass.GetClass <UInterface>() && unrealStruct != UClass.GetClass <UInterface>()) { baseTypeStr.Append(GetTypeName(parentStruct, namespaces)); } if (structInfo.IsClass) { foreach (FImplementedInterface implementedInterface in structInfo.Class.Interfaces) { if (baseTypeStr.Length > 0) { baseTypeStr.Append(", "); } baseTypeStr.Append(GetTypeName(implementedInterface.InterfaceClass, namespaces)); } } if (baseTypeStr.Length > 0) { baseTypeStr.Insert(0, " : "); } AppendDocComment(builder, unrealStruct, isBlueprintType); AppendAttribute(builder, unrealStruct, module, structInfo); if (structInfo.IsInterface) { System.Diagnostics.Debug.Assert(structInfo.Class.Interfaces.Length == 0, "TODO: Interfaces inheriting other interfaces"); string baseInterface = unrealStruct == UClass.GetClass <UInterface>() ? string.Empty : (baseTypeStr.Length == 0 ? " : " : ", ") + Names.IInterface; builder.AppendLine(modifiers + " interface " + typeName + baseTypeStr + baseInterface); } else if (structInfo.IsClass) { builder.AppendLine(modifiers + " partial class " + typeName + baseTypeStr); } else { if (structInfo.StructAsClass) { builder.AppendLine(modifiers + " partial class " + typeName + " : " + Names.StructAsClass); } else { if (structInfo.IsBlittable) { string structLayout = UpdateTypeNameNamespace("StructLayout", "System.Runtime.InteropServices", namespaces); string layoutKind = UpdateTypeNameNamespace("LayoutKind", "System.Runtime.InteropServices", namespaces); builder.AppendLine("[" + structLayout + "(" + layoutKind + ".Sequential)]"); } builder.AppendLine(modifiers + " partial struct " + typeName); } } builder.OpenBrace(); string typeNameEx = structInfo.IsInterface ? typeName + "Impl" : typeName; // Create a seperate builder for building the interface "Impl" class CSharpTextBuilder interfaceImplBuilder = null; if (structInfo.IsInterface) { interfaceImplBuilder = new CSharpTextBuilder(); interfaceImplBuilder.AppendLine(accessSpecifier + " sealed class " + typeNameEx + " : " + Names.IInterfaceImpl + ", " + typeName); interfaceImplBuilder.Indent(); // Move the indent to the same as builder for this point interfaceImplBuilder.OpenBrace(); // Open the class brace } // Create a seperate builder for properties which will be inserted into the native type info initializer CSharpTextBuilder offsetsBuilder = new CSharpTextBuilder(Settings.IndentType); offsetsBuilder.AppendLine("static " + typeNameEx + "()"); offsetsBuilder.IndentCount = builder.IndentCount;// Move the indent to the same as builder offsetsBuilder.OpenBrace(); offsetsBuilder.AppendLine("if (" + Names.UnrealTypes_CanLazyLoadNativeType + "(typeof(" + typeNameEx + ")))"); offsetsBuilder.OpenBrace(); offsetsBuilder.AppendLine(Settings.VarNames.LoadNativeType + "();"); offsetsBuilder.CloseBrace(); offsetsBuilder.AppendLine(Names.UnrealTypes_OnCCtorCalled + "(typeof(" + typeNameEx + "));"); offsetsBuilder.CloseBrace(); offsetsBuilder.AppendLine(); offsetsBuilder.AppendLine("static void " + Settings.VarNames.LoadNativeType + "()"); offsetsBuilder.OpenBrace(); if (structInfo.HasStaticFunction) { builder.AppendLine("static IntPtr " + Settings.VarNames.ClassAddress + ";"); offsetsBuilder.AppendLine(Settings.VarNames.ClassAddress + " = " + (structInfo.IsStruct ? Names.NativeReflection_GetStruct : Names.NativeReflection_GetClass) + "(\"" + unrealStruct.GetPathName() + "\");"); } else { offsetsBuilder.AppendLine("IntPtr " + Settings.VarNames.ClassAddress + " = " + (structInfo.IsStruct ? Names.NativeReflection_GetStruct : Names.NativeReflection_GetClass) + "(\"" + unrealStruct.GetPathName() + "\");"); } if (structInfo.StructAsClass) { offsetsBuilder.AppendLine(typeName + Settings.VarNames.StructAddress + " = " + Settings.VarNames.ClassAddress + ";"); } else if (structInfo.IsStruct) { offsetsBuilder.AppendLine(typeName + Settings.VarNames.StructSize + " = " + Names.NativeReflection_GetStructSize + "(" + Settings.VarNames.ClassAddress + ");"); } if (structInfo.IsStruct && parentStruct != null) { // Export base properties if (Settings.InlineBaseStruct || structInfo.StructAsClass) { UScriptStruct tempParentStruct = parentStruct as UScriptStruct; while (tempParentStruct != null) { StructInfo tempParentStructInfo = GetStructInfo(tempParentStruct); if (tempParentStructInfo != null) { foreach (UProperty property in tempParentStructInfo.GetProperties()) { if (!tempParentStructInfo.IsCollapsedProperty(property)) { GenerateCodeForProperty(module, builder, offsetsBuilder, property, tempParentStructInfo.IsBlueprintType, structInfo, namespaces, tempParentStructInfo.GetPropertyName(property)); } } } tempParentStruct = tempParentStruct.GetSuperStruct() as UScriptStruct; } } else { builder.AppendLine(GetTypeName(parentStruct, namespaces) + " Base;"); } } // Export properties foreach (UProperty property in structInfo.GetProperties()) { if (!structInfo.IsCollapsedProperty(property)) { GenerateCodeForProperty(module, builder, offsetsBuilder, property, isBlueprintType, structInfo, namespaces, structInfo.GetPropertyName(property)); } } foreach (CollapsedMember collapsedMember in structInfo.GetCollapsedMembers()) { GenerateCodeForProperty(module, builder, offsetsBuilder, collapsedMember, isBlueprintType, namespaces); } // Export functions List <ExtensionMethodInfo> extensionMethods = new List <ExtensionMethodInfo>(); foreach (UFunction function in structInfo.GetFunctions()) { if (!structInfo.IsCollapsedFunction(function)) { if (!structInfo.IsInterface) { // If this isn't an interface and the function can be made into an extension method then do so ExtensionMethodInfo extensionMethodInfo = ExtensionMethodInfo.Create(function); if (extensionMethodInfo != null) { extensionMethods.Add(extensionMethodInfo); } } if (function.HasAnyFunctionFlags(EFunctionFlags.Delegate | EFunctionFlags.MulticastDelegate)) { AppendDelegateSignature(module, builder, function, unrealStruct, isBlueprintType, namespaces); builder.AppendLine(); } else if (structInfo.IsInterface) { AppendFunctionOffsets(interfaceImplBuilder, offsetsBuilder, function, false, false, namespaces); AppendDocComment(builder, function, isBlueprintType); AppendAttribute(builder, function, module); builder.AppendLine(GetFunctionSignature(module, function, unrealStruct, namespaces) + ";"); builder.AppendLine(); // Always require a per-instance function address on the interfaces "Impl" class. // This isn't really required if the target function isn't an event but since we are working // with interfaces it is probably best to make sure functions are resolved properly. If we decide // to change this to not require a per-instance function address make sure to update AppendFunctionOffsets // which adds the per-instance function address to the class. Also update AssemblyRewriter.Interface.cs // Also update the "ResetInterface" code which always expects an per-instance address to reset. AppendAttribute(interfaceImplBuilder, function, module); interfaceImplBuilder.AppendLine(GetFunctionSignature(module, function, unrealStruct, null, "public", FunctionSigFlags.None, namespaces)); interfaceImplBuilder.OpenBrace(); AppendFunctionBody(interfaceImplBuilder, function, false, false, true, namespaces); interfaceImplBuilder.CloseBrace(); builder.AppendLine(); } else { AppendFunctionOffsets(builder, offsetsBuilder, function, false, false, namespaces); AppendDocComment(builder, function, isBlueprintType); AppendAttribute(builder, function, module); bool hasSuperFunction = function.GetSuperFunction() != null; if (function.HasAnyFunctionFlags(EFunctionFlags.BlueprintEvent) && !hasSuperFunction) { // Define the declaration method which will call the correct UFunction for the UObject instance builder.AppendLine(GetFunctionSignature(module, function, unrealStruct, namespaces)); builder.OpenBrace(); AppendFunctionBody(builder, function, false, false, true, namespaces); builder.CloseBrace(); builder.AppendLine(); } if (function.HasAnyFunctionFlags(EFunctionFlags.BlueprintEvent)) { if (!Settings.UseExplicitImplementationMethods) { // Used to hide the _Implementation method from being visible in intellisense builder.AppendLine("[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]"); } // Define the _Implementation method builder.AppendLine(GetFunctionSignatureImpl(module, function, unrealStruct, namespaces)); } else { builder.AppendLine(GetFunctionSignature(module, function, unrealStruct, namespaces)); } builder.OpenBrace(); AppendFunctionBody(builder, function, false, false, false, namespaces); builder.CloseBrace(); builder.AppendLine(); } } } if (structInfo.StructAsClass) { if (Settings.GenerateIsValidSafeguards) { builder.AppendLine("static bool " + typeName + Settings.VarNames.IsValid + ";"); // Append XXXX_IsValid = Prop1_IsValid && Prop2_IsValid && Prop3_IsValid...; AppendStructIsValid(offsetsBuilder, typeName, structInfo, parentStruct); } builder.AppendLine("static IntPtr " + typeName + Settings.VarNames.StructAddress + ";"); builder.AppendLine(); builder.AppendLine("protected override IntPtr GetStructAddress()"); builder.OpenBrace(); builder.AppendLine("return " + typeName + Settings.VarNames.StructAddress + ";"); builder.CloseBrace(); builder.AppendLine(); } else if (structInfo.IsStruct) { if (Settings.GenerateIsValidSafeguards && !structInfo.IsBlittable) { builder.AppendLine("static bool " + typeName + Settings.VarNames.IsValid + ";"); } builder.AppendLine("static int " + typeName + Settings.VarNames.StructSize + ";"); builder.AppendLine(); // Add the struct Copy() method (for non blittable structs) builder.AppendLine("public " + typeName + " " + Settings.VarNames.StructCopy + "()"); builder.OpenBrace(); builder.AppendLine(typeName + " result = this;"); foreach (UProperty property in structInfo.GetProperties()) { if (!structInfo.IsCollapsedProperty(property) && IsCollectionProperty(property)) { string propertyName = GetMemberName(property, structInfo.GetPropertyName(property)); builder.AppendLine("if (this." + propertyName + " != null)"); builder.OpenBrace(); UStructProperty structProperty = property as UStructProperty; StructInfo propertyStructInfo = structProperty == null || structProperty.Struct == null ? null : GetStructInfo(structProperty.Struct); if (propertyStructInfo != null && !propertyStructInfo.IsBlittable) { builder.AppendLine("result." + propertyName + " = new " + GetTypeName(property, namespaces) + "();"); builder.AppendLine("for (int i = 0; i < this." + propertyName + ".Count; ++i)"); builder.OpenBrace(); builder.AppendLine("result." + propertyName + ".Add(this." + propertyName + "[i]." + Settings.VarNames.StructCopy + "());"); builder.CloseBrace(); } else { builder.AppendLine("result." + propertyName + " = new " + GetTypeName(property, namespaces) + "(" + "this." + propertyName + ");"); } builder.CloseBrace(); } } if (Settings.InlineBaseStruct) { UScriptStruct tempParentStruct = parentStruct as UScriptStruct; while (tempParentStruct != null) { StructInfo tempParentStructInfo = GetStructInfo(tempParentStruct); if (tempParentStructInfo != null) { foreach (UProperty property in tempParentStructInfo.GetProperties()) { if (!tempParentStructInfo.IsCollapsedProperty(property) && IsCollectionProperty(property)) { string propertyName = GetMemberName(property, tempParentStructInfo.GetPropertyName(property)); builder.AppendLine("if (this." + propertyName + " != null)"); builder.OpenBrace(); builder.AppendLine("result." + propertyName + " = new " + GetTypeName(property, namespaces) + "(" + "this." + propertyName + ");"); builder.CloseBrace(); } } } tempParentStruct = tempParentStruct.GetSuperStruct() as UScriptStruct; } } builder.AppendLine("return result;"); builder.CloseBrace(); builder.AppendLine(); if (structInfo.IsBlittable) { // Validate the size of the blittable struct offsetsBuilder.AppendLine(Names.NativeReflection_ValidateBlittableStructSize + "(" + Settings.VarNames.ClassAddress + ", typeof(" + typeName + "));"); } else { if (Settings.GenerateIsValidSafeguards) { // Append XXXX_IsValid = Prop1_IsValid && Prop2_IsValid && Prop3_IsValid...; AppendStructIsValid(offsetsBuilder, typeName, structInfo, parentStruct); } builder.AppendLine("public static " + typeName + " FromNative(IntPtr nativeBuffer)"); builder.OpenBrace(); builder.AppendLine("return new " + typeName + "(nativeBuffer);"); builder.CloseBrace(); builder.AppendLine(); builder.AppendLine("public static void ToNative(IntPtr nativeBuffer, " + typeName + " value)"); builder.OpenBrace(); builder.AppendLine("value.ToNative(nativeBuffer);"); builder.CloseBrace(); builder.AppendLine(); builder.AppendLine("public static " + typeName + " FromNative(IntPtr nativeBuffer, int arrayIndex, IntPtr prop)"); builder.OpenBrace(); builder.AppendLine("return new " + typeName + "(nativeBuffer + (arrayIndex * " + typeName + Settings.VarNames.StructSize + "));"); builder.CloseBrace(); builder.AppendLine(); builder.AppendLine("public static void ToNative(IntPtr nativeBuffer, int arrayIndex, IntPtr prop, " + typeName + " value)"); builder.OpenBrace(); builder.AppendLine("value.ToNative(nativeBuffer + (arrayIndex * " + typeName + Settings.VarNames.StructSize + "));"); builder.CloseBrace(); builder.AppendLine(); builder.AppendLine("public void ToNative(IntPtr nativeStruct)"); builder.OpenBrace(); AppendStructMarshalerBody(builder, typeName, structInfo, parentStruct, true, namespaces); builder.CloseBrace(); builder.AppendLine(); builder.AppendLine("public " + typeName + "(IntPtr nativeStruct)"); builder.OpenBrace(); /*if (Settings.UObjectAsBlittableType) * { * // UObject types will have an additional backing field which needs to be assigned before being able to * // assign the property * // - The alternative would be to modify the property assignment code to target the backing field instead of * // the property. This is probably the ideal way of doing it but we would need to use a different marshaler * // (BlittableTypeMarshaler<> instead of UObjectMarshaler<>) and ensure the marshaler change doesn't impact * // other generated code elsewhere. * foreach (UProperty property in structInfo.GetProperties()) * { * UObjectProperty objectProperty = property as UObjectProperty; * if (objectProperty != null) * { * string propertyName = GetMemberName(property, structInfo.GetPropertyName(property)); * builder.AppendLine(propertyName + Settings.VarNames.UObjectBlittableName + " = IntPtr.Zero;"); * } * } * }*/ AppendStructMarshalerBody(builder, typeName, structInfo, parentStruct, false, namespaces); builder.CloseBrace(); builder.AppendLine(); } } if (loadNativeTypeInjected.Contains(typeName)) { offsetsBuilder.AppendLine(Settings.VarNames.LoadNativeTypeInjected + "(" + Settings.VarNames.ClassAddress + ");"); } offsetsBuilder.CloseBrace(); // Add the offsets builder if it isn't empty (always required for structs due to struct size export) // Interfaces are built up seperately in a different class which must be added after the interface body. if (!structInfo.IsInterface && (structInfo.HasContent || structInfo.IsStruct)) { builder.AppendLine(offsetsBuilder.ToString()); builder.AppendLine(); } // Remove any trailing empty lines before adding the close brace builder.RemovePreviousEmptyLines(); builder.CloseBrace(); // Add the "Impl" wrapper class for interfaces. This is always required so that we have a default // interface implementation that we can call. if (structInfo.IsInterface) { if (structInfo.HasContent) { interfaceImplBuilder.AppendLine();// Whitespace // Add the ResetInterface method to reset the state of a pooled interface instance interfaceImplBuilder.AppendLine("public override void ResetInterface()"); interfaceImplBuilder.OpenBrace(); foreach (UFunction function in structInfo.GetFunctions()) { interfaceImplBuilder.AppendLine(GetFunctionName(function) + Settings.VarNames.InstanceFunctionAddress + " = IntPtr.Zero;"); } interfaceImplBuilder.CloseBrace(); interfaceImplBuilder.AppendLine(); // Whitespace } interfaceImplBuilder.AppendLine(offsetsBuilder.ToString()); // Add the offsets to the "Impl" class interfaceImplBuilder.CloseBrace(); // Add the close brace for the "Impl" class builder.AppendLine(); // Empty line between interface and "Impl" class builder.AppendLine(interfaceImplBuilder.ToString()); // Add the "Impl" class below the interface } if (!string.IsNullOrEmpty(currentNamespace)) { builder.CloseBrace(); } builder.InsertNamespaces(currentNamespace, namespaces, Settings.SortNamespaces); OnCodeGenerated(module, moduleAssetType, typeName, unrealStruct.GetPathName(), builder); if (extensionMethods.Count > 0) { GenerateCodeForExtensionMethods(module, unrealStruct, extensionMethods); } }
public bool IsChildOf(Type type) { return(IsChildOf(UClass.GetClass(type))); }
public bool IsChildOf <T>() { return(IsChildOf(UClass.GetClass <T>())); }
/// <summary> /// Only call from Initialize() of Systems to ensure initialization order. /// </summary> /// <remarks> /// Note: Dependencies only work within a collection. /// </remarks> public bool InitializeDependency <T>() where T : USubsystem { return(Native_FSubsystemCollection.InitializeDependency(collectionAddress, UClass.GetClass(typeof(T)).Address)); }
public void GenerateCodeForModules(UnrealModuleType[] moduleTypes) { BeginGenerateModules(); HashSet <string> moduleNamesWhitelistToLower = new HashSet <string>(); foreach (string moduleName in ModulesNamesWhitelist) { moduleNamesWhitelistToLower.Add(moduleName.ToLower()); } HashSet <string> moduleNamesBlacklistToLower = new HashSet <string>(); foreach (string moduleName in ModulesNamesBlacklist) { moduleNamesBlacklistToLower.Add(moduleName.ToLower()); } Dictionary <UPackage, List <UStruct> > structsByPackage = new Dictionary <UPackage, List <UStruct> >(); Dictionary <UPackage, List <UEnum> > enumsByPackage = new Dictionary <UPackage, List <UEnum> >(); Dictionary <UPackage, List <UFunction> > globalFunctionsByPackage = new Dictionary <UPackage, List <UFunction> >(); foreach (UStruct unrealStruct in new TObjectIterator <UStruct>()) { if (!unrealStruct.IsA <UFunction>() && CanExportStruct(unrealStruct) && IsAvailableType(unrealStruct)) { UPackage package = unrealStruct.GetOutermost(); if (package != null) { List <UStruct> structs; if (!structsByPackage.TryGetValue(package, out structs)) { structsByPackage.Add(package, structs = new List <UStruct>()); } structs.Add(unrealStruct); } } } foreach (UEnum unrealEnum in new TObjectIterator <UEnum>()) { if (CanExportEnum(unrealEnum) && IsAvailableType(unrealEnum)) { UPackage package = unrealEnum.GetOutermost(); if (package != null) { List <UEnum> enums; if (!enumsByPackage.TryGetValue(package, out enums)) { enumsByPackage.Add(package, enums = new List <UEnum>()); } enums.Add(unrealEnum); } } } UClass packageClass = UClass.GetClass <UPackage>(); foreach (UFunction function in new TObjectIterator <UFunction>()) { UObject outer = function.GetOuter(); if (outer == null || outer.GetClass() != packageClass) { continue; } if (function.HasAnyFunctionFlags(EFunctionFlags.Delegate | EFunctionFlags.MulticastDelegate)) { UPackage package = function.GetOutermost(); if (package != null) { List <UFunction> functions; if (!globalFunctionsByPackage.TryGetValue(package, out functions)) { globalFunctionsByPackage.Add(package, functions = new List <UFunction>()); } functions.Add(function); } } else { FMessage.Log(ELogVerbosity.Error, string.Format("Global function which isn't a delegate '{0}'", function.GetName())); } } Dictionary <FName, string> modulePaths = FModulesPaths.FindModulePaths("*"); // Make sure ModulePaths and ModuleNames are the same. Based on comments FindModules may be changed/removed in the // future so we will want to just use FindModulePaths. For now make sure they are synced up. FName[] moduleNames = FModuleManager.Get().FindModules("*"); if (moduleNames.Length != modulePaths.Count) { FMessage.Log(ELogVerbosity.Warning, string.Format("Module count invalid (update FModulePaths). FindModules:{0} FindModulePaths:{1}", moduleNames.Length, modulePaths.Count)); List <FName> additionalNames = new List <FName>(); foreach (KeyValuePair <FName, string> module in modulePaths) { if (moduleNames.Contains(module.Key)) { FMessage.Log(ELogVerbosity.Warning, "Module: " + module.Key + " - " + module.Value); } else { FMessage.Log(ELogVerbosity.Warning, "Additional module: " + module.Key + " - " + module.Value); } } List <FName> missingNames = new List <FName>(); foreach (FName moduleName in moduleNames) { if (!modulePaths.ContainsKey(moduleName)) { FMessage.Log(ELogVerbosity.Warning, "Missing module: " + moduleName); } } } IPlugin[] plugins = IPluginManager.Instance.GetDiscoveredPlugins(); SlowTaskSetModuleCount(modulePaths.Count); foreach (KeyValuePair <FName, string> modulePath in modulePaths) { SlowTaskBeginModule(modulePath.Key.PlainName); string moduleName = modulePath.Key.PlainName; string longPackageName = FPackageName.ConvertToLongScriptPackageName(moduleName); UPackage package = UObject.FindObjectFast <UPackage>(null, new FName(longPackageName), false, false); if (package != null) { UnrealModuleInfo moduleInfo = new UnrealModuleInfo(package, moduleName, modulePath.Value, UnrealModuleInfo.GetModuleType(moduleName, modulePath.Value, plugins)); if (moduleInfo.Type == UnrealModuleType.Unknown) { FMessage.Log(ELogVerbosity.Error, string.Format("Unknown module type on module '{0}' '{1}'", moduleInfo.Name, moduleInfo.Package)); } else if (!moduleTypes.Contains(moduleInfo.Type) || moduleNamesBlacklistToLower.Contains(moduleInfo.Name.ToLower()) || (moduleNamesWhitelistToLower.Count > 0 && !moduleNamesWhitelistToLower.Contains(moduleInfo.Name.ToLower()))) { continue; } List <UStruct> structs; if (!structsByPackage.TryGetValue(package, out structs)) { structs = new List <UStruct>(); } List <UEnum> enums; if (!enumsByPackage.TryGetValue(package, out enums)) { enums = new List <UEnum>(); } List <UFunction> globalFunctions; if (!globalFunctionsByPackage.TryGetValue(package, out globalFunctions)) { globalFunctions = new List <UFunction>(); } SlowTaskUpdateTarget(structs.Count + enums.Count + globalFunctions.Count); GenerateCodeForModule(moduleInfo, structs.ToArray(), enums.ToArray(), globalFunctions.ToArray()); } } IPlugin.Dispose(plugins); EndGenerateModules(); }
/// <summary> /// Constructs a gameplay object /// </summary> /// <typeparam name="T">the object type</typeparam> /// <param name="outer">the outer for the new object. If not specified, object will be created in the transient package.</param> /// <returns>a pointer of type T to a new object of the specified class</returns> public static T NewObject <T>(ObjectOuter outer = default(ObjectOuter)) where T : UObject { return(NewObject <T>(false, outer, UClass.GetClass <T>())); }