// Update the menu body private void Start() { if (!Templates.KopernicusMainMenu) { return; } // Select a random body? if (Templates.RandomMainMenuBodies.Any()) { Templates.MenuBody = Templates.RandomMainMenuBodies[new Random().Next(0, Templates.RandomMainMenuBodies.Count)]; } // Grab the main body CelestialBody planetCb = UBI.GetBody(Templates.MenuBody); if (planetCb == null) { planetCb = PSystemManager.Instance.localBodies.Find(b => b.isHomeWorld); } if (planetCb == null) { Debug.LogError("[Kopernicus] Could not find home world!"); return; } // Load Textures OnDemandStorage.EnableBody(Templates.MenuBody); // Get the MainMenu-Logic MainMenu main = FindObjectOfType <MainMenu>(); if (main == null) { Debug.LogError("[Kopernicus] No main menu object!"); return; } MainMenuEnvLogic logic = main.envLogic; // Set it to Space, because the Mun-Area won't work with sth else than Mun if (logic.areas.Length < 2) { Debug.LogError("[Kopernicus] Not enough bodies"); return; } // Get our active Space GameObject space = logic.areas[1]; // Deactivate Kerbins Transform Transform kerbin = space.transform.Find("Kerbin"); if (kerbin == null) { Debug.LogError("[Kopernicus] No Kerbin transform!"); return; } kerbin.gameObject.SetActive(false); // Deactivate Muns Transform Transform munPivot = space.transform.Find("MunPivot"); if (munPivot == null) { Debug.LogError("[Kopernicus] No MunPivot transform!"); return; } munPivot.gameObject.SetActive(false); // Activate the textures ScaledSpaceOnDemand od = planetCb.scaledBody.GetComponentInChildren <ScaledSpaceOnDemand>(); if (od != null) { od.Start(); od.LoadTextures(); } // Clone the scaledVersion and attach it to the Scene GameObject menuPlanet = Utility.Instantiate(Utility .FindBody(PSystemManager.Instance.systemPrefab.rootBody, planetCb.transform.name).scaledVersion, space.transform, true); menuPlanet.name = planetCb.transform.name; // Destroy stuff DestroyImmediate(menuPlanet.GetComponent <ScaledSpaceFader>()); DestroyImmediate(menuPlanet.GetComponent <SphereCollider>()); DestroyImmediate(menuPlanet.GetComponentInChildren <AtmosphereFromGround>()); DestroyImmediate(menuPlanet.GetComponent <MaterialSetDirection>()); // That sounds funny Rotato planetRotato = menuPlanet.AddComponent <Rotato>(); Rotato planetRefRotato = kerbin.GetComponent <Rotato>(); planetRotato.speed = planetRefRotato.speed * ((Single)planetCb.rotationPeriod / KERBIN_ROTATION_PERIOD); menuPlanet.transform.Rotate(0f, (Single)planetCb.initialRotation, 0f); // Scale the body menuPlanet.transform.localScale = kerbin.localScale; menuPlanet.transform.localPosition = kerbin.localPosition; menuPlanet.transform.position = kerbin.position; // And set it to layer 0 menuPlanet.layer = 0; Events.OnRuntimeUtilityUpdateMenu.Fire(); }
public static Mesh ComputeScaledSpaceMesh(CelestialBody body, PQS pqs) { // We need to get the body for Jool (to steal it's mesh) const Double R_SCALED_JOOL = 1000.0f; Double rMetersToScaledUnits = (Single)(R_SCALED_JOOL / body.Radius); // Generate a duplicate of the Jool mesh Mesh mesh = DuplicateMesh(Templates.ReferenceGeosphere); Logger.Active.Log(body); Logger.Active.Log(pqs); Logger.Active.Log(body.pqsController); // If this body has a PQS, we can create a more detailed object, otherwise just return the generic mesh if (pqs == null) { return(mesh); } // first we enable all maps OnDemandStorage.EnableBody(body.bodyName); // In order to generate the scaled space we have to enable the mods. Since this is // a prefab they don't get disabled as kill game performance. To resolve this we // clone the PQS, use it, and then delete it when done. At runtime we can simply use // the PQS that is active GameObject pqsVersionGameObject = Injector.IsInPrefab ? Instantiate(pqs.gameObject) : pqs.gameObject; PQS pqsVersion = pqsVersionGameObject.GetComponent <PQS>(); // Deactivate blacklisted Mods PQSMod[] mods = pqsVersion.GetComponentsInChildren <PQSMod>(true).OrderBy(m => m.order).ToArray(); for (Int32 i = 0; i < mods.Length; i++) { // Disable mods that don't belong to us if (mods[i].transform.parent != pqsVersion.transform) { mods[i].modEnabled = false; continue; } switch (mods[i]) { // Disable the OnDemand notifier case PQSMod_OnDemandHandler _: mods[i].modEnabled = false; continue; case PQSMod_FlattenArea _: typeof(PQSMod_FlattenArea).GetFields(BindingFlags.NonPublic | BindingFlags.Instance) .First(f => f.FieldType == typeof(Boolean)).SetValue(mods[i], true); break; } } pqsVersion.StartUpSphere(); pqsVersion.isBuildingMaps = true; // If we were able to find PQS mods if (mods.Length > 0) { // Generate the PQS modifications Vector3[] vertices = mesh.vertices; for (Int32 i = 0; i < mesh.vertexCount; i++) { // Get the UV coordinate of this vertex Vector2 uv = mesh.uv[i]; // Since this is a geosphere, normalizing the vertex gives the direction from center center Vector3 direction = vertices[i]; direction.Normalize(); // Build the vertex data object for the PQS mods PQS.VertexBuildData vertex = new PQS.VertexBuildData { directionFromCenter = direction, vertHeight = body.Radius, u = uv.x, v = uv.y }; // Build from the PQS for (Int32 m = 0; m < mods.Length; m++) { // Don't build disabled mods if (!mods[m].modEnabled) { continue; } // Don't build mods that don't belong to us if (mods[m].transform.parent != pqsVersion.transform) { continue; } mods[m].OnVertexBuildHeight(vertex); } // Check for sea level if (pqsVersion.mapOcean) { vertex.vertHeight = Math.Max(vertex.vertHeight, body.Radius); } // Adjust the displacement vertices[i] = direction * (Single)(vertex.vertHeight * rMetersToScaledUnits); } mesh.vertices = vertices; mesh.RecalculateNormals(); mesh.RecalculateBounds(); RecalculateTangents(mesh); } // Cleanup pqsVersion.isBuildingMaps = false; pqsVersion.DeactivateSphere(); // If we are working with a copied PQS, clean it up if (Injector.IsInPrefab) { UnityEngine.Object.Destroy(pqsVersionGameObject); } OnDemandStorage.DisableBody(body.bodyName); // Return the generated scaled space mesh return(mesh); }
// Generate the scaled space mesh using PQS (all results use scale of 1) public static Mesh ComputeScaledSpaceMesh(CelestialBody body, PQS pqs) { // We need to get the body for Jool (to steal it's mesh) const Double rScaledJool = 1000.0f; Double rMetersToScaledUnits = (Single)(rScaledJool / body.Radius); // Generate a duplicate of the Jool mesh Mesh mesh = DuplicateMesh(Templates.ReferenceGeosphere); Logger.Active.Log(body); Logger.Active.Log(pqs); Logger.Active.Log(body.pqsController); // If this body has a PQS, we can create a more detailed object if (pqs != null) { // first we enable all maps OnDemandStorage.EnableBody(body.bodyName); // The game object the PQS is attached to GameObject pqsVersionGameObject = null; if (Injector.IsInPrefab) { // In order to generate the scaled space we have to enable the mods. Since this is // a prefab they don't get disabled as kill game performance. To resolve this we // clone the PQS, use it, and then delete it when done pqsVersionGameObject = UnityEngine.Object.Instantiate(pqs.gameObject); } else { // At runtime we simply use the PQS that is active pqsVersionGameObject = pqs.gameObject; } PQS pqsVersion = pqsVersionGameObject.GetComponent <PQS>(); // Load the PQS of the ocean PQS pqsOcean = pqs.ChildSpheres?.FirstOrDefault(); // Deactivate blacklisted Mods Type[] blacklist = { typeof(PQSMod_OnDemandHandler) }; foreach (PQSMod mod in pqsVersion.GetComponentsInChildren <PQSMod>(true) .Where(m => m.enabled && blacklist.Contains(m.GetType()))) { mod.modEnabled = false; } // Find the PQS mods and enable the PQS-sphere PQSMod[] mods = pqsVersion.GetComponentsInChildren <PQSMod>(true) .Where(m => m.modEnabled && m.transform.parent == pqsVersion.transform).OrderBy(m => m.order).ToArray(); foreach (PQSMod flatten in mods.Where(m => m is PQSMod_FlattenArea)) { flatten.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance) .First(f => f.FieldType == typeof(Boolean)).SetValue(flatten, true); } Logger.Active.Log(mods.Length); // Do the same for the ocean PQSMod[] oceanMods = new PQSMod[0]; if (pqsOcean != null) { oceanMods = pqsOcean.GetComponentsInChildren <PQSMod>(true) .Where(m => m.modEnabled && m.transform.parent == pqsOcean.transform).OrderBy(m => m.order).ToArray(); foreach (PQSMod flatten in oceanMods.Where(m => m is PQSMod_FlattenArea)) { flatten.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance) .First(f => f.FieldType == typeof(Boolean)).SetValue(flatten, true); } pqsOcean.StartUpSphere(); pqsOcean.isBuildingMaps = true; } pqsVersion.StartUpSphere(); pqsVersion.isBuildingMaps = true; // If we were able to find PQS mods if (mods.Any()) { // Generate the PQS modifications Vector3[] vertices = mesh.vertices; for (Int32 i = 0; i < mesh.vertexCount; i++) { // Get the UV coordinate of this vertex Vector2 uv = mesh.uv[i]; // Since this is a geosphere, normalizing the vertex gives the direction from center center Vector3 direction = vertices[i]; direction.Normalize(); // Build the vertex data object for the PQS mods PQS.VertexBuildData vertex = new PQS.VertexBuildData(); vertex.directionFromCenter = direction; vertex.vertHeight = body.Radius; vertex.u = uv.x; vertex.v = uv.y; // Build from the PQS foreach (PQSMod mod in mods) { mod.OnVertexBuildHeight(vertex); } // Check for sea level if (pqsOcean != null) { // Build the vertex data object for the ocean PQS.VertexBuildData vertexOcean = new PQS.VertexBuildData(); vertexOcean.directionFromCenter = direction; vertexOcean.vertHeight = body.Radius; vertexOcean.u = uv.x; vertexOcean.v = uv.y; // Build from the PQS foreach (PQSMod mod in oceanMods) { mod.OnVertexBuildHeight(vertexOcean); } vertex.vertHeight = Math.Max(vertex.vertHeight, vertexOcean.vertHeight); } // Adjust the displacement vertices[i] = direction * (Single)(vertex.vertHeight * rMetersToScaledUnits); } mesh.vertices = vertices; mesh.RecalculateNormals(); mesh.RecalculateBounds(); } // Cleanup if (pqsOcean != null) { pqsOcean.isBuildingMaps = false; pqsOcean.DeactivateSphere(); } pqsVersion.isBuildingMaps = false; pqsVersion.DeactivateSphere(); // If we are working with a copied PQS, clean it up if (Injector.IsInPrefab) { UnityEngine.Object.Destroy(pqsVersionGameObject); } OnDemandStorage.DisableBody(body.bodyName); } // Return the generated scaled space mesh return(mesh); }