232 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			232 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
|  | using System; | |||
|  | using System.Collections.Generic; | |||
|  | using System.Text; | |||
|  | using EpicGames.Core; | |||
|  | using EpicGames.UHT.Types; | |||
|  | using EpicGames.UHT.Utils; | |||
|  | using UnrealSharpScriptGenerator.Utilities; | |||
|  | 
 | |||
|  | namespace UnrealSharpScriptGenerator; | |||
|  | 
 | |||
|  | public class GeneratorStringBuilder : IDisposable | |||
|  | { | |||
|  |     private int _indent; | |||
|  |     private readonly List<string> _directives = new(); | |||
|  |     private BorrowStringBuilder _borrower = new(StringBuilderCache.Big); | |||
|  |     private StringBuilder StringBuilder => _borrower.StringBuilder; | |||
|  | 
 | |||
|  |     public override string ToString() | |||
|  |     { | |||
|  |         return StringBuilder.ToString(); | |||
|  |     } | |||
|  | 
 | |||
|  |     public void Dispose() | |||
|  |     { | |||
|  |         _borrower.Dispose(); | |||
|  |     } | |||
|  |      | |||
|  |     public void OpenBrace() | |||
|  |     { | |||
|  |         AppendLine("{"); | |||
|  |         Indent(); | |||
|  |     } | |||
|  |      | |||
|  |     public void CloseBrace() | |||
|  |     { | |||
|  |         UnIndent(); | |||
|  |         AppendLine("}"); | |||
|  |     } | |||
|  | 
 | |||
|  |     public void Indent() | |||
|  |     { | |||
|  |        ++_indent; | |||
|  |     } | |||
|  |      | |||
|  |     public void UnIndent() | |||
|  |     { | |||
|  |         --_indent; | |||
|  |     } | |||
|  |      | |||
|  |     public void Append(string text) | |||
|  |     { | |||
|  |         StringBuilder.Append(text); | |||
|  |     } | |||
|  | 
 | |||
|  |     public void AppendLine() | |||
|  |     { | |||
|  |         if (StringBuilder.Length > 0) | |||
|  |         { | |||
|  |             StringBuilder.AppendLine(); | |||
|  |         } | |||
|  |          | |||
|  |         for (int i = 0; i < _indent; i++) | |||
|  |         { | |||
|  |             StringBuilder.Append("    "); | |||
|  |         } | |||
|  |     } | |||
|  |      | |||
|  |     public void AppendLine(string line) | |||
|  |     { | |||
|  |         AppendLine(); | |||
|  |         StringBuilder.Append(line); | |||
|  |     } | |||
|  |      | |||
|  |     public void DeclareDirective(string directive) | |||
|  |     { | |||
|  |         if (_directives.Contains(directive) || string.IsNullOrEmpty(directive)) | |||
|  |         { | |||
|  |             return; | |||
|  |         } | |||
|  |          | |||
|  |         _directives.Add(directive); | |||
|  |         AppendLine($"using {directive};"); | |||
|  |     } | |||
|  |      | |||
|  |     public void DeclareDirectives(List<string> directives) | |||
|  |     { | |||
|  |         foreach (string directive in directives) | |||
|  |         { | |||
|  |             DeclareDirective(directive); | |||
|  |         } | |||
|  |     } | |||
|  |      | |||
|  |     public void BeginPreproccesorBlock(string condition) | |||
|  |     { | |||
|  |         AppendLine($"#if {condition}"); | |||
|  |     } | |||
|  |      | |||
|  |     public void EndPreproccesorBlock() | |||
|  |     { | |||
|  |         AppendLine("#endif"); | |||
|  |     } | |||
|  |      | |||
|  |     public void BeginWithEditorPreproccesorBlock() | |||
|  |     { | |||
|  |         BeginPreproccesorBlock("WITH_EDITOR"); | |||
|  |     } | |||
|  |      | |||
|  |     public void TryAddWithEditor(UhtProperty property) | |||
|  |     { | |||
|  |         if (property.HasAllFlags(EPropertyFlags.EditorOnly)) | |||
|  |         { | |||
|  |             BeginWithEditorPreproccesorBlock(); | |||
|  |         } | |||
|  |     } | |||
|  |      | |||
|  |     public void TryEndWithEditor(UhtProperty property) | |||
|  |     { | |||
|  |         if (property.HasAllFlags(EPropertyFlags.EditorOnly)) | |||
|  |         { | |||
|  |             EndPreproccesorBlock(); | |||
|  |         } | |||
|  |     } | |||
|  |      | |||
|  |     public void TryEndWithEditor(UhtFunction function) | |||
|  |     { | |||
|  |         if (function.FunctionFlags.HasAllFlags(EFunctionFlags.EditorOnly)) | |||
|  |         { | |||
|  |             EndPreproccesorBlock(); | |||
|  |         } | |||
|  |     } | |||
|  |      | |||
|  |     public void TryAddWithEditor(UhtFunction function) | |||
|  |     { | |||
|  |         if (function.FunctionFlags.HasAllFlags(EFunctionFlags.EditorOnly)) | |||
|  |         { | |||
|  |             BeginWithEditorPreproccesorBlock(); | |||
|  |         } | |||
|  |     } | |||
|  |      | |||
|  |     public void BeginUnsafeBlock() | |||
|  |     { | |||
|  |         AppendLine("unsafe"); | |||
|  |         OpenBrace(); | |||
|  |     } | |||
|  |      | |||
|  |     public void EndUnsafeBlock() | |||
|  |     { | |||
|  |         CloseBrace(); | |||
|  |     } | |||
|  |      | |||
|  |     public void GenerateTypeSkeleton(string typeNameSpace, bool blittable = false, bool nullableEnabled = false) | |||
|  |     { | |||
|  |         if (nullableEnabled) | |||
|  |         { | |||
|  |             AppendLine("#nullable enable"); | |||
|  |         } | |||
|  |         DeclareDirective(ScriptGeneratorUtilities.AttributeNamespace); | |||
|  |         DeclareDirective(ScriptGeneratorUtilities.CoreAttributeNamespace); | |||
|  |         DeclareDirective(ScriptGeneratorUtilities.InteropNamespace); | |||
|  |         DeclareDirective(ScriptGeneratorUtilities.MarshallerNamespace); | |||
|  |          | |||
|  |         if (blittable) | |||
|  |         { | |||
|  |             DeclareDirective(ScriptGeneratorUtilities.InteropServicesNamespace); | |||
|  |         } | |||
|  | 
 | |||
|  |         AppendLine(); | |||
|  |         AppendLine($"namespace {typeNameSpace};"); | |||
|  |         AppendLine(); | |||
|  |     } | |||
|  |      | |||
|  |     public void GenerateTypeSkeleton(UhtType type) | |||
|  |     { | |||
|  |         GenerateTypeSkeleton(type.GetNamespace()); | |||
|  |     } | |||
|  |      | |||
|  |     public void DeclareType(UhtType? type , string typeName, string declaredTypeName, string? baseType = null, bool isPartial = true, string? modifiers = "", List<UhtClass>? nativeInterfaces = default, List<string>? csInterfaces = default) | |||
|  |     { | |||
|  |         string partialSpecifier = isPartial ? "partial " : string.Empty; | |||
|  |         List<string> inheritingFrom = new List<string>(); | |||
|  |          | |||
|  |         if (!string.IsNullOrEmpty(baseType)) inheritingFrom.Add(baseType); | |||
|  | 
 | |||
|  |         if (nativeInterfaces != null) | |||
|  |         { | |||
|  |             foreach (UhtType @interface in nativeInterfaces) | |||
|  |             { | |||
|  |                 string fullInterfaceName = @interface.GetFullManagedName(); | |||
|  |                 inheritingFrom.Add(fullInterfaceName); | |||
|  |             } | |||
|  |         } | |||
|  | 
 | |||
|  |         if (csInterfaces != null) | |||
|  |         { | |||
|  |             foreach (string @interface in csInterfaces) inheritingFrom.Add(@interface); | |||
|  |         } | |||
|  | 
 | |||
|  |         string accessSpecifier = "public"; | |||
|  |         if (type != null && type.HasMetadata("InternalType")) | |||
|  |         { | |||
|  |             accessSpecifier = "internal"; | |||
|  |         } | |||
|  | 
 | |||
|  |         string inheritanceSpecifier = | |||
|  |             inheritingFrom.Count > 0 ? $" : {string.Join(", ", inheritingFrom)}" : string.Empty; | |||
|  |          | |||
|  |         AppendLine($"{accessSpecifier}{modifiers} {partialSpecifier}{typeName} {declaredTypeName}{inheritanceSpecifier}"); | |||
|  |         OpenBrace(); | |||
|  |     } | |||
|  |      | |||
|  |     public void AppendStackAlloc(string sizeVariableName) | |||
|  |     { | |||
|  |         AppendLine($"byte* paramsBufferAllocation = stackalloc byte[{sizeVariableName}];"); | |||
|  |         AppendLine("nint paramsBuffer = (nint) paramsBufferAllocation;"); | |||
|  |     } | |||
|  | 
 | |||
|  |     public void AppendStackAllocFunction(string sizeVariableName, string structName, bool appendInitializer = true) | |||
|  |     { | |||
|  |         AppendStackAlloc(sizeVariableName); | |||
|  |          | |||
|  |         if (appendInitializer) | |||
|  |         { | |||
|  |             AppendLine($"{ExporterCallbacks.UFunctionCallbacks}.CallInitializeFunctionParams({structName}, paramsBuffer);"); | |||
|  |         } | |||
|  |     } | |||
|  | 
 | |||
|  |     public void AppendStackAllocProperty(string sizeVariableName, string sourcePropertyName) | |||
|  |     { | |||
|  |         AppendStackAlloc(sizeVariableName); | |||
|  |         AppendLine($"{ExporterCallbacks.FPropertyCallbacks}.CallInitializeValue({sourcePropertyName}, paramsBuffer);"); | |||
|  |     } | |||
|  | } |