// example based on the MSDN Properties Sample (abstractshape.cs, shapes.cs, shapetest.cs) public static void GenShapeTest(AssemblyGen ag) { var st = ag.StaticFactory; var exp = ag.ExpressionFactory; ITypeMapper m = ag.TypeMapper; // abstractshape.cs TypeGen Shape = ag.Public.Abstract.Class("Shape"); { FieldGen myId = Shape.Private.Field(typeof(string), "myId"); PropertyGen Id = Shape.Public.SimpleProperty(myId, "Id"); CodeGen g = Shape.Public.Constructor().Parameter(typeof(string), "s"); { g.Assign(Id, g.Arg("s")); // calling the set accessor of the Id property } // Area is a read-only property - only a get accessor is needed: PropertyGen Area = Shape.Public.Abstract.Property(typeof(double), "Area"); Area.Getter(); g = Shape.Public.Override.Method(typeof(string), "ToString"); { g.Return(Id + " Area = " + st.Invoke(typeof(string), "Format", "{0:F2}", Area)); } } // shapes.cs TypeGen Square = ag.Public.Class("Square", Shape); { FieldGen mySide = Square.Private.Field(typeof(int), "mySide"); CodeGen g = Square.Public.Constructor().Parameter(typeof(int), "side").Parameter(typeof(string), "id"); { g.InvokeBase(g.Arg("id")); g.Assign(mySide, g.Arg("side")); } PropertyGen Area = Square.Public.Override.Property(typeof(double), "Area"); g = Area.Getter(); { // Given the side, return the area of a square: g.Return(mySide * mySide); } } TypeGen Circle = ag.Public.Class("Circle", Shape); { FieldGen myRadius = Circle.Private.Field(typeof(int), "myRadius"); CodeGen g = Circle.Public.Constructor().Parameter(typeof(int), "radius").Parameter(typeof(string), "id"); { g.InvokeBase(g.Arg("id")); g.Assign(myRadius, g.Arg("radius")); } PropertyGen Area = Circle.Public.Override.Property(typeof(double), "Area"); g = Area.Getter(); { // Given the radius, return the area of a circle: g.Return(myRadius * myRadius * Math.PI); } } TypeGen Rectangle = ag.Public.Class("Rectangle", Shape); { FieldGen myWidth = Rectangle.Private.Field(typeof(int), "myWidth"); FieldGen myHeight = Rectangle.Private.Field(typeof(int), "myHeight"); CodeGen g = Rectangle.Public.Constructor() .Parameter(typeof(int), "width") .Parameter(typeof(int), "height") .Parameter(typeof(string), "id") ; { g.InvokeBase(g.Arg("id")); g.Assign(myWidth, g.Arg("width")); g.Assign(myHeight, g.Arg("height")); } PropertyGen Area = Rectangle.Public.Override.Property(typeof(double), "Area"); g = Area.Getter(); { // Given the width and height, return the area of a rectangle: g.Return(myWidth * myHeight); } } // shapetest.cs TypeGen TestClass = ag.Public.Class("TestClass"); { CodeGen g = TestClass.Public.Static.Method(typeof(void), "Main"); { var shapes = g.Local(exp.NewInitializedArray(Shape, exp.New(Square, 5, "Square #1"), exp.New(Circle, 3, "Circle #1"), exp.New(Rectangle, 4, 5, "Rectangle #1"))); g.WriteLine("Shapes Collection"); Operand s = g.ForEach(Shape, shapes); { g.WriteLine(s); } g.End(); } } }
/// <summary> /// Iterate over all loaded mods and emit new types /// </summary> protected void Awake() { // Generate overloaded PQSMod types AssemblyGen assembly = new AssemblyGen(Guid.NewGuid().ToString(), new CompilerOptions { OutputPath = Path.GetTempFileName() }); List <Type> modTypes = GetModTypes(); foreach (Type modType in modTypes) { if (typeof(PQSMod).IsAssignableFrom(modType)) { // Get the ModLoader type we want to extend Type loaderType = modTypes.FirstOrDefault(t => t.BaseType != null && t.BaseType.FullName != null && t.BaseType.FullName.StartsWith("Kopernicus.Configuration.ModLoader.ModLoader") && t.BaseType.GetGenericArguments()[0] == modType); if (loaderType == null) { continue; } // Generate the Mod Type TypeGen modGen = assembly.Public.Class($"{modType.Name}Regional", modType); { FieldGen multiplierMap = modGen.Public.Field(typeof(MapSO), "multiplierMap"); FieldGen splitChannels = modGen.Public.Field(typeof(Boolean), "splitChannels"); FieldGen multiplier = modGen.Private.Field(typeof(Color), "multiplier"); FieldGen preBuildColor = modGen.Private.Field(typeof(Color), "preBuildColor"); FieldGen preBuildHeight = modGen.Private.Field(typeof(Double), "preBuildHeight"); // OnVertexBuildHeight CodeGen onVertexBuild = modGen.Public.Override.Method(typeof(void), "OnVertexBuild") .Parameter(typeof(PQS.VertexBuildData), "data"); { ContextualOperand data = onVertexBuild.Arg("data"); onVertexBuild.Assign(multiplier, onVertexBuild.Local(multiplierMap.Invoke( "GetPixelColor", new TypeMapper(), data.Field("u"), data.Field("v")))); onVertexBuild.If(!splitChannels); { onVertexBuild.Assign(multiplier.Field("a", new TypeMapper()), multiplier.Field("r", new TypeMapper())); } onVertexBuild.End(); onVertexBuild.Assign(preBuildColor, data.Field("vertColor")); onVertexBuild.Assign(preBuildHeight, data.Field("vertHeight")); onVertexBuild.Invoke(onVertexBuild.Base(), "OnVertexBuild", data); onVertexBuild.Assign(data.Field("vertColor"), assembly.StaticFactory.Invoke(typeof(Color), "Lerp", preBuildColor, data.Field("vertColor"), multiplier.Field("a", new TypeMapper()))); onVertexBuild.Assign(data.Field("vertHeight"), assembly.StaticFactory.Invoke(typeof(UtilMath), "Lerp", preBuildHeight, data.Field("vertHeight"), multiplier.Field("r", new TypeMapper()))); } // OnVertexBuildHeight CodeGen onVertexBuildHeight = modGen.Public.Override.Method(typeof(void), "OnVertexBuildHeight") .Parameter(typeof(PQS.VertexBuildData), "data"); { ContextualOperand data = onVertexBuildHeight.Arg("data"); onVertexBuildHeight.Assign(multiplier, onVertexBuildHeight.Local(multiplierMap.Invoke( "GetPixelColor", new TypeMapper(), data.Field("u"), data.Field("v")))); onVertexBuildHeight.If(!splitChannels); { onVertexBuildHeight.Assign(multiplier.Field("a", new TypeMapper()), multiplier.Field("r", new TypeMapper())); } onVertexBuildHeight.End(); onVertexBuildHeight.Assign(preBuildColor, data.Field("vertColor")); onVertexBuildHeight.Assign(preBuildHeight, data.Field("vertHeight")); onVertexBuildHeight.Invoke(onVertexBuildHeight.Base(), "OnVertexBuildHeight", data); onVertexBuildHeight.Assign(data.Field("vertColor"), assembly.StaticFactory.Invoke(typeof(Color), "Lerp", preBuildColor, data.Field("vertColor"), multiplier.Field("a", new TypeMapper()))); onVertexBuildHeight.Assign(data.Field("vertHeight"), assembly.StaticFactory.Invoke(typeof(UtilMath), "Lerp", preBuildHeight, data.Field("vertHeight"), multiplier.Field("r", new TypeMapper()))); } } // Generate the Loader Type modGen.Complete(); Type modLoader = typeof(ModLoader <>).MakeGenericType(modGen.GetCompletedType()); TypeGen loaderGen = assembly.Public.Class($"{modType.Name.Replace("PQSMod_", "").Replace("PQS", "")}Regional", modLoader).Attribute(typeof(RequireConfigType), Kopernicus.ConfigParser.Enumerations.ConfigType.Node); { PropertyGen multiplierMap = loaderGen.Public.Property(typeof(MapSOParserRGB <MapSO>), "multiplierMap") .Attribute(typeof(ParserTarget), "multiplierMap"); { CodeGen getter = multiplierMap.Getter(); { getter.Return(getter.Base().Property("Mod").Field("multiplierMap")); } CodeGen setter = multiplierMap.Setter(); { setter.Assign(setter.Base().Property("Mod").Field("multiplierMap"), setter.PropertyValue()); } } PropertyGen splitChannels = loaderGen.Public.Property(typeof(NumericParser <Boolean>), "splitChannels") .Attribute(typeof(ParserTarget), "splitChannels"); { CodeGen getter = splitChannels.Getter(); { getter.Return(getter.Base().Property("Mod").Field("splitChannels")); } CodeGen setter = splitChannels.Setter(); { setter.Assign(setter.Base().Property("Mod").Field("splitChannels"), setter.PropertyValue()); } } FieldGen loader = loaderGen.Public.Field(loaderType, "loader") .BeginAttribute(typeof(ParserTarget), "Mod").SetField("AllowMerge", true).End(); CodeGen create_PQS = loaderGen.Public.Override.Method(typeof(void), "Create") .Parameter(typeof(PQS), "pqsVersion"); { ContextualOperand pqsVersion = create_PQS.Arg("pqsVersion"); create_PQS.Invoke(create_PQS.Base(), "Create", pqsVersion); create_PQS.Assign(loader, assembly.ExpressionFactory.New(loaderType)); create_PQS.Invoke(loader, "Create", create_PQS.Base().Property("Mod"), pqsVersion); } CodeGen create_Mod_PQS = loaderGen.Public.Override.Method(typeof(void), "Create") .Parameter(modGen, "_mod") .Parameter(typeof(PQS), "pqsVersion"); { ContextualOperand _mod = create_Mod_PQS.Arg("_mod"); ContextualOperand pqsVersion = create_Mod_PQS.Arg("pqsVersion"); create_Mod_PQS.Invoke(create_Mod_PQS.Base(), "Create", _mod, pqsVersion); create_Mod_PQS.Assign(loader, assembly.ExpressionFactory.New(loaderType)); create_Mod_PQS.Invoke(loader, "Create", create_Mod_PQS.Base().Property("Mod"), pqsVersion); } } } } assembly.Save(); // Hacking into my own mod. Oh well. modTypes.AddRange(assembly.GetAssembly().GetTypes()); typeof(Parser).GetField("_modTypes", BindingFlags.NonPublic | BindingFlags.Static) ?.SetValue(null, modTypes); }