Refactoring and reorg of Program file
This commit is contained in:
@@ -10,33 +10,16 @@ using System.Reflection.Emit;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using Microsoft.CSharp;
|
using Microsoft.CSharp;
|
||||||
using BlendFile = Kaitai.BlenderBlend;
|
using BlendFile = Kaitai.BlenderBlend;
|
||||||
|
|
||||||
// ReSharper disable BitwiseOperatorOnEnumWithoutFlags
|
// ReSharper disable BitwiseOperatorOnEnumWithoutFlags
|
||||||
|
|
||||||
namespace CodeGenerator {
|
namespace CodeGenerator {
|
||||||
|
|
||||||
public static class StrExt {
|
|
||||||
public static string ParseFName(this string str) {
|
|
||||||
str = str.Replace("*", "ptr_");
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string ParseFType(this string str) {
|
|
||||||
return str switch {
|
|
||||||
"char" => typeof(char).AssemblyQualifiedName,
|
|
||||||
"short" => typeof(short).AssemblyQualifiedName,
|
|
||||||
"int" => typeof(int).AssemblyQualifiedName,
|
|
||||||
"float" => typeof(float).AssemblyQualifiedName,
|
|
||||||
"double" => typeof(double).AssemblyQualifiedName,
|
|
||||||
"string" => typeof(string).AssemblyQualifiedName,
|
|
||||||
"void" => typeof(object).AssemblyQualifiedName,
|
|
||||||
_ => str
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Program {
|
public class Program {
|
||||||
public static BlendFile blendfile;
|
public static BlendFile blendfile;
|
||||||
private static StringBuilder sb = new();
|
private static StringBuilder sb = new();
|
||||||
|
private const string OutPath = @"Blendfile\DNA";
|
||||||
|
private const string Namespace = "BlendFile.DNA";
|
||||||
|
private static readonly string[] AdaptedTypes = new[] { "uchar" };
|
||||||
|
|
||||||
public static void Log(string message) {
|
public static void Log(string message) {
|
||||||
sb.AppendLine(message);
|
sb.AppendLine(message);
|
||||||
@@ -44,56 +27,69 @@ namespace CodeGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void Main(string[] args) {
|
public static void Main(string[] args) {
|
||||||
|
ReadBlendFile();
|
||||||
|
|
||||||
|
Log("Generating C# code");
|
||||||
|
|
||||||
|
Log("Pass 1: Generating types");
|
||||||
|
CodeNamespace ns = GenerateTypes();
|
||||||
|
|
||||||
|
Log("Pass 2: Writing out code");
|
||||||
|
OutputCodeFiles(ns);
|
||||||
|
|
||||||
|
Log("Finished generating C# code");
|
||||||
|
File.AppendAllText("Log.txt", sb.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ReadBlendFile() {
|
||||||
Log("Reading empty.blend file");
|
Log("Reading empty.blend file");
|
||||||
blendfile = BlendFile.FromFile("empty.blend");
|
blendfile = BlendFile.FromFile("empty.blend");
|
||||||
|
|
||||||
Log($"Header: Blender v{blendfile.Hdr.Version} {blendfile.Hdr.Endian}\n" +
|
Log($"Header: Blender v{blendfile.Hdr.Version} {blendfile.Hdr.Endian}\n" +
|
||||||
$"DataBlocks: {blendfile.Blocks.Count}\n" +
|
$"DataBlocks: {blendfile.Blocks.Count}\n" +
|
||||||
$"DNA1: {blendfile.SdnaStructs.Count} structures\n");
|
$"DNA1: {blendfile.SdnaStructs.Count} structures\n");
|
||||||
|
}
|
||||||
Log("Generating C# code");
|
|
||||||
|
|
||||||
//Create a new NameSpace
|
|
||||||
CodeNamespace ns = new CodeNamespace("Blender");
|
|
||||||
|
|
||||||
Log("Pass 1: Generating structs");
|
|
||||||
|
|
||||||
|
private static CodeNamespace GenerateTypes() {
|
||||||
|
CodeNamespace ns = new CodeNamespace(Namespace);
|
||||||
foreach (var type in blendfile.SdnaStructs) {
|
foreach (var type in blendfile.SdnaStructs) {
|
||||||
Log($"Generating struct {type.Type}");
|
Log($"Generating struct {type.Type}");
|
||||||
bool referenceSelf = false;
|
bool referenceSelf = false;
|
||||||
bool referencePointer = false;
|
bool referencePointer = false;
|
||||||
|
|
||||||
//Create a new type declaration
|
//Create a new type declaration
|
||||||
var ctd = new CodeTypeDeclaration(type.Type);// { IsStruct = true };
|
var ctd = new CodeTypeDeclaration(type.Type); // { IsStruct = true };
|
||||||
|
|
||||||
foreach (var field in type.Fields) {
|
foreach (var field in type.Fields) {
|
||||||
if(field.Name.Contains("*")) {
|
if (field.Name.Contains("*")) {
|
||||||
referencePointer = true;
|
referencePointer = true;
|
||||||
}
|
}
|
||||||
if(field.Type.Contains(type.Type)) {
|
if (field.Type.Contains(type.Type)) {
|
||||||
referenceSelf = true;
|
referenceSelf = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(referenceSelf || referencePointer) {
|
if (referenceSelf || referencePointer) {
|
||||||
Log("Struct contains references");
|
Log("Struct contains references");
|
||||||
ctd.IsClass = true;
|
ctd.IsClass = true;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
ctd.IsStruct = true;
|
ctd.IsStruct = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Add the class to the namespace
|
//Add the class to the namespace
|
||||||
ns.Types.Add(ctd);
|
ns.Types.Add(ctd);
|
||||||
|
|
||||||
//Add the fields to the class
|
//Add the fields to the class
|
||||||
Log($"Fields: {type.Fields.Count}");
|
Log($"Fields: {type.Fields.Count}");
|
||||||
|
|
||||||
foreach (var field in type.Fields) {
|
foreach (var field in type.Fields) {
|
||||||
CodeMemberField cmf;
|
CodeMemberField cmf;
|
||||||
string name = field.Name;
|
string name = field.Name;
|
||||||
if (field.Name.Contains("[")) {
|
if (field.Name.Contains("[")) {
|
||||||
Log($"Generating array field {field.Name}");
|
Log($"Generating array field {field.Name}");
|
||||||
cmf = CreateArrayMemberField(field);
|
cmf = CreateArrayMemberField(field);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
Log($"Generating field {field.Name}");
|
Log($"Generating field {field.Name}");
|
||||||
cmf = CreateMemberField(field);
|
cmf = CreateMemberField(field);
|
||||||
}
|
}
|
||||||
@@ -106,79 +102,7 @@ namespace CodeGenerator {
|
|||||||
|
|
||||||
Log("Finished generating struct");
|
Log("Finished generating struct");
|
||||||
}
|
}
|
||||||
|
return ns;
|
||||||
Log("Pass 2: Writing out code");
|
|
||||||
CodeNamespace tempNs = new CodeNamespace("BlendFile.DNA");
|
|
||||||
if(!Path.Exists("Blendfile\\DNA")) {
|
|
||||||
Directory.CreateDirectory("Blendfile\\DNA");
|
|
||||||
}
|
|
||||||
|
|
||||||
CodeGeneratorOptions codeGeneratorOptions = new CodeGeneratorOptions() {
|
|
||||||
BlankLinesBetweenMembers = false,
|
|
||||||
BracingStyle = "Block",
|
|
||||||
ElseOnClosing = false,
|
|
||||||
IndentString = " ",
|
|
||||||
VerbatimOrder = false
|
|
||||||
};
|
|
||||||
var provider = new CSharpCodeProvider();
|
|
||||||
|
|
||||||
foreach (var type in ns.Types.OfType<CodeTypeDeclaration>()) {
|
|
||||||
tempNs.Types.Add(type);
|
|
||||||
Log($"Writing out {(type.IsStruct ? "struct" : "class")} {type.Name}");
|
|
||||||
using var sw = new StreamWriter($"Blender\\{type.Name}.cs");
|
|
||||||
provider.GenerateCodeFromNamespace(tempNs, sw, codeGeneratorOptions);
|
|
||||||
tempNs.Types.Remove(type);
|
|
||||||
}
|
|
||||||
Log("Finished generating C# code");
|
|
||||||
|
|
||||||
File.AppendAllText("Log.txt", sb.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static CodeTypeConstructor GenerateStaticConstructor(CodeTypeDeclaration ctd) {
|
|
||||||
CodeTypeConstructor ctc = new CodeTypeConstructor();
|
|
||||||
ctc.Attributes = MemberAttributes.Static;
|
|
||||||
ctc.Statements.AddRange(ctd.Members
|
|
||||||
.OfType<CodeMemberField>()
|
|
||||||
.Where(f => f.Type.ArrayRank > 0)
|
|
||||||
.Select(f => {
|
|
||||||
var dims = new List<int>();
|
|
||||||
for (int i = 0; i < f.Type.ArrayRank; i++) {
|
|
||||||
dims.Add(0);
|
|
||||||
}
|
|
||||||
return new CodeAssignStatement(
|
|
||||||
new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), f.Name),
|
|
||||||
NewArray(f.Type, dims)
|
|
||||||
);
|
|
||||||
}).ToArray<CodeStatement>());
|
|
||||||
return ctc;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static CodeConstructor GenerateConstructor(BlenderBlend.DnaStruct type, CodeTypeDeclaration ctd) {
|
|
||||||
//Create a normal constructor
|
|
||||||
CodeConstructor cc = new CodeConstructor {
|
|
||||||
Name = type.Type,
|
|
||||||
Attributes = MemberAttributes.Public,
|
|
||||||
ReturnType = new(type.Type)
|
|
||||||
};
|
|
||||||
|
|
||||||
//Add the parameters to the constructor
|
|
||||||
cc.Parameters.AddRange(ctd.Members
|
|
||||||
.OfType<CodeMemberField>()
|
|
||||||
.Select(f => {
|
|
||||||
var cpde = new CodeParameterDeclarationExpression(f.Type, f.Name);
|
|
||||||
cpde.Direction = FieldDirection.In;
|
|
||||||
return cpde;
|
|
||||||
}).ToArray());
|
|
||||||
|
|
||||||
//Assign the parameters to the respective fields
|
|
||||||
cc.Statements.AddRange(ctd.Members
|
|
||||||
.OfType<CodeMemberField>()
|
|
||||||
.Select(f => new CodeAssignStatement(
|
|
||||||
new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), f.Name),
|
|
||||||
new CodeArgumentReferenceExpression(f.Name))
|
|
||||||
).ToArray<CodeStatement>());
|
|
||||||
|
|
||||||
return cc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static CodeMemberField CreateMemberField(BlenderBlend.DnaField field) {
|
private static CodeMemberField CreateMemberField(BlenderBlend.DnaField field) {
|
||||||
@@ -224,13 +148,86 @@ namespace CodeGenerator {
|
|||||||
cmf.Type.ArrayRank = dimensions.Count;
|
cmf.Type.ArrayRank = dimensions.Count;
|
||||||
|
|
||||||
//Define the array initialization expression
|
//Define the array initialization expression
|
||||||
cmf.InitExpression = NewArray(cmf.Type, dimensions);
|
cmf.InitExpression = GenerateArrayInitExpression(cmf.Type, dimensions);
|
||||||
return cmf;
|
return cmf;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CodeExpression NewArray (CodeTypeReference type, IEnumerable<int> dimensions) {
|
public static CodeExpression GenerateArrayInitExpression(CodeTypeReference type, IEnumerable<int> dimensions) {
|
||||||
string dims = string.Concat(dimensions.Select(d => $"[{d}]"));
|
string dims = string.Concat(dimensions.Select(d => $"[{d}]"));
|
||||||
return new CodeSnippetExpression($"new {type.BaseType}{dims}");
|
return new CodeSnippetExpression($"new {type.BaseType}{dims}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static CodeTypeConstructor GenerateStaticConstructor(CodeTypeDeclaration ctd) {
|
||||||
|
CodeTypeConstructor ctc = new CodeTypeConstructor();
|
||||||
|
ctc.Attributes = MemberAttributes.Static;
|
||||||
|
ctc.Statements.AddRange(ctd.Members
|
||||||
|
.OfType<CodeMemberField>()
|
||||||
|
.Where(f => f.Type.ArrayRank > 0)
|
||||||
|
.Select(f =>
|
||||||
|
{
|
||||||
|
var dims = new List<int>();
|
||||||
|
for (int i = 0; i < f.Type.ArrayRank; i++) {
|
||||||
|
dims.Add(0);
|
||||||
|
}
|
||||||
|
return new CodeAssignStatement(
|
||||||
|
new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), f.Name),
|
||||||
|
GenerateArrayInitExpression(f.Type, dims)
|
||||||
|
);
|
||||||
|
}).ToArray<CodeStatement>());
|
||||||
|
return ctc;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CodeConstructor GenerateConstructor(BlenderBlend.DnaStruct type, CodeTypeDeclaration ctd) {
|
||||||
|
//Create a normal constructor
|
||||||
|
CodeConstructor cc = new CodeConstructor {
|
||||||
|
Name = type.Type,
|
||||||
|
Attributes = MemberAttributes.Public,
|
||||||
|
ReturnType = new(type.Type)
|
||||||
|
};
|
||||||
|
|
||||||
|
//Add the parameters to the constructor
|
||||||
|
cc.Parameters.AddRange(ctd.Members
|
||||||
|
.OfType<CodeMemberField>()
|
||||||
|
.Select(f =>
|
||||||
|
{
|
||||||
|
var cpde = new CodeParameterDeclarationExpression(f.Type, f.Name);
|
||||||
|
cpde.Direction = FieldDirection.In;
|
||||||
|
return cpde;
|
||||||
|
}).ToArray());
|
||||||
|
|
||||||
|
//Assign the parameters to the respective fields
|
||||||
|
cc.Statements.AddRange(ctd.Members
|
||||||
|
.OfType<CodeMemberField>()
|
||||||
|
.Select(f => new CodeAssignStatement(
|
||||||
|
new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), f.Name),
|
||||||
|
new CodeArgumentReferenceExpression(f.Name))
|
||||||
|
).ToArray<CodeStatement>());
|
||||||
|
|
||||||
|
return cc;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OutputCodeFiles(CodeNamespace ns) {
|
||||||
|
CodeNamespace tempNs = new CodeNamespace(Namespace);
|
||||||
|
if (!Path.Exists(OutPath)) {
|
||||||
|
Directory.CreateDirectory(OutPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
CodeGeneratorOptions codeGeneratorOptions = new CodeGeneratorOptions() {
|
||||||
|
BlankLinesBetweenMembers = false,
|
||||||
|
BracingStyle = "Block",
|
||||||
|
ElseOnClosing = false,
|
||||||
|
IndentString = " ",
|
||||||
|
VerbatimOrder = false
|
||||||
|
};
|
||||||
|
var provider = new CSharpCodeProvider();
|
||||||
|
|
||||||
|
foreach (var type in ns.Types.OfType<CodeTypeDeclaration>()) {
|
||||||
|
tempNs.Types.Add(type);
|
||||||
|
Log($"Writing out {(type.IsStruct ? "struct" : "class")} {type.Name}");
|
||||||
|
using var sw = new StreamWriter($"{OutPath}\\{type.Name}.cs");
|
||||||
|
provider.GenerateCodeFromNamespace(tempNs, sw, codeGeneratorOptions);
|
||||||
|
tempNs.Types.Remove(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user