Пример #1
0
        public bool TryGetFilename(out string fileName, out string error)
        {
            error = null;

            // Get the filename without the valid file extension e.g. "../../../Engine/Test/AssetName.AssetName"
            if (!FPackageName.TryConvertLongPackageNameToFilename(ObjectPath.ToString(), out fileName))
            {
                error = "Couldn't find package for asset " + ObjectPath.ToString();
                return(false);
            }

            // Remove the dummy extension "AssetName.AssetName" -> "AssetName"
            int LastDot = fileName.LastIndexOf('.');

            if (LastDot <= 0)
            {
                error = "Bad filename: " + fileName;
                return(false);
            }
            fileName = fileName.Substring(0, LastDot);

            // Get the filename with the correct file extension ("WithoutExtension" means the input doesn't have an extension)
            if (!FPackageName.FindPackageFileWithoutExtension(fileName, out fileName) || !FPaths.FileExists(fileName))
            {
                error = "Couldn't find asset: " + fileName;
                return(false);
            }

            return(true);
        }
Пример #2
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);
        }
Пример #3
0
        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());
        }
Пример #4
0
        public void GenerateCodeForModule(string moduleName, bool loadModule)
        {
            string   longPackageName = FPackageName.ConvertToLongScriptPackageName(moduleName);
            UPackage package         = UObject.FindObjectFast <UPackage>(null, new FName(longPackageName), false, false);

            if (package == null && !FModuleManager.Instance.IsModuleLoaded(new FName(moduleName)))
            {
                // package is almost always non-null even when IsModuleLoaded returns false - if the package is non-null it
                // seems the module types are available so we don't have to call LoadModule (check if this is always true)

                if (!loadModule)
                {
                    return;
                }

                EModuleLoadResult loadResult;
                FModuleManager.Instance.LoadModuleWithFailureReason(new FName(moduleName), out loadResult);
                if (loadResult != EModuleLoadResult.Success)
                {
                    FMessage.Log("Failed to load module '" + moduleName + "'. Reason: " + loadResult);
                    return;
                }

                package = UObject.FindObjectFast <UPackage>(null, new FName(longPackageName), false, false);
            }

            if (package != null)
            {
                Dictionary <FName, string> modulePaths = FModulesPaths.FindModulePaths("*");
                string modulePath;
                if (!modulePaths.TryGetValue(new FName(moduleName), out modulePath))
                {
                    return;
                }

                BeginGenerateModules();
                GenerateCodeForModule(new UnrealModuleInfo(package, moduleName, modulePath));
                EndGenerateModules();
            }
        }
Пример #5
0
        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();
        }
