protected void RecalculateEditorShip(ShipConstruct ship) { if (ship != null) { for (int i = 0; i < allRadSources.Count; i++) { UnregisterSource(allRadSources[i]); } for (int i = 0; i < allRadSinks.Count; i++) { UnregisterSink(allRadSinks[i]); } for (int i = 0; i < ship.Parts.Count; i++) { RadioactiveSource src = ship.Parts[i].gameObject.GetComponent <RadioactiveSource>(); RadioactiveSink snk = ship.Parts[i].gameObject.GetComponent <RadioactiveSink>(); if (src != null) { RegisterSource(src); } if (snk != null) { RegisterSink(snk); } } } }
// Computes LOS between a source and a sink // Returns the list of parts between the two objects protected List <AttenuationZone> GetLineOfSight(RadioactiveSource src, RadioactiveSink target) { RaycastHit[] hits1; RaycastHit[] hits2; float sep = Vector3.Distance(src.EmitterTransform.position, target.SinkTransform.position); // Only cast against Default and Terrain LayerMask mask; LayerMask maskA = 1 << LayerMask.NameToLayer("Default"); LayerMask maskB = 1 << LayerMask.NameToLayer("TerrainColliders"); LayerMask maskC = 1 << LayerMask.NameToLayer("Local Scenery"); mask = maskA | maskB | maskC; // raycast from the source to target and vice versa hits1 = Physics.RaycastAll(src.EmitterTransform.position, target.SinkTransform.position - src.EmitterTransform.position, sep, mask); hits2 = Physics.RaycastAll(target.SinkTransform.position, src.EmitterTransform.position - target.SinkTransform.position, sep, mask); List <RaycastHit> hitsBackward = hits2.ToList(); List <RaycastHit> hitsForward = hits1.ToList(); /// sort by distance, ascending if (hitsForward.Count > 0) { hitsForward = hitsForward.OrderBy(o => o.distance).ToList(); } if (hitsBackward.Count > 0) { hitsBackward = hitsBackward.OrderByDescending(o => o.distance).ToList(); } return(CreatePathway(hitsForward, hitsBackward, src, target, sep)); }
// Build new link for a new sink in the network protected void BuildNewRadiationLink(RadioactiveSink snk) { for (int i = 0; i < allRadSources.Count; i++) { RadiationLink l = new RadiationLink(allRadSources[i], snk); allLinks.Add(l); } }
public RadiationLink(RadioactiveSource src, RadioactiveSink snk) { fluxStart = RadioactivitySettings.defaultRaycastFluxStart; source = src; sink = snk; if (Radioactivity.Instance.RayOverlayShown) ShowOverlay(); //ComputeConnection(src, snk); }
public void HideOverlay(RadioactiveSink snk) { for (int i = 0; i < allLinks.Count; i++) { if (allLinks[i].sink == snk) { allLinks[i].HideOverlay(); } } }
public void ShowOverlay(RadioactiveSink snk) { for (int i = 0; i < allLinks.Count; i++) { if (allLinks[i].sink == snk && !allLinks[i].overlayShown) { allLinks[i].ShowOverlay(); } } }
// Add a radiation sink to the sink list public void RegisterSink(RadioactiveSink snk) { allRadSinks.Add(snk); BuildNewRadiationLink(snk); pointRadiationNetworkChanged = true; if (RadioactivitySettings.debugNetwork) { Utils.Log("Network: Adding radiation sink " + snk.SinkID + " on part " + snk.part.name + " to simulator"); } }
public RadiationLink(RadioactiveSource src, RadioactiveSink snk) { fluxStart = RadioactivitySettings.defaultRaycastFluxStart; source = src; sink = snk; if (Radioactivity.Instance.RayOverlayShown) { ShowOverlay(); } //ComputeConnection(src, snk); }
// Remove a radiation sink from the sink list public void UnregisterSink(RadioactiveSink snk) { if (allRadSinks.Count > 0) { pointRadiationNetworkChanged = true; RemoveRadiationLink(snk); allRadSinks.Remove(snk); if (RadioactivitySettings.debugNetwork && snk != null) { Utils.Log("Network: Removing radiation sink " + snk.SinkID + " on part " + snk.part.name + " from simulator"); } } }
protected void TryAddSink(RadioactiveSink snk) { bool exists = false; for (int i = 0; i < allRadSinks.Count; i++) { if (allRadSinks[i] == snk) { exists = true; } } if (!exists) { this.RegisterSink(snk); } }
// Compute the ray path between the source and sink public void ComputeGeometry(RadioactiveSource src, RadioactiveSink target) { if (RadioactivitySettings.debugNetwork) { Utils.Log("Network: Creating connection from " + src.part.name + " to " + target.part.name); } // Store the relative position of both endpoints relPos = Utils.getRelativePosition(src.EmitterTransform, target.SinkTransform.position);//src.EmitterTransform.position - target.SinkTransform.position; // Gets parts between source and sink attenuationPath = GetLineOfSight(src, target); // Attenuate the ray between these fluxStart = src.AttenuateShadowShields(target.SinkTransform.position - src.EmitterTransform.position); fluxEndScale = AttenuateFlux(attenuationPath, fluxStart); needsGeometricRecalculation = false; }
protected void AddEVARadioactivityTrackers(Part p) { if (p.GetComponent <RadioactiveSink>() != null) { Utils.Log("EVA: Module already exists"); } else { Utils.Log("EVA: Adding modules"); RadioactiveSink sink = p.gameObject.AddComponent <RadioactiveSink>(); RadiationShieldedCrewContainer tracker = p.gameObject.AddComponent <RadiationShieldedCrewContainer>(); sink.SinkID = "Kerbal"; sink.IconID = 3; tracker.AbsorberID = "Kerbal"; tracker.RadiationAttenuationFraction = 0.0f; evaModified = true; } }
// Removes a link to a given radiation sink protected void RemoveRadiationLink(RadioactiveSink snk) { List <RadiationLink> toRm = new List <RadiationLink>(); for (int i = 0; i < allLinks.Count; i++) { if (allLinks[i].sink == snk) { toRm.Add(allLinks[i]); } } if (toRm.Count > 0) { for (int i = 0; i < toRm.Count; i++) { toRm[i].HideOverlay(); toRm[i].CleanupSink(); allLinks.Remove(toRm[i]); } } }
protected void TryAddSink(RadioactiveSink snk) { bool exists = false; for (int i=0; i< allRadSinks.Count; i++) { if (allRadSinks[i] == snk) exists = true; } if (!exists) this.RegisterSink(snk); }
// Removes a link to a given radiation sink protected void RemoveRadiationLink(RadioactiveSink snk) { List <RadiationLink> toRm = new List<RadiationLink>(); for (int i = 0; i < allLinks.Count; i++) { if (allLinks[i].sink == snk) { toRm.Add(allLinks[i]); } } if (toRm.Count> 0) { for (int i = 0; i < toRm.Count; i++) { toRm[i].HideOverlay(); toRm[i].CleanupSink(); allLinks.Remove(toRm[i]); } } }
// Build new link for a new sink in the network protected void BuildNewRadiationLink(RadioactiveSink snk) { for (int i=0; i< allRadSources.Count; i++) { RadiationLink l = new RadiationLink(allRadSources[i], snk); allLinks.Add(l); } }
// Remove a radiation sink from the sink list public void UnregisterSink(RadioactiveSink snk) { if (allRadSinks.Count > 0) { pointRadiationNetworkChanged = true; RemoveRadiationLink(snk); allRadSinks.Remove(snk); if (RadioactivitySettings.debugNetwork && snk != null) Utils.Log("Network: Removing radiation sink " + snk.SinkID + " on part " + snk.part.name + " from simulator"); } }
// Add a radiation sink to the sink list public void RegisterSink(RadioactiveSink snk) { allRadSinks.Add(snk); BuildNewRadiationLink(snk); pointRadiationNetworkChanged = true; if (RadioactivitySettings.debugNetwork) Utils.Log("Network: Adding radiation sink "+ snk.SinkID +" on part " + snk.part.name + " to simulator"); }
// Compute the ray path between the source and sink public void ComputeGeometry(RadioactiveSource src, RadioactiveSink target) { if (RadioactivitySettings.debugNetwork) Utils.Log("Network: Creating connection from " + src.part.name + " to " + target.part.name); // Store the relative position of both endpoints relPos = Utils.getRelativePosition(src.EmitterTransform, target.SinkTransform.position);//src.EmitterTransform.position - target.SinkTransform.position; // Gets parts between source and sink attenuationPath = GetLineOfSight(src, target); // Attenuate the ray between these fluxStart = src.AttenuateShadowShields(target.SinkTransform.position- src.EmitterTransform.position); fluxEndScale = AttenuateFlux(attenuationPath, fluxStart); needsGeometricRecalculation = false; }
// Computes LOS between a source and a sink // Returns the list of parts between the two objects protected List<AttenuationZone> GetLineOfSight(RadioactiveSource src, RadioactiveSink target) { RaycastHit[] hits1; RaycastHit[] hits2; float sep = Vector3.Distance(src.EmitterTransform.position, target.SinkTransform.position); // Only cast against Default and Terrain LayerMask mask; LayerMask maskA = 1 << LayerMask.NameToLayer("Default"); LayerMask maskB = 1 << LayerMask.NameToLayer("TerrainColliders"); LayerMask maskC = 1 << LayerMask.NameToLayer("Local Scenery"); mask = maskA | maskB | maskC; // raycast from the source to target and vice versa hits1 = Physics.RaycastAll(src.EmitterTransform.position, target.SinkTransform.position - src.EmitterTransform.position, sep, mask); hits2 = Physics.RaycastAll(target.SinkTransform.position, src.EmitterTransform.position - target.SinkTransform.position, sep, mask); List<RaycastHit> hitsBackward = hits2.ToList(); List<RaycastHit> hitsForward = hits1.ToList(); /// sort by distance, ascending if (hitsForward.Count > 0) { hitsForward = hitsForward.OrderBy(o => o.distance).ToList(); } if (hitsBackward.Count > 0) { hitsBackward = hitsBackward.OrderByDescending(o => o.distance).ToList(); } return CreatePathway(hitsForward, hitsBackward, src, target, sep); }
// Go through raycast results (both ways) in order to create the attenuation path protected List<AttenuationZone> CreatePathway(List<RaycastHit> outgoing, List<RaycastHit> incoming, RadioactiveSource src, RadioactiveSink target, float totalPathLength) { List<AttenuationZone> attens = new List<AttenuationZone>(); if (RadioactivitySettings.debugRaycasting) Utils.Log("Raycaster: Looking along a distance of " +totalPathLength.ToString() + " with "+ outgoing.Count + " hits"); float curZoneStartDistance = RadioactivitySettings.defaultSourceFluxDistance; float curZoneEndDistance = 0.01f; Vector3 curZoneStartPoint = src.EmitterTransform.position + (target.SinkTransform.position - src.EmitterTransform.position).normalized*curZoneStartDistance; Vector3 curZoneEndPoint = target.SinkTransform.position; int hitNum = 0; // for each object we hit outgoing, see if we found it incoming for (int i=0; i < outgoing.Count; i++) { if (RadioactivitySettings.debugRaycasting) Utils.Log("Raycaster: Looking for incoming rayhits with " + outgoing[i].collider.name); RaycastHit found = incoming.Find(item => item.collider == outgoing[i].collider); // If there is a matching collider if (found.collider != null) { curZoneEndDistance = outgoing[i].distance; curZoneEndPoint = outgoing[i].point; if (curZoneEndDistance - curZoneStartDistance > 0f) { attens.Add(new AttenuationZone(curZoneStartDistance, curZoneEndDistance, curZoneStartPoint, curZoneEndPoint)); curZoneStartPoint = curZoneEndPoint; curZoneStartDistance = curZoneEndDistance; } int layer = found.collider.gameObject.layer; if (RadioactivitySettings.debugRaycasting) Utils.Log("Raycaster: Hit on layer " + LayerMask.LayerToName(layer)); if (layer == LayerMask.NameToLayer("Default")) { Part associatedPart = outgoing[i].collider.GetComponentInParent<Part>(); if (RadioactivitySettings.debugRaycasting) Utils.Log("Raycaster: Located 2-way hit! Path through is of L: " + (totalPathLength - outgoing[i].distance - found.distance).ToString() + " and part is " + associatedPart.ToString()); if (associatedPart != target.part) { curZoneStartPoint = outgoing[i].point; curZoneEndPoint = found.point; curZoneStartDistance = outgoing[i].distance; curZoneEndDistance = totalPathLength - found.distance; attens.Add(new AttenuationZone(curZoneStartDistance, curZoneEndDistance, associatedPart, curZoneStartPoint, curZoneEndPoint)); } } if (found.collider.gameObject.layer == LayerMask.NameToLayer("TerrainColliders")) { if (RadioactivitySettings.debugRaycasting) Utils.Log("Raycaster: Located 2-way hit! Path through is of L: " + (totalPathLength - outgoing[i].distance - found.distance).ToString() + " on terraincolliders layer"); curZoneStartPoint = outgoing[i].point; curZoneEndPoint = found.point; curZoneStartDistance = outgoing[i].distance; curZoneEndDistance = totalPathLength - found.distance; attens.Add(new AttenuationZone(outgoing[i].distance, totalPathLength - found.distance, AttenuationType.Terrain, outgoing[i].point, found.point)); } if (found.collider.gameObject.layer == LayerMask.NameToLayer("Local Scenery")) { if (RadioactivitySettings.debugRaycasting) Utils.Log("Raycaster: Located 2-way hit! Path through is of L: " + (totalPathLength - outgoing[i].distance - found.distance).ToString() + " on LocalScenery layer"); curZoneStartPoint = outgoing[i].point; curZoneEndPoint = found.point; curZoneStartDistance = outgoing[i].distance; curZoneEndDistance = totalPathLength - found.distance; attens.Add(new AttenuationZone(outgoing[i].distance, totalPathLength - found.distance, AttenuationType.Terrain, outgoing[i].point, found.point)); } hitNum++; } else { if (RadioactivitySettings.debugRaycasting) Utils.Log("Raycaster: No incoming hits with " + outgoing[i].collider.name + ", discarding..."); } } curZoneEndPoint = target.SinkTransform.position; if (hitNum > 0) curZoneStartDistance = curZoneEndDistance; curZoneEndDistance = totalPathLength; attens.Add(new AttenuationZone(curZoneStartDistance, curZoneEndDistance, curZoneStartPoint, curZoneEndPoint)); // TODO: Need to add another AttenuationZone if we start inside a part. probably take the last hit in the incoming array to do this (not the best assumption) // TODO: Need to add another AttenuationZone to account for the target part. probably take the last hit in the outgoing array to do this (good assumption) // Add the empty space as a single zone //if (totalPathLength > 0f) // attens.Add(new AttenuationZone(totalPathLength, src.EmitterTransform.position, target.SinkTransform.position)); return attens; }
// Go through raycast results (both ways) in order to create the attenuation path protected List <AttenuationZone> CreatePathway(List <RaycastHit> outgoing, List <RaycastHit> incoming, RadioactiveSource src, RadioactiveSink target, float totalPathLength) { List <AttenuationZone> attens = new List <AttenuationZone>(); if (RadioactivitySettings.debugRaycasting) { Utils.Log("Raycaster: Looking along a distance of " + totalPathLength.ToString() + " with " + outgoing.Count + " hits"); } float curZoneStartDistance = RadioactivitySettings.defaultSourceFluxDistance; float curZoneEndDistance = 0.01f; Vector3 curZoneStartPoint = src.EmitterTransform.position + (target.SinkTransform.position - src.EmitterTransform.position).normalized * curZoneStartDistance; Vector3 curZoneEndPoint = target.SinkTransform.position; int hitNum = 0; // for each object we hit outgoing, see if we found it incoming for (int i = 0; i < outgoing.Count; i++) { if (RadioactivitySettings.debugRaycasting) { Utils.Log("Raycaster: Looking for incoming rayhits with " + outgoing[i].collider.name); } RaycastHit found = incoming.Find(item => item.collider == outgoing[i].collider); // If there is a matching collider if (found.collider != null) { curZoneEndDistance = outgoing[i].distance; curZoneEndPoint = outgoing[i].point; if (curZoneEndDistance - curZoneStartDistance > 0f) { attens.Add(new AttenuationZone(curZoneStartDistance, curZoneEndDistance, curZoneStartPoint, curZoneEndPoint)); curZoneStartPoint = curZoneEndPoint; curZoneStartDistance = curZoneEndDistance; } int layer = found.collider.gameObject.layer; if (RadioactivitySettings.debugRaycasting) { Utils.Log("Raycaster: Hit on layer " + LayerMask.LayerToName(layer)); } if (layer == LayerMask.NameToLayer("Default")) { Part associatedPart = outgoing[i].collider.GetComponentInParent <Part>(); if (RadioactivitySettings.debugRaycasting) { Utils.Log("Raycaster: Located 2-way hit! Path through is of L: " + (totalPathLength - outgoing[i].distance - found.distance).ToString() + " and part is " + associatedPart.ToString()); } if (associatedPart != target.part) { curZoneStartPoint = outgoing[i].point; curZoneEndPoint = found.point; curZoneStartDistance = outgoing[i].distance; curZoneEndDistance = totalPathLength - found.distance; attens.Add(new AttenuationZone(curZoneStartDistance, curZoneEndDistance, associatedPart, curZoneStartPoint, curZoneEndPoint)); } } if (found.collider.gameObject.layer == LayerMask.NameToLayer("TerrainColliders")) { if (RadioactivitySettings.debugRaycasting) { Utils.Log("Raycaster: Located 2-way hit! Path through is of L: " + (totalPathLength - outgoing[i].distance - found.distance).ToString() + " on terraincolliders layer"); } curZoneStartPoint = outgoing[i].point; curZoneEndPoint = found.point; curZoneStartDistance = outgoing[i].distance; curZoneEndDistance = totalPathLength - found.distance; attens.Add(new AttenuationZone(outgoing[i].distance, totalPathLength - found.distance, AttenuationType.Terrain, outgoing[i].point, found.point)); } if (found.collider.gameObject.layer == LayerMask.NameToLayer("Local Scenery")) { if (RadioactivitySettings.debugRaycasting) { Utils.Log("Raycaster: Located 2-way hit! Path through is of L: " + (totalPathLength - outgoing[i].distance - found.distance).ToString() + " on LocalScenery layer"); } curZoneStartPoint = outgoing[i].point; curZoneEndPoint = found.point; curZoneStartDistance = outgoing[i].distance; curZoneEndDistance = totalPathLength - found.distance; attens.Add(new AttenuationZone(outgoing[i].distance, totalPathLength - found.distance, AttenuationType.Terrain, outgoing[i].point, found.point)); } hitNum++; } else { if (RadioactivitySettings.debugRaycasting) { Utils.Log("Raycaster: No incoming hits with " + outgoing[i].collider.name + ", discarding..."); } } } curZoneEndPoint = target.SinkTransform.position; if (hitNum > 0) { curZoneStartDistance = curZoneEndDistance; } curZoneEndDistance = totalPathLength; attens.Add(new AttenuationZone(curZoneStartDistance, curZoneEndDistance, curZoneStartPoint, curZoneEndPoint)); // TODO: Need to add another AttenuationZone if we start inside a part. probably take the last hit in the incoming array to do this (not the best assumption) // TODO: Need to add another AttenuationZone to account for the target part. probably take the last hit in the outgoing array to do this (good assumption) // Add the empty space as a single zone //if (totalPathLength > 0f) // attens.Add(new AttenuationZone(totalPathLength, src.EmitterTransform.position, target.SinkTransform.position)); return(attens); }