diff --git a/Managed/PluginInstaller/PluginInstaller/Program.cs b/Managed/PluginInstaller/PluginInstaller/Program.cs index 8458013..a95eb25 100644 --- a/Managed/PluginInstaller/PluginInstaller/Program.cs +++ b/Managed/PluginInstaller/PluginInstaller/Program.cs @@ -15,642 +15,638 @@ namespace PluginInstaller { - class Program - { - private const string ExampleEnginePath = "C:/Epic Games/UE_4.22/"; - private static string msbuildPath; - - public static readonly bool IsLinux; - public static readonly bool IsMacOS; - public static readonly bool IsWindows; - - /// - /// The directory path of PluginInstaller.exe - /// - public static string AppDirectory; - - static Program() - { - switch (Environment.OSVersion.Platform) - { - case PlatformID.Unix: - case PlatformID.MacOSX: - if (File.Exists("/usr/lib/libc.dylib") && File.Exists("/System/Library/CoreServices/SystemVersion.plist")) - { - // This isn't exactly fool proof but msbuild does similar in NativeMethodsShared.cs - IsMacOS = true; - } - else - { - IsLinux = true; - } - break; - default: - IsWindows = true; - break; - } - } - - static void Main(string[] args) - { - AppDirectory = Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath); - - string enginePath = GetEnginePathFromCurrentFolder(); - if (string.IsNullOrEmpty(enginePath) || !Directory.Exists(enginePath)) - { - Console.WriteLine("Failed to find the engine folder! Make sure PluginInstaller.exe is under /Engine/Plugins/USharp/Binaries/Managed/PluginInstaller/PluginInstaller.exe"); - Console.ReadLine(); - return; - } - - PrintHelp(); - Console.WriteLine(); - - Console.WriteLine("Targeting engine version '" + new DirectoryInfo(enginePath).Name + "'"); - Console.WriteLine(); - - ProcessArgs(null, args); - - while (true) - { - string line = Console.ReadLine(); - string[] lineArgs = ParseArgs(line); - if (ProcessArgs(line, lineArgs)) - { - break; - } - } - } - - private static bool ProcessArgs(string commandLine, string[] args) - { - if (args.Length > 0) - { - switch (args[0].ToLower()) - { - case "exit": - case "close": - case "quit": - case "q": - return true; - - case "clear": - case "cls": - Console.Clear(); - break; - - case "build": - CompileCs(args); - CompileCpp(args); - Console.WriteLine("done"); - break; - - case "buildcs": - CompileCs(args); - Console.WriteLine("done"); - break; - - case "buildcustomsln": - if(args.Length >= 3 && - !string.IsNullOrEmpty(args[1]) && File.Exists(args[1]) && - !string.IsNullOrEmpty(args[2]) && File.Exists(args[2])) - { - BuildCustomSolution(args[1], args[2]); - } - break; - - case "buildcpp": - { - Stopwatch cppCompileTime = new Stopwatch(); - cppCompileTime.Start(); - CompileCpp(args); - Console.WriteLine("done (" + cppCompileTime.Elapsed + ")"); - } - break; - - case "copyruntime": - if (args.Length >= 2) - { - bool minimal = args.Length >= 3 && args[2].ToLower() == "min"; - string configFile = NetRuntimeHelper.GetConfigFile(minimal); - - if (File.Exists(configFile)) - { - switch (args[1].ToLower()) - { - case "all": - NetRuntimeHelper.CopyAll(minimal); - Console.WriteLine("done"); - break; - case "mono": - NetRuntimeHelper.CopyMono(minimal); - Console.WriteLine("done"); - break; - case "coreclr": - NetRuntimeHelper.CopyCoreCLR(minimal); - Console.WriteLine("done"); - break; - } - } - else - { - Console.WriteLine("Couldn't find '" + configFile + "'"); - } - } - else - { - Console.WriteLine("Invalid input. Expected one of the following: all, mono, coreclr"); - } - break; - - case "help": - case "?": - PrintHelp(); - break; - } - } - - return false; - } - - private static void PrintHelp() - { - Console.WriteLine("Available commands:"); - Console.WriteLine("- build builds C# and C++ projects"); - Console.WriteLine("- buildcs builds C# projects (Loader, AssemblyRewriter, Runtime)"); - Console.WriteLine("- buildcpp builds C++ projects"); - Console.WriteLine("- copyruntime [all] [mono] [coreclr] copies the given runtime(s) locally"); - } - - private static string[] ParseArgs(string commandLine) - { - char[] parmChars = commandLine.ToCharArray(); - bool inSingleQuote = false; - bool inDoubleQuote = false; - for (var index = 0; index < parmChars.Length; index++) - { - if (parmChars[index] == '"' && !inSingleQuote) - { - inDoubleQuote = !inDoubleQuote; - parmChars[index] = '\n'; - } - if (parmChars[index] == '\'' && !inDoubleQuote) - { - inSingleQuote = !inSingleQuote; - parmChars[index] = '\n'; - } - if (!inSingleQuote && !inDoubleQuote && parmChars[index] == ' ') - { - parmChars[index] = '\n'; - } - } - return (new string(parmChars)).Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries); - } - - private static Dictionary GetKeyValues(string[] args) - { - Dictionary result = new Dictionary(); - if (args != null) - { - foreach (string arg in args) - { - int valueIndex = arg.IndexOf('='); - if (valueIndex > 0) - { - string key = arg.Substring(0, valueIndex); - string value = arg.Substring(valueIndex + 1); - result[arg.ToLower()] = value; - } - else - { - result[arg.ToLower()] = null; - } - } - } - return result; - } - - private static string GetCurrentDirectory() - { - return AppDirectory; - } - - internal static void CopyFiles(DirectoryInfo source, DirectoryInfo target, bool overwrite) - { - CopyFiles(source, target, overwrite, false); - } - - internal static void CopyFiles(DirectoryInfo source, DirectoryInfo target, bool overwrite, bool recursive) - { - if (!target.Exists) - { - target.Create(); - } - - if (recursive) - { - foreach (DirectoryInfo dir in source.GetDirectories()) - { - CopyFilesRecursive(dir, target.CreateSubdirectory(dir.Name), overwrite); - } - } - foreach (FileInfo file in source.GetFiles()) - { - CopyFile(file.FullName, Path.Combine(target.FullName, file.Name), overwrite); - } - } - - internal static void CopyFilesRecursive(DirectoryInfo source, DirectoryInfo target, bool overwrite) - { - CopyFiles(source, target, overwrite, true); - } - - internal static void CopyFile(string sourceFileName, string destFileName, bool overwrite) - { - if ((overwrite || !File.Exists(destFileName)) && File.Exists(sourceFileName)) - { - try - { - File.Copy(sourceFileName, destFileName, overwrite); - } - catch - { - Console.WriteLine("Failed to copy to '{0}'", destFileName); - } - } - } - - static string GetEnginePathFromCurrentFolder() - { - // Check upwards for /Epic Games/ENGINE_VERSION/Engine/Plugins/USharp/ and extract the path from there - string[] parentFolders = { "Managed", "Binaries", "USharp", "Plugins", "Engine" }; - string currentPath = GetCurrentDirectory(); - - DirectoryInfo dir = Directory.GetParent(currentPath); - for (int i = 0; i < parentFolders.Length; i++) - { - if (!dir.Exists || !dir.Name.Equals(parentFolders[i], StringComparison.OrdinalIgnoreCase)) - { - return null; - } - dir = dir.Parent; - } - - // Make sure one of these folders exists along side the Engine folder: FeaturePacks, Samples, Templates - if (dir.Exists && Directory.Exists(Path.Combine(dir.FullName, "Templates"))) - { - return dir.FullName; - } - - return null; - } - - /// - /// Returns the main USharp plugin directory from the engine path - /// - private static string GetUSharpPluginDirectory(string enginePath) - { - return Path.Combine(enginePath, "Engine", "Plugins", "USharp"); - } - - private static void CompileCs(string[] args) - { - string slnDir = Path.Combine(GetCurrentDirectory(), "../../../Managed/UnrealEngine.Runtime"); - if (!Directory.Exists(slnDir)) - { - Console.WriteLine("Failed to find the UnrealEngine.Runtime directory"); - return; - } - - string loaderProj = Path.Combine(slnDir, "Loader/Loader.csproj"); - string runtimeProj = Path.Combine(slnDir, "UnrealEngine.Runtime/UnrealEngine.Runtime.csproj"); - string assemblyRewriterProj = Path.Combine(slnDir, "UnrealEngine.AssemblyRewriter/UnrealEngine.AssemblyRewriter.csproj"); - string[] projectPaths = { loaderProj, runtimeProj, assemblyRewriterProj }; - string[] shippingBuildProjectPaths = { runtimeProj }; - string slnPath = Path.Combine(slnDir, "UnrealEngine.Runtime.sln"); - - Dictionary keyValues = GetKeyValues(args); - bool x86Build = keyValues.ContainsKey("x86"); - - foreach (string projPath in projectPaths) - { - if (!File.Exists(projPath)) - { - Console.WriteLine("Failed to find C# project '{0}'", projPath); - return; - } - } - - for (int i = 0; i < 2; i++) - { - bool shippingBuild = i == 1; - string[] paths = shippingBuild ? shippingBuildProjectPaths : projectPaths; - - foreach (string projPath in paths) - { - string targetName = Path.GetFileName(projPath); - if (shippingBuild) - { - targetName += " (Shipping)"; - } - - if (!BuildCs(slnPath, projPath, !shippingBuild, x86Build, null)) - { - Console.WriteLine("Failed to build (see build.log) - " + targetName); - return; - } - else - { - Console.WriteLine("Build successful - " + targetName); - } - } - } - } - - private static bool BuildCs(string solutionPath, string projectPath, bool debug, bool x86, string customDefines) - { - string buildLogFile = Path.Combine(GetCurrentDirectory(), "build.log"); - - if (!string.IsNullOrEmpty(solutionPath) && File.Exists(solutionPath)) - { - solutionPath = Path.GetFullPath(solutionPath); - } - if (!string.IsNullOrEmpty(projectPath) && File.Exists(projectPath)) - { - projectPath = Path.GetFullPath(projectPath); - } - - if (string.IsNullOrEmpty(msbuildPath)) - { - msbuildPath = NetRuntimeHelper.FindMsBuildPath(); - } - - if (string.IsNullOrEmpty(msbuildPath)) - { - File.AppendAllText(buildLogFile, "Couldn't find MSBuild path" + Environment.NewLine); - return false; - } - - string config = debug ? "Debug" : "Release"; - string platform = x86 ? "x86" : "\"Any CPU\""; - string fileArgs = "\"" + solutionPath + "\"" + " /p:Configuration=" + config + " /p:Platform=" + platform; - if (!string.IsNullOrEmpty(projectPath)) - { - // '.' must be replaced with '_' for /t - string projectName = Path.GetFileNameWithoutExtension(projectPath).Replace(".", "_"); - - // Skip project references just in case (this means projects should be built in the correct order though) - fileArgs += " /t:" + projectName + " /p:BuildProjectReferences=false"; - } - if (!string.IsNullOrEmpty(customDefines)) - { - Debug.Assert(!customDefines.Contains(' ')); - fileArgs += " /p:DefineConstants=" + customDefines; - } - - File.AppendAllText(buildLogFile, "Build: " + msbuildPath + " - " + fileArgs + Environment.NewLine); - - using (Process process = new Process()) - { - process.StartInfo = new ProcessStartInfo - { - FileName = msbuildPath, - Arguments = fileArgs, - RedirectStandardOutput = true, - RedirectStandardError = true, - UseShellExecute = false, - CreateNoWindow = true - }; - - StringBuilder output = new StringBuilder(); - StringBuilder error = new StringBuilder(); - - using (AutoResetEvent outputWaitHandle = new AutoResetEvent(false)) - using (AutoResetEvent errorWaitHandle = new AutoResetEvent(false)) - { - process.OutputDataReceived += (sender, e) => - { - if (e.Data == null) - { - outputWaitHandle.Set(); - } - else - { - output.AppendLine(e.Data); - } - }; - process.ErrorDataReceived += (sender, e) => - { - if (e.Data == null) - { - errorWaitHandle.Set(); - } - else - { - error.AppendLine(e.Data); - } - }; - - process.Start(); - - process.BeginOutputReadLine(); - process.BeginErrorReadLine(); - - int timeout = 60000; - bool built = process.WaitForExit(timeout) && outputWaitHandle.WaitOne(timeout) && errorWaitHandle.WaitOne(timeout); - - File.AppendAllText(buildLogFile, "Build sln '" + solutionPath + "' proj '" + projectPath + "'" + Environment.NewLine); - File.AppendAllText(buildLogFile, string.Empty.PadLeft(100, '-') + Environment.NewLine); - File.AppendAllText(buildLogFile, output.ToString() + Environment.NewLine); - File.AppendAllText(buildLogFile, error.ToString() + Environment.NewLine + Environment.NewLine); - - if (!built) - { - Console.WriteLine("Failed to wait for compile."); - } - - return built && process.ExitCode == 0; - } - } - } - - private static void CompileCpp(string[] args) - { - Dictionary keyValues = GetKeyValues(args); - bool shippingBuild = keyValues.ContainsKey("shipping"); - bool x86Build = keyValues.ContainsKey("x86"); - bool skipCopy = keyValues.ContainsKey("nocopy"); - bool skipCleanup = keyValues.ContainsKey("noclean"); - - string pluginName = "USharp"; - string pluginExtension = ".uplugin"; - string pluginExtensionTemp = ".uplugin_temp"; - - string enginePath = GetEnginePathFromCurrentFolder(); - string batchFileName = "RunUAT" + (IsWindows ? ".bat" : ".sh"); - string batchFilesDir = Path.Combine(enginePath, "Engine/Build/BatchFiles/"); - string batchPath = Path.Combine(batchFilesDir, batchFileName); - - string pluginDir = Path.Combine(enginePath, "Engine/Plugins/", pluginName); - string pluginPath = Path.Combine(pluginDir, pluginName + pluginExtension); - //string outputDir = Path.Combine(projectBaseDir, "Build"); - - if (!File.Exists(batchPath)) - { - Console.WriteLine("Failed to compile C++ project. Couldn't find RunUAT at '" + batchPath + "'"); - return; - } - - try - { - if (!File.Exists(pluginPath)) - { - // We might have a temp plugin file extension due to a partial previous build - string tempPluginPath = Path.ChangeExtension(pluginPath, pluginExtensionTemp); - if (File.Exists(tempPluginPath)) - { - File.Move(tempPluginPath, pluginPath); - } - } - } - catch - { - } - - if (!File.Exists(pluginPath)) - { - Console.WriteLine("Failed to compile C++ project. Couldn't find the plugin '{0}'", Path.GetFullPath(pluginPath)); - return; - } - - // Use an appdata folder instead of a local Build folder as we may be building from inside the engine folder - // which doesn't allow compile output to be within a sub folder of /Engine/ - string usharpAppData = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "USharp"); - if (!Directory.Exists(usharpAppData)) - { - Directory.CreateDirectory(usharpAppData); - } - string outputDir = Path.Combine(usharpAppData, "Build"); - - // In 4.20 if it detects that the plugin already exists our compilation will fail (even if we are compiling in-place!) - // Therefore we need to rename the existing .uplugin file to have a different extension so that UBT doesn't complain. - // NOTE: For reference the build error is "Found 'USharp' plugin in two locations" ... "Plugin names must be unique." - string existingPluginFile = Path.Combine(pluginDir, pluginName + pluginExtension); - string tempExistingPluginFile = null; - if (File.Exists(existingPluginFile)) - { - tempExistingPluginFile = Path.ChangeExtension(existingPluginFile, pluginExtensionTemp); - if (File.Exists(tempExistingPluginFile)) - { - File.Delete(tempExistingPluginFile); - } - File.Move(existingPluginFile, tempExistingPluginFile); - } - - // Since we are compiling from within the engine plugin folder make sure to use temp changed .plugin_temp file - pluginPath = tempExistingPluginFile; - - // Create *another* temp directory where we will copy just the C++ source files over. Otherwise the build tool will copy - // all of the content files before it builds (which might be a lot of data) - string tempCopyDir = Path.Combine(usharpAppData, "BuildTemp2"); - string tempCopyPluginPath = Path.Combine(tempCopyDir, Path.GetFileName(pluginPath)); - if (!Directory.Exists(tempCopyDir)) - { - Directory.CreateDirectory(tempCopyDir); - } - CopyFile(pluginPath, tempCopyPluginPath, true); - CopyFilesRecursive(new DirectoryInfo(Path.Combine(pluginDir, "Source")), new DirectoryInfo(Path.Combine(tempCopyDir, "Source")), true); - CopyFilesRecursive(new DirectoryInfo(Path.Combine(pluginDir, "Config")), new DirectoryInfo(Path.Combine(tempCopyDir, "Config")), true); - // The Intermediate directory doesn't seem to improve compile times so don't bother copying it for now (saves around 100MB of data copying 2x) - //CopyFilesRecursive(new DirectoryInfo(Path.Combine(pluginDir, "Intermediate")), new DirectoryInfo(Path.Combine(tempCopyDir, "Intermediate")), true); - - try - { - using (Process process = new Process()) - { - process.StartInfo = new ProcessStartInfo() - { - FileName = batchPath, - UseShellExecute = false, - - // The -Platform arg is ignored? It instead compiles based on whitelisted/blacklisted? (or for all platforms if no list) - Arguments = string.Format("BuildPlugin -Plugin=\"{0}\" -Package=\"{1}\" -Rocket -Platform=Win64", tempCopyPluginPath, outputDir) - }; - process.Start(); - process.WaitForExit(); - } - - if (!skipCopy) - { - // Copy the entire contents of /Binaries/ and /Intermediate/ - string[] copyDirs = { "Binaries", "Intermediate" }; - foreach (string dir in copyDirs) - { - if (Directory.Exists(Path.Combine(outputDir, dir))) - { - CopyFilesRecursive(new DirectoryInfo(Path.Combine(outputDir, dir)), - new DirectoryInfo(Path.Combine(pluginDir, dir)), true); - } - } - } - } - finally - { - try - { - if (!string.IsNullOrEmpty(tempExistingPluginFile) && File.Exists(tempExistingPluginFile)) - { - if (File.Exists(existingPluginFile)) - { - File.Delete(existingPluginFile); - } - File.Move(tempExistingPluginFile, existingPluginFile); - } - } - catch - { - } - - if (!skipCleanup) - { - try - { - if (Directory.Exists(outputDir)) - { - Directory.Delete(outputDir, true); - } - } - catch - { - } - } - - try - { - if (Directory.Exists(tempCopyDir)) - { - Directory.Delete(tempCopyDir, true); - } - } - catch - { - } - } - } - - static bool BuildCustomSolution(string slnPath, string projPath) - { - Console.WriteLine("Attempting to build solution: " + slnPath); - bool buildcs = BuildCs(slnPath, projPath, true, false, null); - if(buildcs) - { - Console.WriteLine("Solution was compiled successfully"); - } - else - { - Console.WriteLine("There was an issue with compiling the provided solution: " + slnPath); - } - return buildcs; - } - } -} + class Program + { + private const string ExampleEnginePath = "C:/Epic Games/UE_4.24/"; + private static string msbuildPath; + + public static readonly bool IsLinux; + public static readonly bool IsMacOS; + public static readonly bool IsWindows; + + /// + /// The directory path of PluginInstaller.exe + /// + public static string AppDirectory; + + static Program() + { + switch (Environment.OSVersion.Platform) + { + case PlatformID.Unix: + case PlatformID.MacOSX: + if (File.Exists("/usr/lib/libc.dylib") && File.Exists("/System/Library/CoreServices/SystemVersion.plist")) + { + // This isn't exactly fool proof but msbuild does similar in NativeMethodsShared.cs + IsMacOS = true; + } + else + { + IsLinux = true; + } + break; + default: + IsWindows = true; + break; + } + } + + static void Main(string[] args) + { + AppDirectory = Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath); + + string enginePath = GetEnginePathFromCurrentFolder(); + if (string.IsNullOrEmpty(enginePath) || !Directory.Exists(enginePath)) + { + Console.WriteLine("Failed to find the engine folder! Make sure PluginInstaller.exe is under /Engine/Plugins/USharp/Binaries/Managed/PluginInstaller/PluginInstaller.exe"); + Console.ReadLine(); + return; + } + + PrintHelp(); + Console.WriteLine(); + + Console.WriteLine("Targeting engine version '" + new DirectoryInfo(enginePath).Name + "'"); + Console.WriteLine(); + + ProcessArgs(null, args); + + while (true) + { + string line = Console.ReadLine(); + string[] lineArgs = ParseArgs(line); + if (ProcessArgs(line, lineArgs)) + { + break; + } + } + } + + private static bool ProcessArgs(string commandLine, string[] args) + { + if (args.Length > 0) + { + switch (args[0].ToLower()) + { + case "exit": + case "close": + case "quit": + case "q": + return true; + + case "clear": + case "cls": + Console.Clear(); + break; + + case "build": + CompileCs(args); + CompileCpp(args); + Console.WriteLine("done"); + break; + + case "buildcs": + CompileCs(args); + Console.WriteLine("done"); + break; + + case "buildcustomsln": + if (args.Length >= 3 && + !string.IsNullOrEmpty(args[1]) && File.Exists(args[1]) && + !string.IsNullOrEmpty(args[2]) && File.Exists(args[2])) + { + BuildCustomSolution(args[1], args[2]); + } + break; + + case "buildcpp": + { + Stopwatch cppCompileTime = new Stopwatch(); + cppCompileTime.Start(); + CompileCpp(args); + Console.WriteLine("done (" + cppCompileTime.Elapsed + ")"); + } + break; + + case "copyruntime": + if (args.Length >= 2) + { + bool minimal = args.Length >= 3 && args[2].ToLower() == "min"; + string configFile = NetRuntimeHelper.GetConfigFile(minimal); + + if (File.Exists(configFile)) + { + switch (args[1].ToLower()) + { + case "all": + NetRuntimeHelper.CopyAll(minimal); + Console.WriteLine("done"); + break; + case "mono": + NetRuntimeHelper.CopyMono(minimal); + Console.WriteLine("done"); + break; + case "coreclr": + NetRuntimeHelper.CopyCoreCLR(minimal); + Console.WriteLine("done"); + break; + } + } + else + { + Console.WriteLine("Couldn't find '" + configFile + "'"); + } + } + else + { + Console.WriteLine("Invalid input. Expected one of the following: all, mono, coreclr"); + } + break; + + case "help": + case "?": + PrintHelp(); + break; + } + } + + return false; + } + + private static void PrintHelp() + { + Console.WriteLine("Available commands:"); + Console.WriteLine("- build builds C# and C++ projects"); + Console.WriteLine("- buildcs builds C# projects (Loader, AssemblyRewriter, Runtime)"); + Console.WriteLine("- buildcpp builds C++ projects"); + Console.WriteLine("- copyruntime [all] [mono] [coreclr] copies the given runtime(s) locally"); + } + + private static string[] ParseArgs(string commandLine) + { + char[] parmChars = commandLine.ToCharArray(); + bool inSingleQuote = false; + bool inDoubleQuote = false; + for (var index = 0; index < parmChars.Length; index++) + { + if (parmChars[index] == '"' && !inSingleQuote) + { + inDoubleQuote = !inDoubleQuote; + parmChars[index] = '\n'; + } + if (parmChars[index] == '\'' && !inDoubleQuote) + { + inSingleQuote = !inSingleQuote; + parmChars[index] = '\n'; + } + if (!inSingleQuote && !inDoubleQuote && parmChars[index] == ' ') + { + parmChars[index] = '\n'; + } + } + return (new string(parmChars)).Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries); + } + + private static Dictionary GetKeyValues(string[] args) + { + Dictionary result = new Dictionary(); + if (args != null) + { + foreach (string arg in args) + { + int valueIndex = arg.IndexOf('='); + if (valueIndex > 0) + { + string key = arg.Substring(0, valueIndex); + string value = arg.Substring(valueIndex + 1); + result[arg.ToLower()] = value; + } + else + { + result[arg.ToLower()] = null; + } + } + } + return result; + } + + private static string GetCurrentDirectory() + { + return AppDirectory; + } + + internal static void CopyFiles(DirectoryInfo source, DirectoryInfo target, bool overwrite) + { + CopyFiles(source, target, overwrite, false); + } + + internal static void CopyFiles(DirectoryInfo source, DirectoryInfo target, bool overwrite, bool recursive) + { + if (!target.Exists) + { + target.Create(); + } + + if (recursive) + { + foreach (DirectoryInfo dir in source.GetDirectories()) + { + CopyFilesRecursive(dir, target.CreateSubdirectory(dir.Name), overwrite); + } + } + foreach (FileInfo file in source.GetFiles()) + { + CopyFile(file.FullName, Path.Combine(target.FullName, file.Name), overwrite); + } + } + + internal static void CopyFilesRecursive(DirectoryInfo source, DirectoryInfo target, bool overwrite) + { + CopyFiles(source, target, overwrite, true); + } + + internal static void CopyFile(string sourceFileName, string destFileName, bool overwrite) + { + if ((overwrite || !File.Exists(destFileName)) && File.Exists(sourceFileName)) + { + try + { + File.Copy(sourceFileName, destFileName, overwrite); + } + catch + { + Console.WriteLine("Failed to copy to '{0}'", destFileName); + } + } + } + + static string GetEnginePathFromCurrentFolder() + { + // Check upwards for /Epic Games/ENGINE_VERSION/Engine/Plugins/USharp/ and extract the path from there + string[] parentFolders = { "Managed", "Binaries", "USharp", "Plugins", "Engine" }; + string currentPath = GetCurrentDirectory(); + + DirectoryInfo dir = Directory.GetParent(currentPath); + for (int i = 0; i < parentFolders.Length; i++) + { + if (!dir.Exists || !dir.Name.Equals(parentFolders[i], StringComparison.OrdinalIgnoreCase)) + { + return null; + } + dir = dir.Parent; + } + + // Make sure one of these folders exists along side the Engine folder: FeaturePacks, Samples, Templates + if (dir.Exists && Directory.Exists(Path.Combine(dir.FullName, "Templates"))) + { + return dir.FullName; + } + + return null; + } + + /// + /// Returns the main USharp plugin directory from the engine path + /// + private static string GetUSharpPluginDirectory(string enginePath) + { + return Path.Combine(enginePath, "Engine", "Plugins", "USharp"); + } + + private static void CompileCs(string[] args) + { + string slnDir = Path.Combine(GetCurrentDirectory(), "../../../Managed/UnrealEngine.Runtime"); + if (!Directory.Exists(slnDir)) + { + Console.WriteLine("Failed to find the UnrealEngine.Runtime directory"); + return; + } + + string loaderProj = Path.Combine(slnDir, "Loader/Loader.csproj"); + string runtimeProj = Path.Combine(slnDir, "UnrealEngine.Runtime/UnrealEngine.Runtime.csproj"); + string assemblyRewriterProj = Path.Combine(slnDir, "UnrealEngine.AssemblyRewriter/UnrealEngine.AssemblyRewriter.csproj"); + string[] projectPaths = { loaderProj, runtimeProj, assemblyRewriterProj }; + string[] shippingBuildProjectPaths = { runtimeProj }; + string slnPath = Path.Combine(slnDir, "UnrealEngine.Runtime.sln"); + + Dictionary keyValues = GetKeyValues(args); + bool x86Build = keyValues.ContainsKey("x86"); + + foreach (string projPath in projectPaths) + { + if (!File.Exists(projPath)) + { + Console.WriteLine("Failed to find C# project '{0}'", projPath); + return; + } + } + + for (int i = 0; i < 2; i++) + { + bool shippingBuild = i == 1; + string[] paths = shippingBuild ? shippingBuildProjectPaths : projectPaths; + + foreach (string projPath in paths) + { + string targetName = Path.GetFileName(projPath); + if (shippingBuild) + { + targetName += " (Shipping)"; + } + + if (!BuildCs(slnPath, projPath, !shippingBuild, x86Build, null)) + { + Console.WriteLine("Failed to build (see build.log) - " + targetName); + return; + } + else + { + Console.WriteLine("Build successful - " + targetName); + } + } + } + } + + private static bool BuildCs(string solutionPath, string projectPath, bool debug, bool x86, string customDefines) + { + string buildLogFile = Path.Combine(GetCurrentDirectory(), "build.log"); + + if (!string.IsNullOrEmpty(solutionPath) && File.Exists(solutionPath)) + { + solutionPath = Path.GetFullPath(solutionPath); + } + if (!string.IsNullOrEmpty(projectPath) && File.Exists(projectPath)) + { + projectPath = Path.GetFullPath(projectPath); + } + + if (string.IsNullOrEmpty(msbuildPath)) + { + msbuildPath = NetRuntimeHelper.FindMsBuildPath(); + } + + if (string.IsNullOrEmpty(msbuildPath)) + { + File.AppendAllText(buildLogFile, "Couldn't find MSBuild path" + Environment.NewLine); + return false; + } + + string config = debug ? "Debug" : "Release"; + string platform = x86 ? "x86" : "\"Any CPU\""; + string fileArgs = "\"" + solutionPath + "\"" + " /p:Configuration=" + config + " /p:Platform=" + platform; + if (!string.IsNullOrEmpty(projectPath)) + { + // '.' must be replaced with '_' for /t + string projectName = Path.GetFileNameWithoutExtension(projectPath).Replace(".", "_"); + + // Skip project references just in case (this means projects should be built in the correct order though) + fileArgs += " /t:" + projectName + " /p:BuildProjectReferences=false"; + } + if (!string.IsNullOrEmpty(customDefines)) + { + Debug.Assert(!customDefines.Contains(' ')); + fileArgs += " /p:DefineConstants=" + customDefines; + } + + File.AppendAllText(buildLogFile, "Build: " + msbuildPath + " - " + fileArgs + Environment.NewLine); + + using (Process process = new Process()) + { + process.StartInfo = new ProcessStartInfo + { + FileName = msbuildPath, + Arguments = fileArgs, + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false, + CreateNoWindow = true + }; + + StringBuilder output = new StringBuilder(); + StringBuilder error = new StringBuilder(); + + using (AutoResetEvent outputWaitHandle = new AutoResetEvent(false)) + using (AutoResetEvent errorWaitHandle = new AutoResetEvent(false)) + { + process.OutputDataReceived += (sender, e) => + { + if (e.Data == null) + { + outputWaitHandle.Set(); + } + else + { + output.AppendLine(e.Data); + } + }; + process.ErrorDataReceived += (sender, e) => + { + if (e.Data == null) + { + errorWaitHandle.Set(); + } + else + { + error.AppendLine(e.Data); + } + }; + + process.Start(); + + process.BeginOutputReadLine(); + process.BeginErrorReadLine(); + + int timeout = 60000; + bool built = process.WaitForExit(timeout) && outputWaitHandle.WaitOne(timeout) && errorWaitHandle.WaitOne(timeout); + + File.AppendAllText(buildLogFile, "Build sln '" + solutionPath + "' proj '" + projectPath + "'" + Environment.NewLine); + File.AppendAllText(buildLogFile, string.Empty.PadLeft(100, '-') + Environment.NewLine); + File.AppendAllText(buildLogFile, output.ToString() + Environment.NewLine); + File.AppendAllText(buildLogFile, error.ToString() + Environment.NewLine + Environment.NewLine); + + if (!built) + { + Console.WriteLine("Failed to wait for compile."); + } + + return built && process.ExitCode == 0; + } + } + } + + private static void CompileCpp(string[] args) + { + Dictionary keyValues = GetKeyValues(args); + bool shippingBuild = keyValues.ContainsKey("shipping"); + bool x86Build = keyValues.ContainsKey("x86"); + bool skipCopy = keyValues.ContainsKey("nocopy"); + bool skipCleanup = keyValues.ContainsKey("noclean"); + + string pluginName = "USharp"; + string pluginExtension = ".uplugin"; + string pluginExtensionTemp = ".uplugin_temp"; + + string enginePath = GetEnginePathFromCurrentFolder(); + string batchFileName = "RunUAT" + (IsWindows ? ".bat" : ".sh"); + string batchFilesDir = Path.Combine(enginePath, "Engine/Build/BatchFiles/"); + string batchPath = Path.Combine(batchFilesDir, batchFileName); + + string pluginDir = Path.Combine(enginePath, "Engine/Plugins/", pluginName); + string pluginPath = Path.Combine(pluginDir, pluginName + pluginExtension); + //string outputDir = Path.Combine(projectBaseDir, "Build"); + + if (!File.Exists(batchPath)) + { + Console.WriteLine("Failed to compile C++ project. Couldn't find RunUAT at '" + batchPath + "'"); + return; + } + + try + { + if (!File.Exists(pluginPath)) + { + // We might have a temp plugin file extension due to a partial previous build + string tempPluginPath = Path.ChangeExtension(pluginPath, pluginExtensionTemp); + if (File.Exists(tempPluginPath)) + { + File.Move(tempPluginPath, pluginPath); + } + } + } + catch + { + } + + if (!File.Exists(pluginPath)) + { + Console.WriteLine("Failed to compile C++ project. Couldn't find the plugin '{0}'", Path.GetFullPath(pluginPath)); + return; + } + + // Use an appdata folder instead of a local Build folder as we may be building from inside the engine folder + // which doesn't allow compile output to be within a sub folder of /Engine/ + string usharpAppData = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "USharp"); + if (!Directory.Exists(usharpAppData)) + { + Directory.CreateDirectory(usharpAppData); + } + string outputDir = Path.Combine(usharpAppData, "Build"); + + // In 4.20 if it detects that the plugin already exists our compilation will fail (even if we are compiling in-place!) + // Therefore we need to rename the existing .uplugin file to have a different extension so that UBT doesn't complain. + // NOTE: For reference the build error is "Found 'USharp' plugin in two locations" ... "Plugin names must be unique." + string existingPluginFile = Path.Combine(pluginDir, pluginName + pluginExtension); + string tempExistingPluginFile = Path.ChangeExtension(existingPluginFile, pluginExtensionTemp); + + // Create *another* temp directory where we will copy just the C++ source files over. Otherwise the build tool will copy + // all of the content files before it builds (which might be a lot of data) + string tempCopyDir = Path.Combine(usharpAppData, "BuildTemp2"); + string tempCopyPluginPath = Path.Combine(tempCopyDir, Path.GetFileName(pluginPath)); + if (!Directory.Exists(tempCopyDir)) + { + Directory.CreateDirectory(tempCopyDir); + } + CopyFile(pluginPath, tempCopyPluginPath, true); + CopyFilesRecursive(new DirectoryInfo(Path.Combine(pluginDir, "Source")), new DirectoryInfo(Path.Combine(tempCopyDir, "Source")), true); + CopyFilesRecursive(new DirectoryInfo(Path.Combine(pluginDir, "Config")), new DirectoryInfo(Path.Combine(tempCopyDir, "Config")), true); + // The Intermediate directory doesn't seem to improve compile times so don't bother copying it for now (saves around 100MB of data copying 2x) + //CopyFilesRecursive(new DirectoryInfo(Path.Combine(pluginDir, "Intermediate")), new DirectoryInfo(Path.Combine(tempCopyDir, "Intermediate")), true); + + // Since we are compiling from within the engine plugin folder make sure to use temp changed .plugin_temp file + pluginPath = tempExistingPluginFile; + if (File.Exists(tempExistingPluginFile)) + { + File.Delete(tempExistingPluginFile); + } + File.Move(existingPluginFile, tempExistingPluginFile); + + try + { + using (Process process = new Process()) + { + process.StartInfo = new ProcessStartInfo() + { + FileName = batchPath, + UseShellExecute = false, + + // The -Platform arg is ignored? It instead compiles based on whitelisted/blacklisted? (or for all platforms if no list) + Arguments = string.Format("BuildPlugin -Plugin=\"{0}\" -Package=\"{1}\" -Rocket -Platform=Win64", tempCopyPluginPath, outputDir) + }; + process.Start(); + process.WaitForExit(); + } + + if (!skipCopy) + { + // Copy the entire contents of /Binaries/ and /Intermediate/ + string[] copyDirs = { "Binaries", "Intermediate" }; + foreach (string dir in copyDirs) + { + if (Directory.Exists(Path.Combine(outputDir, dir))) + { + CopyFilesRecursive(new DirectoryInfo(Path.Combine(outputDir, dir)), + new DirectoryInfo(Path.Combine(pluginDir, dir)), true); + } + } + } + } + finally + { + try + { + if (!string.IsNullOrEmpty(tempExistingPluginFile) && File.Exists(tempExistingPluginFile)) + { + if (File.Exists(existingPluginFile)) + { + File.Delete(existingPluginFile); + } + File.Move(tempExistingPluginFile, existingPluginFile); + } + } + catch + { + } + + if (!skipCleanup) + { + try + { + if (Directory.Exists(outputDir)) + { + Directory.Delete(outputDir, true); + } + } + catch + { + } + } + + try + { + if (Directory.Exists(tempCopyDir)) + { + Directory.Delete(tempCopyDir, true); + } + } + catch + { + } + } + } + + static bool BuildCustomSolution(string slnPath, string projPath) + { + Console.WriteLine("Attempting to build solution: " + slnPath); + bool buildcs = BuildCs(slnPath, projPath, true, false, null); + if (buildcs) + { + Console.WriteLine("Solution was compiled successfully"); + } + else + { + Console.WriteLine("There was an issue with compiling the provided solution: " + slnPath); + } + return buildcs; + } + } +} \ No newline at end of file diff --git a/Managed/UnrealEngine.Runtime/UnrealEngine.Runtime/Core/Math/EAxis.cs b/Managed/UnrealEngine.Runtime/UnrealEngine.Runtime/Core/Math/EAxis.cs index 4abb11b..66fe32c 100644 --- a/Managed/UnrealEngine.Runtime/UnrealEngine.Runtime/Core/Math/EAxis.cs +++ b/Managed/UnrealEngine.Runtime/UnrealEngine.Runtime/Core/Math/EAxis.cs @@ -8,7 +8,7 @@ namespace UnrealEngine.Runtime // Engine\Source\Runtime\Core\Public\Math\Axis.h /// Generic axis enum (mirrored for property use in Object.h) - [UEnum, UMetaPath("/Script/CoreUObject.EAxis")] + [UEnum, UMetaPath("/Script/CoreUObject.Axis")] public enum EAxis { None = 0, diff --git a/Managed/UnrealEngine.Runtime/UnrealEngine.Runtime/CoreUObject/FObjectInitializer.cs b/Managed/UnrealEngine.Runtime/UnrealEngine.Runtime/CoreUObject/FObjectInitializer.cs index d7e2cb0..b6922b1 100644 --- a/Managed/UnrealEngine.Runtime/UnrealEngine.Runtime/CoreUObject/FObjectInitializer.cs +++ b/Managed/UnrealEngine.Runtime/UnrealEngine.Runtime/CoreUObject/FObjectInitializer.cs @@ -182,12 +182,12 @@ public FObjectInitializer DoNotCreateDefaultSubobject(string subobjectName) /// /// Internal use only, checks if the override is legal and if not deal with error messages /// - public bool IslegalOverride(FName componentName, UClass derivedComponentClass, UClass baseComponentClass) - { - return Native_FObjectInitializer.IslegalOverride(NativeObjectInitializer, ref componentName, - derivedComponentClass == null ? IntPtr.Zero : derivedComponentClass.Address, - baseComponentClass == null ? IntPtr.Zero : baseComponentClass.Address); - } + //public bool IslegalOverride(FName componentName, UClass derivedComponentClass, UClass baseComponentClass) + //{ + // return Native_FObjectInitializer.IslegalOverride(NativeObjectInitializer, ref componentName, + // derivedComponentClass == null ? IntPtr.Zero : derivedComponentClass.Address, + // baseComponentClass == null ? IntPtr.Zero : baseComponentClass.Address); + //} public void FinalizeSubobjectClassInitialization() { diff --git a/Managed/UnrealEngine.Runtime/UnrealEngine.Runtime/Engine/Subsystems/FSubsystemCollection.cs b/Managed/UnrealEngine.Runtime/UnrealEngine.Runtime/Engine/Subsystems/FSubsystemCollection.cs index fc9c5fa..5fa921d 100644 --- a/Managed/UnrealEngine.Runtime/UnrealEngine.Runtime/Engine/Subsystems/FSubsystemCollection.cs +++ b/Managed/UnrealEngine.Runtime/UnrealEngine.Runtime/Engine/Subsystems/FSubsystemCollection.cs @@ -22,9 +22,9 @@ internal FSubsystemCollection(IntPtr collectionAddress) /// /// Initialize the collection of systems, systems will be created and initialized. /// - public void Initialize() + public void Initialize(UObject NewOuter) { - Native_FSubsystemCollection.Initialize(collectionAddress); + Native_FSubsystemCollection.Initialize(collectionAddress, NewOuter == null ? IntPtr.Zero : NewOuter.Address); } /// diff --git a/Managed/UnrealEngine.Runtime/UnrealEngine.Runtime/Internal/Native/Native_FObjectInitializer.cs b/Managed/UnrealEngine.Runtime/UnrealEngine.Runtime/Internal/Native/Native_FObjectInitializer.cs index ca00506..ce28327 100644 --- a/Managed/UnrealEngine.Runtime/UnrealEngine.Runtime/Internal/Native/Native_FObjectInitializer.cs +++ b/Managed/UnrealEngine.Runtime/UnrealEngine.Runtime/Internal/Native/Native_FObjectInitializer.cs @@ -16,7 +16,7 @@ static class Native_FObjectInitializer public delegate IntPtr Del_CreateDefaultSubobject(IntPtr instance, IntPtr outer, ref FName subobjectFName, IntPtr returnType, IntPtr classToCreateByDefault, csbool isRequired, csbool isTransient); public delegate IntPtr Del_DoNotCreateDefaultSubobject(IntPtr instance, ref FName subobjectName); public delegate IntPtr Del_DoNotCreateDefaultSubobjectStr(IntPtr instance, ref FScriptArray subobjectName); - public delegate csbool Del_IslegalOverride(IntPtr instance, ref FName componentName, IntPtr derivedComponentClass, IntPtr baseComponentClass); + //public delegate csbool Del_IslegalOverride(IntPtr instance, ref FName componentName, IntPtr derivedComponentClass, IntPtr baseComponentClass); public delegate void Del_FinalizeSubobjectClassInitialization(IntPtr instance); public delegate void Del_AssertIfInConstructor(IntPtr outer, ref FScriptArray errorMessage); public delegate IntPtr Del_Get(); @@ -28,7 +28,7 @@ static class Native_FObjectInitializer public static Del_CreateDefaultSubobject CreateDefaultSubobject; public static Del_DoNotCreateDefaultSubobject DoNotCreateDefaultSubobject; public static Del_DoNotCreateDefaultSubobjectStr DoNotCreateDefaultSubobjectStr; - public static Del_IslegalOverride IslegalOverride; + //public static Del_IslegalOverride IslegalOverride; public static Del_FinalizeSubobjectClassInitialization FinalizeSubobjectClassInitialization; public static Del_AssertIfInConstructor AssertIfInConstructor; public static Del_Get Get; diff --git a/Managed/UnrealEngine.Runtime/UnrealEngine.Runtime/Internal/Native/Native_FSubsystemCollection.cs b/Managed/UnrealEngine.Runtime/UnrealEngine.Runtime/Internal/Native/Native_FSubsystemCollection.cs index 1f1d709..385fd21 100644 --- a/Managed/UnrealEngine.Runtime/UnrealEngine.Runtime/Internal/Native/Native_FSubsystemCollection.cs +++ b/Managed/UnrealEngine.Runtime/UnrealEngine.Runtime/Internal/Native/Native_FSubsystemCollection.cs @@ -9,7 +9,7 @@ namespace UnrealEngine.Runtime.Native { public static class Native_FSubsystemCollection { - public delegate void Del_Initialize(IntPtr instance); + public delegate void Del_Initialize(IntPtr instance, IntPtr NewOuter); public delegate void Del_Deinitialize(IntPtr instance); public delegate csbool Del_InitializeDependency(IntPtr instance, IntPtr subsystemClass); public delegate IntPtr Del_GetSubsystem(IntPtr instance, IntPtr subsystemClass); diff --git a/Settings/ModulesWhitelist.txt b/Settings/ModulesWhitelist.txt index 9c36603..a366386 100644 --- a/Settings/ModulesWhitelist.txt +++ b/Settings/ModulesWhitelist.txt @@ -47,6 +47,7 @@ Sequencer Slate SlateCore SourceControl +StaticMeshDescription TimeManagement UMG UMGEditor diff --git a/Source/USharp/Private/ExportedFunctions/Export_FApp.h b/Source/USharp/Private/ExportedFunctions/Export_FApp.h index 5db82fb..06a77a5 100644 --- a/Source/USharp/Private/ExportedFunctions/Export_FApp.h +++ b/Source/USharp/Private/ExportedFunctions/Export_FApp.h @@ -5,7 +5,7 @@ CSEXPORT void CSCONV Export_FApp_GetBranchName(FString& result) CSEXPORT int32/*EBuildConfigurations::Type*/ CSCONV Export_FApp_GetBuildConfiguration() { - return FApp::GetBuildConfiguration(); + return (int32)FApp::GetBuildConfiguration(); } CSEXPORT void CSCONV Export_FApp_GetBuildVersion(FString& result) diff --git a/Source/USharp/Private/ExportedFunctions/Export_FObjectInitializer.h b/Source/USharp/Private/ExportedFunctions/Export_FObjectInitializer.h index af99be4..a11020c 100644 --- a/Source/USharp/Private/ExportedFunctions/Export_FObjectInitializer.h +++ b/Source/USharp/Private/ExportedFunctions/Export_FObjectInitializer.h @@ -33,10 +33,10 @@ CSEXPORT FObjectInitializer const& CSCONV Export_FObjectInitializer_DoNotCreateD return instance->DoNotCreateDefaultSubobject(*SubobjectName); } -CSEXPORT csbool CSCONV Export_FObjectInitializer_IslegalOverride(FObjectInitializer* instance, const FName& InComponentName, class UClass *DerivedComponentClass, class UClass *BaseComponentClass) -{ - return instance->IslegalOverride(InComponentName, DerivedComponentClass, BaseComponentClass); -} +//CSEXPORT csbool CSCONV Export_FObjectInitializer_IslegalOverride(FObjectInitializer* instance, const FName& InComponentName, class UClass *DerivedComponentClass, class UClass *BaseComponentClass) +//{ +// return instance->IslegalOverride(InComponentName, DerivedComponentClass, BaseComponentClass); +//} CSEXPORT void CSCONV Export_FObjectInitializer_FinalizeSubobjectClassInitialization(FObjectInitializer* instance) { @@ -62,7 +62,7 @@ CSEXPORT void CSCONV Export_FObjectInitializer(RegisterFunc registerFunc) REGISTER_FUNC(Export_FObjectInitializer_CreateDefaultSubobject); REGISTER_FUNC(Export_FObjectInitializer_DoNotCreateDefaultSubobject); REGISTER_FUNC(Export_FObjectInitializer_DoNotCreateDefaultSubobjectStr); - REGISTER_FUNC(Export_FObjectInitializer_IslegalOverride); + //REGISTER_FUNC(Export_FObjectInitializer_IslegalOverride); REGISTER_FUNC(Export_FObjectInitializer_FinalizeSubobjectClassInitialization); REGISTER_FUNC(Export_FObjectInitializer_AssertIfInConstructor); REGISTER_FUNC(Export_FObjectInitializer_Get); diff --git a/Source/USharp/Private/ExportedFunctions/Export_FSubsystemCollection.h b/Source/USharp/Private/ExportedFunctions/Export_FSubsystemCollection.h index 0c4e95b..b15650b 100644 --- a/Source/USharp/Private/ExportedFunctions/Export_FSubsystemCollection.h +++ b/Source/USharp/Private/ExportedFunctions/Export_FSubsystemCollection.h @@ -1,6 +1,6 @@ -CSEXPORT void CSCONV Export_FSubsystemCollection_Initialize(FSubsystemCollectionBase& instance) +CSEXPORT void CSCONV Export_FSubsystemCollection_Initialize(FSubsystemCollectionBase& instance, UObject* NewOuter) { - instance.Initialize(); + instance.Initialize(NewOuter); } CSEXPORT void CSCONV Export_FSubsystemCollection_Deinitialize(FSubsystemCollectionBase& instance) diff --git a/Source/USharp/Private/ExportedFunctions/Export_ICppStructOps.h b/Source/USharp/Private/ExportedFunctions/Export_ICppStructOps.h index 5c2cda3..47c3378 100644 --- a/Source/USharp/Private/ExportedFunctions/Export_ICppStructOps.h +++ b/Source/USharp/Private/ExportedFunctions/Export_ICppStructOps.h @@ -68,7 +68,7 @@ CSEXPORT csbool CSCONV Export_ICppStructOps_HasGetTypeHash(UScriptStruct::ICppSt CSEXPORT uint32 CSCONV Export_ICppStructOps_GetTypeHash(UScriptStruct::ICppStructOps* instance, const void* Src) { - return instance->GetTypeHash(Src); + return instance->GetStructTypeHash(Src); } CSEXPORT uint64 CSCONV Export_ICppStructOps_GetComputedPropertyFlags(UScriptStruct::ICppStructOps* instance) diff --git a/Source/USharp/Private/ExportedFunctions/Export_UField.h b/Source/USharp/Private/ExportedFunctions/Export_UField.h index 5c14ba9..ec05329 100644 --- a/Source/USharp/Private/ExportedFunctions/Export_UField.h +++ b/Source/USharp/Private/ExportedFunctions/Export_UField.h @@ -81,22 +81,22 @@ CSEXPORT csbool CSCONV Export_UField_GetBoolMetaDataF(UField* instance, const FN CSEXPORT int32 CSCONV Export_UField_GetINTMetaData(UField* instance, const FString& Key) { - return instance->GetINTMetaData(*Key); + return instance->GetIntMetaData(*Key); } CSEXPORT int32 CSCONV Export_UField_GetINTMetaDataF(UField* instance, const FName& Key) { - return instance->GetINTMetaData(Key); + return instance->GetIntMetaData(Key); } CSEXPORT float CSCONV Export_UField_GetFLOATMetaData(UField* instance, const FString& Key) { - return instance->GetFLOATMetaData(*Key); + return instance->GetFloatMetaData(*Key); } CSEXPORT float CSCONV Export_UField_GetFLOATMetaDataF(UField* instance, const FName& Key) { - return instance->GetFLOATMetaData(Key); + return instance->GetFloatMetaData(Key); } CSEXPORT UClass* CSCONV Export_UField_GetClassMetaData(UField* instance, const FString& Key) diff --git a/Source/USharp/Private/ExportedFunctions/Internal/HotReload/SharpHotReloadClassReinstancer.cpp b/Source/USharp/Private/ExportedFunctions/Internal/HotReload/SharpHotReloadClassReinstancer.cpp index 5b5bb42..bf95348 100644 --- a/Source/USharp/Private/ExportedFunctions/Internal/HotReload/SharpHotReloadClassReinstancer.cpp +++ b/Source/USharp/Private/ExportedFunctions/Internal/HotReload/SharpHotReloadClassReinstancer.cpp @@ -464,6 +464,7 @@ void FSharpHotReloadClassReinstancer::CollectChangedProperties(FCDOPropertyConta // Delegates case (BaseCastFlags | CASTCLASS_UDelegateProperty): case (BaseCastFlags | CASTCLASS_UMulticastDelegateProperty): + case (BaseCastFlags | CASTCLASS_UMulticastDelegateProperty | CASTCLASS_UMulticastSparseDelegateProperty): { void* OldValuePtr = OldProperty->ContainerPtrToValuePtr(Container.OldPtr); void* NewValuePtr = NewProperty->ContainerPtrToValuePtr(Container.NewPtr); diff --git a/Source/USharpEditor/Private/SharpTemplateProjectDefs.cpp b/Source/USharpEditor/Private/SharpTemplateProjectDefs.cpp index 96e92ae..7a0ef1e 100644 --- a/Source/USharpEditor/Private/SharpTemplateProjectDefs.cpp +++ b/Source/USharpEditor/Private/SharpTemplateProjectDefs.cpp @@ -11,12 +11,14 @@ void USharpTemplateProjectDefs::RegisterTemplate() { - FGameProjectGenerationModule::Get().RegisterTemplateCategory( - TEXT("USharp"), - LOCTEXT("USharpCategory_Name", "C#"), - LOCTEXT("USharpCategory_Description", "C# (USharp)"), - FEditorStyle::GetBrush("GameProjectDialog.BlueprintIcon"), - FEditorStyle::GetBrush("GameProjectDialog.BlueprintImage")); + //Remove This Line For UE_4.24. + //Initialize Inside USharp/Templates/TemplateCategories.ini file instead. + //FGameProjectGenerationModule::Get().RegisterTemplateCategory( + // TEXT("USharp"), + // LOCTEXT("USharpCategory_Name", "C#"), + // LOCTEXT("USharpCategory_Description", "C# (USharp)"), + // FEditorStyle::GetBrush("GameProjectDialog.BlueprintIcon"), + // FEditorStyle::GetBrush("GameProjectDialog.BlueprintImage")); // A seperate tab for "C#/C++" may be useful at a later date when there enough templates to demand it /*FGameProjectGenerationModule::Get().RegisterTemplateCategory( diff --git a/Templates/TemplateCategories.ini b/Templates/TemplateCategories.ini new file mode 100644 index 0000000..31f1e46 --- /dev/null +++ b/Templates/TemplateCategories.ini @@ -0,0 +1,2 @@ +[/Script/GameProjectGeneration.TemplateCategories] + Categories=(Key="USharp", LocalizedDisplayNames=((Language="en", Text="C#")), LocalizedDescriptions=((Language="en", Text="C# (USharp)")), Icon="GameProjectDialog.BlueprintIcon", Image="GameProjectDialog.BlueprintImage", IsMajorCategory=false) \ No newline at end of file