Пример #6
0
        private string GetModuleNamespace(UnrealModuleType moduleType, string moduleName, UnrealModuleType moduleAssetType, bool allowFoldersAsNamespace, string path)
        {
            string namespaceName = null;

            switch (moduleType)
            {
            case UnrealModuleType.Game:
                switch (moduleAssetType)
                {
                case UnrealModuleType.Engine:
                    namespaceName = Settings.Namespaces.EngineAsset;
                    break;

                case UnrealModuleType.GamePlugin:
                    namespaceName = Settings.Namespaces.GamePluginAsset;
                    break;

                case UnrealModuleType.EnginePlugin:
                    namespaceName = Settings.Namespaces.EnginePluginAsset;
                    break;

                default:
                    namespaceName = Settings.Namespaces.Game;
                    break;
                }
                break;

            case UnrealModuleType.GamePlugin:
                namespaceName = Settings.Namespaces.GamePlugin;
                break;

            case UnrealModuleType.Engine:
                namespaceName = Settings.Namespaces.Engine;
                if (moduleName == "CoreUObject")
                {
                    // Allow CoreUObject to be redirected to a common namespace name (UnrealEngine.Runtime)
                    namespaceName = GetEngineObjectNamespace();
                }
                break;

            case UnrealModuleType.EnginePlugin:
                namespaceName = Settings.Namespaces.EnginePlugin;
                break;

            default:
                return(namespaceName);
            }

            if (string.IsNullOrWhiteSpace(namespaceName))
            {
                return(null);
            }

            if (namespaceName.Contains("{Default}"))
            {
                namespaceName = namespaceName.Replace("{Default}", Settings.Namespaces.Default);
            }

            if (namespaceName.Contains("{Game}"))
            {
                string gameName = FPaths.GetBaseFilename(FPaths.ProjectFilePath);
                namespaceName = namespaceName.Replace("{Game}", gameName);
            }

            if (namespaceName.Contains("{Module}"))
            {
                namespaceName = namespaceName.Replace("{Module}", moduleName);
            }

            if (namespaceName.Contains("{Folder}"))
            {
                if (allowFoldersAsNamespace && moduleAssetType != UnrealModuleType.Unknown)
                {
                    // Get the directory of the file and remove root name "/Game/"
                    string directory  = FPackageName.GetLongPackagePath(path);
                    int    slashIndex = directory.IndexOf('/', 1);
                    if (slashIndex >= 0)
                    {
                        directory = directory.Substring(slashIndex + 1);
                    }
                    else
                    {
                        // The path is empty or only the root name
                        directory = string.Empty;
                    }

                    // Make each '/' a part of the namespace
                    string expandedNamespace = directory.Replace("/", ".");

                    namespaceName = namespaceName.Replace("{Folder}", expandedNamespace);
                }
                else
                {
                    namespaceName = namespaceName.Replace("{Folder}", string.Empty);
                }
            }

            // Remove duplicate '.' chars
            StringBuilder result = new StringBuilder(namespaceName);

            for (int i = result.Length - 1; i >= 0; --i)
            {
                if (result[i] == '.')
                {
                    if (i == 0 || result[i - 1] == '.' || i == result.Length - 1)
                    {
                        result.Remove(i, 1);
                    }
                }
            }

            return(result.ToString());
        }
Пример #7
0
        private string GetModuleNamespace(UField field, out UnrealModuleType moduleAssetType, bool allowFoldersAsNamespace = true)
        {
            moduleAssetType = UnrealModuleType.Unknown;
            UPackage package = field.GetOutermost();

            if (package != null)
            {
                CachedNamespace cachedNamespace;
                if (namespaceCache.TryGetValue(package, out cachedNamespace))
                {
                    moduleAssetType = cachedNamespace.ModuleAssetType;
                    return(cachedNamespace.Namespace);
                }

                UnrealModuleType moduleType = UnrealModuleType.Unknown;
                moduleAssetType = UnrealModuleType.Unknown;

                string packageFilename = package.FileName.ToString();
                if (string.IsNullOrEmpty(packageFilename.ToString()) || packageFilename == FName.None.ToString())
                {
                    packageFilename = field.GetPathName();
                }

                string moduleName = FPackageName.GetShortName(package.GetName());
                if (packageFilename.StartsWith("/Script"))
                {
                    if (!modulesByName.TryGetValue(new FName(moduleName), out moduleType))
                    {
                        moduleType = UnrealModuleType.Unknown;
                        FMessage.Log(ELogVerbosity.Error, string.Format("Failed to find module for module '{0}'", moduleName));
                    }
                }
                else if (packageFilename.StartsWith("/Game/"))
                {
                    moduleType      = UnrealModuleType.Game;
                    moduleAssetType = UnrealModuleType.Game;
                    moduleName      = FPaths.GetBaseFilename(FPaths.ProjectFilePath);// {Module} same as {Game}
                }
                else if (packageFilename.StartsWith("/Engine/"))
                {
                    moduleType      = UnrealModuleType.Game;
                    moduleAssetType = UnrealModuleType.Engine;
                    moduleName      = Settings.Namespaces.Default;
                }
                else
                {
                    string rootName = null;
                    if (packageFilename.Length > 1 && packageFilename[0] == '/')
                    {
                        int slashIndex = packageFilename.IndexOf('/', 1);
                        if (slashIndex >= 0)
                        {
                            rootName   = packageFilename.Substring(1, slashIndex - 1);
                            moduleName = rootName;// Update ModuleName for {Module}

                            if (!modulesByName.TryGetValue(new FName(rootName), out moduleAssetType))
                            {
                                moduleAssetType = UnrealModuleType.Unknown;
                            }
                        }
                    }

                    if (moduleAssetType == UnrealModuleType.Unknown)
                    {
                        FMessage.Log(ELogVerbosity.Error, string.Format("Unknown module asset type root:'{0}' path:'{1}' name:'{2}' path2:'{3}'",
                                                                        rootName, packageFilename, field.GetName(), field.GetPathName()));
                    }
                    moduleType = UnrealModuleType.Game;
                }

                if (moduleType != UnrealModuleType.Unknown)
                {
                    string namespaceName = GetModuleNamespace(moduleType, moduleName, moduleAssetType, allowFoldersAsNamespace, packageFilename);
                    namespaceCache[package] = new CachedNamespace(namespaceName, moduleName, moduleType, moduleAssetType);
                    return(namespaceName);
                }
                else
                {
                    FMessage.Log(ELogVerbosity.Error, string.Format("Unknown module type {0} {1}", packageFilename, moduleName));
                }
            }
            return(null);
        }
