/// <summary> /// Generates a PQS Setup + the Scaled Space Maps needed /// </summary> /// <returns></returns> // ReSharper disable once InconsistentNaming private static void GeneratePQS(ref ConfigNode node, String name, String folder, Planet planet, Color planetColor, out Color average, out List <Color> biomes) { // Log Console.WriteLine("Preparing to load PQS data"); // Create the node ConfigNode pqs = new ConfigNode("PQS"); // TODO: Material Settings? // Create a node for the mods ConfigNode mods = new ConfigNode("Mods"); pqs.AddConfigNode(mods); // Load the PQSDatabase and select a setup ConfigNode pqsDatabase = Utility.Load("pqs"); List <PQSPreset> data = pqsDatabase.nodes.Select(n => Parser.CreateObjectFromConfigNode <PQSPreset>(n)) .ToList(); data = data.Where(d => ((planet.radius * 100) > d.MinRadius) && ((planet.radius * 100) < d.MaxRadius)) .ToList(); PQSPreset setup = data[Random.Next(0, data.Count)]; // Setup the interpreter Interpreter interpreter = new Interpreter() .SetVariable("planet", planet, typeof(Planet)) .SetVariable("pqsVersion", setup, typeof(PQSPreset)) .SetVariable("Random", Random, typeof(Random)) .SetVariable("Seed", Seed, typeof(Int32)) .SetVariable("Color", Utility.GenerateColor(), typeof(Color)) .Reference(typeof(Parser)) .Reference(typeof(Generator)) .Reference(typeof(Utility)) .Reference(typeof(Utils)); // Transfer the mod nodes and evaluate expressions foreach (ConfigNode modNode in setup.Mods.nodes) { mods.AddConfigNode(Utility.Eval(modNode, interpreter)); } // Create a new PQSObject PQS pqsVersion = new PQS(planet.radius * 100); List <PQSMod> patchedmods = new List <PQSMod>(); // Log Console.WriteLine($"Created PQS Object for {name}"); // Get all loaded types List <Type> types = AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes()).ToList(); // Load mods from Config foreach (ConfigNode mod in mods.nodes) { // get the mod type if (types.Count(t => t.Name == mod.name) == 0) { continue; } Type loaderType = types.FirstOrDefault(t => t.Name == mod.name); String testName = mod.name != "LandControl" ? "PQSMod_" + mod.name : "PQSLandControl"; Type modType = types.FirstOrDefault(t => t.Name == testName); if ((loaderType == null) || (modType == null)) { continue; } // Do any PQS mods already exist on this PQS matching this mod? IEnumerable <PQSMod> existingmods = pqsVersion.mods.Where(m => m.GetType() == modType); // Create the loader Object loader = Activator.CreateInstance(loaderType); // Reflection, because C# being silly... :/ MethodInfo createNew = loaderType.GetMethod("Create", new[] { typeof(PQS) }); MethodInfo create = loaderType.GetMethod("Create", new[] { modType }); IList <PQSMod> pqsmods = existingmods as IList <PQSMod> ?? existingmods.ToList(); if (pqsmods.Any()) { // Attempt to find a PQS mod we can edit that we have not edited before PQSMod existingMod = pqsmods.FirstOrDefault(m => !patchedmods.Contains(m) && (!mod.HasValue("name") || (mod.HasValue("index") ? (pqsmods.ToList().IndexOf(m) == Int32.Parse(mod.GetValue("index"))) && (m.name == mod.GetValue("name")) : m.name == mod.GetValue("name")))); if (existingMod != null) { create.Invoke(loader, new Object[] { existingMod }); Parser.LoadObjectFromConfigurationNode(loader, mod); patchedmods.Add(existingMod); } else { createNew.Invoke(loader, new Object[] { pqsVersion }); Parser.LoadObjectFromConfigurationNode(loader, mod); } } else { createNew.Invoke(loader, new Object[] { pqsVersion }); Parser.LoadObjectFromConfigurationNode(loader, mod); } // Log Console.WriteLine($"Created a new instance of {loaderType.Name} on {name}"); } // Size Int32 width = pqsVersion.radius >= 600000 ? 4096 : pqsVersion.radius <= 100000 ? 1024 : 2048; // Biome colors int numBiomes = Random.Next(2, 10); biomes = new List <Color>(numBiomes); for (int i = 0; i < numBiomes; i++) { biomes.Add(Utility.GenerateColor()); } // Export ScaledSpace Maps using (UnsafeBitmap diffuse = new UnsafeBitmap(width, width / 2)) { using (UnsafeBitmap height = new UnsafeBitmap(width, width / 2)) { using (UnsafeBitmap biomeMap = new UnsafeBitmap(width, width / 2)) { Console.WriteLine("Exporting Scaled Space maps from the PQS. This could take a while..."); // Iterate over the PQS pqsVersion.SetupSphere(); diffuse.LockBitmap(); height.LockBitmap(); biomeMap.LockBitmap(); for (Int32 i = 0; i < width; i++) { for (Int32 j = 0; j < (width / 2); j++) { // Create a VertexBuildData VertexBuildData builddata = new VertexBuildData { directionFromCenter = Quaternion.CreateFromAngleAxis((360d / width) * i, Vector3.Up) * Quaternion .CreateFromAngleAxis(90d - ((180d / (width / 2.0)) * j), Vector3.Right) * Vector3.Forward, vertHeight = pqsVersion.radius }; // Build the maps pqsVersion.OnVertexBuildHeight(builddata); pqsVersion.OnVertexBuild(builddata); builddata.vertColor.a = 1f; Single h = Mathf.Clamp01((Single)((builddata.vertHeight - pqsVersion.radius) * (1d / pqsVersion.radiusMax))); Single h1 = Mathf.Clamp01((Single)((builddata.vertHeight - pqsVersion.radius) * (1d / (pqsVersion.radiusMax != 0 ? pqsVersion.radiusMax : planet.radius)))); diffuse.SetPixel(i, j, builddata.vertColor); height.SetPixel(i, j, new Color(h, h, h)); biomeMap.SetPixel(i, j, biomes[(int)(h1 * (numBiomes - 1))]); } } diffuse.UnlockBitmap(); height.UnlockBitmap(); biomeMap.UnlockBitmap(); // Save the textures Directory.CreateDirectory(Directory.GetCurrentDirectory() + "/systems/" + folder + "/PluginData/"); using (UnsafeBitmap normals = Utility.BumpToNormalMap(height, 9)) { // TODO: Implement something to make strength dynamic diffuse.Bitmap .Save(Directory.GetCurrentDirectory() + "/systems/" + folder + "/PluginData/" + name + "_Texture.png", ImageFormat.Png); height.Bitmap .Save(Directory.GetCurrentDirectory() + "/systems/" + folder + "/PluginData/" + name + "_Height.png", ImageFormat.Png); // In case you need it :) normals.Bitmap .Save(Directory.GetCurrentDirectory() + "/systems/" + folder + "/PluginData/" + name + "_Normals.png", ImageFormat.Png); biomeMap.Bitmap .Save(Directory.GetCurrentDirectory() + "/systems/" + folder + "/PluginData/" + name + "_Biomes.png", ImageFormat.Png); } } } // Log Console.WriteLine($"Saved maps to {Directory.GetCurrentDirectory() + "/systems/" + folder + "/PluginData/"}"); // Finish node.AddConfigNode(pqs); // Colors average = Utility.GetAverageColor(diffuse.Bitmap); } }