void CopyCSharpCodeToClipboard(object sender, EventArgs args)
{
StringBuilder builder = new StringBuilder();
int bitCount = 0;
Dictionary<string, string> translatedShortNames = new Dictionary<string,string>();
Dictionary<string, string> translatedDescriptions = new Dictionary<string,string>();
#region Detect an unknown "_BOOL" type and report it.
foreach (ParameterDefinitionRow row in Children) {
if (row.DotNetType.EndsWith("_BOOL") || row.RealDotNetType.EndsWith("_BOOL")) {
MessageBox.Show("This has an unhandled '_BOOL' type, the code will be wrong.");
break;
}
}
#endregion
#region Read the translated names from the clipboard.
if (Clipboard.ContainsText()) {
string[] lines = Clipboard.GetText().TrimStart().Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None);
if(lines.Length > 0 && lines[0] == JapaneseTranslationMarker) {
for (int offset = 1; offset < lines.Length; offset += 4) {
string id = lines[offset];
translatedShortNames[id] = lines.TryGet(offset + 1, "");
translatedDescriptions[id] = lines.TryGet(offset + 2, "");
}
}
}
#endregion
#region Print information to paste into various locations.
builder.Append("/*\n");
builder.AppendFormat(
"For ParameterTable.cs under {1}.ReadRow:\n" +
" case TableRows.{0}.TableName: return new TableRows.{0}(table, index, loader, next);\n", Name, typeof(ParameterTableRow).Name);
builder.AppendFormat(
"For ParameterDefinition.cs under {0}.GetDotNetType():\n", typeof(ParameterDefinitionRow).Name);
HashSet<string> unknownTypes = new HashSet<string>();
string enumerations = "";
foreach (ParameterDefinitionRow row in Children)
if (ParameterDefinitionRow.GetDotNetType(row.Type) == null && unknownTypes.Add(row.Type)) {
builder.AppendFormat("\tcase \"{0}\": return typeof({0}).Name;\n", row.Type);
enumerations += string.Format(
"\n\t/// <summary></summary>\n" +
"\t/// <remarks>\"{0}\" in Dark Souls.</remarks>\n" +
"\tpublic enum {0} : {1} {{\n" +
"\t}}\n", row.Type, row.RealDotNetType.ToLower());
}
if(enumerations != null)
builder.AppendFormat("For Enumerations.cs:{0}", enumerations);
builder.Append("*/\n");
#endregion
builder.AppendFormat(
"using Glare.Assets;\nusing System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.IO;\nusing System.Linq;\nusing System.Reflection;\nusing System.Text;\n\n" +
"namespace Alexandria.Engines.DarkSouls {{\n" +
"\tpartial class TableRows {{\n");
if (LoadContext is ArchiveRecord) {
ArchiveRecord record = (ArchiveRecord)LoadContext;
builder.AppendFormat(
"\t\t/// <summary></summary>\n" +
"\t\t/// <remarks>\n" +
"\t\t/// Defined as \"{0}\" in Dark Souls in the file \"{1}\" (id {2:X2}h).\n" +
"\t\t/// </remarks>\n", Name, record.Name, record.Id);
}
builder.AppendFormat(
"\t\tpublic class {0} : {1} {{\n" +
"\t\t\tpublic const string TableName = \"{0}\";\n\n", Name, typeof(ParameterTableRow).Name);
#region Print field definitions, grouping them up to make them easier to deal with.
Dictionary<string, string> fieldDefinitions = new Dictionary<string, string>();
// Define the fields.
foreach (ParameterDefinitionRow row in Children) {
if (row.IsBitField)
continue;
string type = row.DotNetType;
string name = row.DotNetFieldName;
string current;
fieldDefinitions[type] = fieldDefinitions.TryGetValue(type, out current) ?
current + ", " + name :
name;
}
// Print the field definitions.
foreach (var item in fieldDefinitions)
builder.AppendFormat("\t\t\t{0} {1};\n", item.Key, item.Value);
builder.Append("\n");
#endregion
#region Print the PropertyInfo declarations.
builder.AppendFormat("\t\t\tpublic static readonly {0}\n", typeof(PropertyInfo).Name);
foreach (ParameterDefinitionRow row in Children)
builder.AppendFormat("\t\t\t\t{0}Property = GetProperty<{1}>(\"{0}\"){2}\n", row.DotNetName, Name, row == Children[Children.Count - 1] ? ";" : ",");
builder.Append("\n");
#endregion
#region Print the property definitions
bitCount = 0;
foreach (ParameterDefinitionRow row in Children) {
string getProperty = "return " + row.DotNetFieldName + ";";
string setProperty = string.Format("SetProperty(ref {0}, ref value, {1}Property);", row.DotNetFieldName, row.DotNetName);
if (row.IsBitField) {
getProperty = string.Format("return {3}GetBitProperty({0}, {1}, {2}Property){4};",
bitCount,
row.BitFieldBits,
row.DotNetName,
row.IsBoolean ? "" : "(" + row.DotNetType + ")",
row.IsBoolean ? " != 0" : "");
setProperty = string.Format("SetBitProperty({0}, {1}, {3}, {2}Property);", bitCount, row.BitFieldBits, row.DotNetName, row.IsBoolean ? "value ? 1 : 0" : "(int)value");
bitCount += row.BitFieldBits;
}
string translatedShortName = translatedShortNames.TryGetValue(row.DotNetName, "");
string translatedDescription = translatedDescriptions.TryGetValue(row.DotNetName, "");
builder.AppendFormat(
"\t\t\t/// <summary>{0}</summary>\n" +
"\t\t\t/// <remarks>\n" +
"\t\t\t/// Japanese short name: \"{2}\", Google translated: \"{0}\".\n" +
"\t\t\t/// Japanese description: \"{3}\", Google translated: \"{1}\".\n" +
"\t\t\t/// </remarks>\n",
translatedShortName, translatedDescription, // {0} and {1}
row.JapaneseShortName, row.JapaneseDescription); // {2} and {3}
builder.AppendFormat("\t\t\t[{0}(\"{1}\", index: {2}, @default: {3}, minimum: {4}, maximum: {5}, step: {6}, order: {7}, unknown2: {8})]\n",
typeof(ParameterTableRowAttribute).Name, row.Name, row.Index, row.ValueDefault, row.ValueMinimum, row.ValueMaximum, row.ValueStep, row.UnknownValue1, row.UnknownValue2);
builder.AppendFormat("\t\t\t[DisplayName(\"{0}\")]\n", translatedShortName.Replace("\"", "\\\""));
builder.AppendFormat("\t\t\t[Description(\"{0}\")]\n", translatedDescription.Replace("\"", "\\\""));
if(!row.IsArray)
builder.AppendFormat("\t\t\t[DefaultValue({0})]\n", row.CSharpValueDefault);
if (row.Type == "dummy8")
builder.AppendFormat("\t\t\t[Browsable(false)]\n");
builder.AppendFormat("\t\t\tpublic {0} {1} {{\n", row.DotNetType, row.DotNetName);
builder.AppendFormat("\t\t\t\tget {{ {0} }}\n", getProperty);
if (!row.IsEnum && !row.IsBoolean && !row.IsArray)
builder.AppendFormat(
"\t\t\t\tset {{\n" +
"\t\t\t\t\tif((double)value < {1} || (double)value > {2})\n" +
"\t\t\t\t\t\tthrow new ArgumentOutOfRangeException(\"value\", \"value of \" + value + \" is out of range {1} to {2} for \" + {0}Property.Name + \".\");\n" +
"\t\t\t\t\t{3}\n" +
"\t\t\t\t}}\n", row.DotNetName, row.ValueMinimum, row.ValueMaximum, setProperty);
else
builder.AppendFormat("\t\t\t\tset {{ {0} }}\n", setProperty);
builder.Append("\t\t\t}\n");
builder.Append("\n");
}
#endregion
#region Print the constructor
builder.AppendFormat(
"\t\t\tinternal {0}({1} table, int index, {2} loader, int next)\n" +
"\t\t\t\t: base(table, index, loader) {{\n" +
"\t\t\t\tBinaryReader reader = loader.Reader;\n\n", Name, typeof(ParameterTable).Name, typeof(AssetLoader).Name);
bool bitsMode = false, hadBits = false;
foreach (ParameterDefinitionRow row in Children) {
if (row.IsBitField) {
if (bitsMode == false) {
if (hadBits)
MessageBox.Show("Multiple bit fields counted; code will not be correct.");
hadBits = true;
bitsMode = true;
bitCount = 0;
for (int bitCounter = row.Index; bitCounter < Children.Count; bitCounter++) {
ParameterDefinitionRow bitRow = (ParameterDefinitionRow)Children[bitCounter];
if (!bitRow.IsBitField)
continue;
bitCount += bitRow.BitFieldBits;
}
builder.AppendFormat("\t\t\t\tBitFields = reader.ReadBytes({0});\n", (bitCount + 7) / 8);
}
} else {
bitsMode = false;
if (row.DataType == "dummy8")
builder.AppendFormat("\t\t\t\t{0} = reader.ReadBytes({1});\n", row.DotNetName, row.Size);
else
builder.AppendFormat("\t\t\t\t{0} = {1}reader.Read{2}();\n", row.DotNetName, row.IsEnum ? "(" + row.DotNetType + ")" : "", row.RealDotNetType);
}
}
builder.Append("\t\t\t}\n\n");
#endregion
#region Print the initialiser constructor.
builder.AppendFormat(
"\t\t\tinternal {0}({1} table, int index)\n" +
"\t\t\t\t: base(table, index) {{\n", Name, typeof(ParameterTable).Name);
if (bitCount > 0)
builder.AppendFormat("\t\t\t\tBitFields = new byte[{0}];\n", (bitCount + 7) / 8);
foreach (ParameterDefinitionRow row in Children) {
builder.AppendFormat("\t\t\t\t{0} = {1};\n", row.DotNetName, row.CSharpValueDefault);
}
builder.Append("\t\t\t}\n\n");
#endregion
#region Print the write method.
builder.Append("\t\t\tpublic override void Write(BinaryWriter writer) {\n");
foreach (ParameterDefinitionRow row in Children) {
if (row.IsBitField) {
if (bitsMode == false) {
bitsMode = true;
builder.Append("\t\t\t\twriter.Write(BitFields);\n");
}
} else {
if (row.DataType == "dummy8")
builder.AppendFormat("\t\t\t\twriter.Write({0});\n", row.DotNetName);
else
builder.AppendFormat("\t\t\t\twriter.Write({0}{1});\n", row.IsEnum ? "(" + row.RealDotNetType + ")" : "", row.DotNetName);
}
}
builder.Append("\t\t\t}\n");
#endregion
builder.Append("\t\t}\n");
builder.Append("\t}\n");
builder.Append("}\n");
Clipboard.Clear();
Clipboard.SetText(builder.ToString());
}