Пример #8
0
        public void OnCodeGenerated(CodeGenerator.UnrealModuleInfo module, UnrealModuleType moduleAssetType, string typeName, string path, string code)
        {
            // Note: path will be empty if using combined enums file or global delegates files
            string root, directory, moduleName, assetName, memberName;

            FPackageName.GetPathInfo(path, out root, out directory, out moduleName, out assetName, out memberName);
            //Log("path:'{0}' root:'{1}' directory:'{2}' asset:'{3}' member:'{4}'", path, root, directory, assetName, memberName);

            string rootFolderName = GetRootFolderName(path, root, module.Type, moduleAssetType);

            if (string.IsNullOrEmpty(rootFolderName) && !string.IsNullOrEmpty(path))
            {
                Log(ELogVerbosity.Error, "Unknown asset root '{0}' ModuleType:'{1}' ModuleAssetType:'{2}' Path:'{3}'",
                    root, module.Type, moduleAssetType, path);
                return;
            }

            string name = Settings.UseTypeNameAsSourceFileName || string.IsNullOrEmpty(assetName) ? typeName : assetName;

            string sourceFilePath = null;
            string projPath       = null;
            string slnPath        = null;

            switch (module.Type)
            {
            case UnrealModuleType.Game:
            {
                string relativeSourceFilePath = null;
                if (EmulateGameFolderStructure(moduleAssetType))
                {
                    relativeSourceFilePath = Path.Combine(directory, name + ".cs");
                }
                else
                {
                    relativeSourceFilePath = name + ".cs";
                }
                string baseCodeDir = Settings.GetGeneratedCodeDir(false);
                if (module.IsBlueprint)
                {
                    baseCodeDir = Path.Combine(Settings.GetManagedDir(), Settings.GetProjectName() + ".Managed", "Blueprint", "Generated");
                }
                if (moduleAssetType == UnrealModuleType.Unknown)
                {
                    // Don't use root folders for native game code wrappers as root folders don't make much sense for them
                    sourceFilePath = Path.Combine(baseCodeDir, relativeSourceFilePath);
                }
                else
                {
                    sourceFilePath = Path.Combine(baseCodeDir, rootFolderName, relativeSourceFilePath);
                }
                slnPath  = GameSlnPath;
                projPath = module.IsBlueprint ? GameProjPath : GameNativeGenerationProjPath;
            }
            break;

            case UnrealModuleType.EnginePlugin:
            case UnrealModuleType.Engine:
            {
                bool mergeAsPluginProj = false;
                bool mergeAsUnrealProj = false;
                switch (Settings.EngineProjMerge)
                {
                case CodeGeneratorSettings.ManagedEngineProjMerge.Engine:
                    if (module.Type == UnrealModuleType.Engine)
                    {
                        mergeAsUnrealProj = true;
                    }
                    break;

                case CodeGeneratorSettings.ManagedEngineProjMerge.Plugins:
                    if (module.Type == UnrealModuleType.EnginePlugin)
                    {
                        mergeAsPluginProj = true;
                    }
                    break;

                case CodeGeneratorSettings.ManagedEngineProjMerge.EngineAndPlugins:
                    if (module.Type == UnrealModuleType.EnginePlugin)
                    {
                        mergeAsPluginProj = true;
                    }
                    else
                    {
                        mergeAsUnrealProj = true;
                    }
                    break;

                case CodeGeneratorSettings.ManagedEngineProjMerge.EngineAndPluginsCombined:
                    mergeAsUnrealProj = true;
                    break;
                }
                if (mergeAsPluginProj || mergeAsUnrealProj)
                {
                    string projName = mergeAsUnrealProj ? "UnrealEngine.csproj" : "UnrealEngine.Plugins.csproj";
                    if (Settings.EngineProjMerge == CodeGeneratorSettings.ManagedEngineProjMerge.EngineAndPluginsCombined)
                    {
                        projPath = Path.Combine(Settings.GetManagedModulesDir(), projName);
                    }
                    else
                    {
                        projPath = Path.Combine(Settings.GetManagedModulesDir(), rootFolderName, projName);
                    }
                }
                else
                {
                    projPath = Path.Combine(Settings.GetManagedModulesDir(), rootFolderName, module.Name, module.Name + ".csproj");
                }

                sourceFilePath = Path.Combine(Settings.GetManagedModulesDir(), rootFolderName, module.Name, name + ".cs");

                if (Settings.ModulesLocation == CodeGeneratorSettings.ManagedModulesLocation.GameFolderCombineSln)
                {
                    slnPath = GameSlnPath;
                }
                else if (Settings.ModulesLocation == CodeGeneratorSettings.ManagedModulesLocation.GameFolderCombineSlnProj)
                {
                    slnPath  = GameSlnPath;
                    projPath = GameProjPath;
                }
                else
                {
                    slnPath = Path.Combine(Settings.GetManagedModulesDir(), "UnrealEngine.sln");
                }
            }
            break;

            case UnrealModuleType.GamePlugin:
            {
                if (moduleAssetType == UnrealModuleType.Unknown)
                {
                    // Don't use root folders for native game code wrappers as root folders don't make much sense for them
                    sourceFilePath = Path.Combine(Settings.GetGeneratedCodeDir(true), module.Name, name + ".cs");
                }
                else
                {
                    sourceFilePath = Path.Combine(Settings.GetGeneratedCodeDir(true), rootFolderName, module.Name, name + ".cs");
                }
                slnPath = GameSlnPath;

                if (Settings.GameProjMerge == CodeGeneratorSettings.ManagedGameProjMerge.GameAndPlugins)
                {
                    projPath = GameNativeGenerationProjPath;
                }
                else if (Settings.GameProjMerge == CodeGeneratorSettings.ManagedGameProjMerge.Plugins)
                {
                    projPath = GamePluginGenerationProjPath;
                }
                else
                {
                    projPath = Path.Combine(Settings.GetManagedDir(), rootFolderName, module.Name, module.Name + ".csproj");
                }
            }
            break;
            }

            if (!string.IsNullOrWhiteSpace(sourceFilePath))
            {
                sourceFilePath = Path.GetFullPath(sourceFilePath);
            }
            if (!string.IsNullOrWhiteSpace(projPath))
            {
                projPath = Path.GetFullPath(projPath);
            }
            if (!string.IsNullOrWhiteSpace(slnPath))
            {
                slnPath = Path.GetFullPath(slnPath);
            }

            if (string.IsNullOrWhiteSpace(sourceFilePath) || string.IsNullOrWhiteSpace(projPath) || string.IsNullOrWhiteSpace(slnPath))
            {
                Log(ELogVerbosity.Error, "Unknown output location for '{0}' '{1}'", typeName, path);
            }
            else if (!ValidateOutputPath(sourceFilePath) || !ValidateOutputPath(projPath) || !ValidateOutputPath(slnPath))
            {
                Log(ELogVerbosity.Error, "Invalid output path '{0}'", sourceFilePath);
            }
            else
            {
                //FMessage.Log(ELogVerbosity.Log, sourceFilePath + " | " + projPath + " | " + slnPath);

                try
                {
                    if (UpdateSolutionAndProject(slnPath, projPath))
                    {
                        if (!AddSourceFile(slnPath, projPath, sourceFilePath, code))
                        {
                            Log(ELogVerbosity.Error, "Failed to add source file '{0}'", sourceFilePath);
                        }
                    }
                    else
                    {
                        Log(ELogVerbosity.Error, "Failed to create sln/csproj '{0}' '{1}'", slnPath, projPath);
                    }
                }
                catch (Exception e)
                {
                    Log(ELogVerbosity.Error, "Exception when adding source file '{0}' {1}", sourceFilePath, e);
                }
            }
        }
Пример #9
0
        public static ManagedUnrealClass CreateClass(Type type)
        {
            ManagedUnrealClass existingClass = FindClass(type);

            if (existingClass != null)
            {
                if (!FBuild.WithHotReload)
                {
                    // TODO: Add support for hotreloading C# classes when WITH_HOT_RELOAD isn't available
                    // - WITH_HOT_RELOAD will be false on shipping, monolithic and server builds
                    // - Would need to make a copy of FHotReloadClassReinstancer (or just use it directly if
                    //   it doesn't depend on WITH_HOT_RELOAD and gets compiled into builds)
                    // - Would likely break blueprint classes which depend on any C# classes reinstanced in this way
                    return(existingClass);
                }

                existingClass.Clear();
                HotReloadClassCount++;
            }

            if (!type.IsSubclassOf(typeof(UObject)))
            {
                return(null);
            }

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

            if (pathAttribute == null || string.IsNullOrEmpty(pathAttribute.Path))
            {
                return(null);
            }

            IntPtr parentClass = GetStaticClass(type.BaseType);

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

            string root, directory, moduleName, className, memberName;

            FPackageName.GetPathInfo(pathAttribute.Path, out root, out directory, out moduleName, out className, out memberName);

            string packageName = "/" + root + "/" + directory;

            if (string.IsNullOrEmpty(moduleName) || string.IsNullOrEmpty(className))
            {
                return(null);
            }

            IntPtr package = NativeReflection.FindObject(Native_UPackage.StaticClass(), IntPtr.Zero, packageName, true);

            if (package == IntPtr.Zero)
            {
                package = NativeReflection.CreatePackage(IntPtr.Zero, packageName);
                Native_UPackage.SetPackageFlags(package, EPackageFlags.CompiledIn);

                // TODO: Find how to create a proper guid for a package (UHT CodeGenerator.cpp seems to use a crc of generated code)
                using (System.Security.Cryptography.SHA256 sha256 = System.Security.Cryptography.SHA256.Create())
                {
                    byte[] hash = sha256.ComputeHash(Encoding.ASCII.GetBytes(packageName));

                    // Truncate the hash
                    byte[] buffer = new byte[16];
                    Buffer.BlockCopy(hash, 0, buffer, 0, buffer.Length);

                    Native_UPackage.SetGuid(package, new Guid(buffer));
                }
            }

            ManagedUnrealClass managedUnrealClass = null;

            if (existingClass != null)
            {
                managedUnrealClass = existingClass;
            }
            else
            {
                managedUnrealClass = new ManagedUnrealClass(type, packageName, className, parentClass);
            }

            managedUnrealClass.StaticClass = USharpClass.CreateClassPtr(
                managedUnrealClass.PackageName,
                managedUnrealClass.ClassName,
                (uint)Native_UStruct.GetPropertiesSize(managedUnrealClass.ParentClass),
                EClassFlags.None,
                EClassCastFlags.None,
                managedUnrealClass.ConfigName,
                managedUnrealClass.ParentClass,
                managedUnrealClass.WithinClass,
                managedUnrealClass.ClassConstructor,
                managedUnrealClass.ClassVTableHelperCtorCaller,
                managedUnrealClass.ClassAddReferencedObjects);

            Native_UObjectBase.UObjectForceRegistration(managedUnrealClass.StaticClass);

            if (existingClass == null)
            {
                Classes.Add(type, managedUnrealClass);
                ClassesByAddress.Add(managedUnrealClass.StaticClass, managedUnrealClass);
            }

            managedUnrealClass.Initialize();

            return(managedUnrealClass);
        }