Ryle Radio 1.0.0
An open-source "radio" system for Unity, allowing tracks, tuning, broadcasters, and more!
Loading...
Searching...
No Matches
RadioInsulator.cs
1using NaughtyAttributes;
4using UnityEngine;
5
7{
8
9 /// <summary>
10 /// An "insulator" for a \ref RadioTrackWrapper - if a RadioOutput is inside the bounds of this object, the affected tracks on it will become quieter.
11 ///
12 /// There aren't really any real-world analogues for the strength of an insulator like this- think of it like putting a radio in a Faraday cage or something I suppose
13 ///
14 /// This also has custom editor stuff in \ref RadioInsulatorEditor
15 /// </summary>
16 [AddComponentMenu("Ryle Radio/Radio Insulator")]
18 {
19 /// <summary>
20 /// The size of the inner box of the insulator- inside of this box, insulation is the highest
21 /// </summary>
22 [Space(8)]
23 public Vector3 innerBoxSize = Vector3.one * 0.9f;
24
25 /// <summary>
26 /// The size of the outer box of the insulator- outside of this box, insulation is 0- between this and the inner box, insulation is between [0 - 1]
27 /// </summary>
28 public Vector3 outerBoxSize = Vector3.one;
29
30 /// <summary>
31 /// The max and min insulation in the outer and inner boxes.
32 ///
33 /// If an output is on the edge of the outer box, insulation will be the x-value here.
34 /// If an output is inside the inner box, insulation will be the y-value.
35 /// If an output is between the inner and outer boxes, it will be somewhere between the x and y values according to the \ref insulationCurve
36 ///
37 /// If the x-value is above 0, you might want to toggle \ref applyToAllOutputsOutside so this becomes global
38 /// </summary>
39 [Space(8)]
40 [SerializeField, MinMaxSlider(0, 1)]
41 private Vector2 insulation = new(0, 0.5f);
42
43 /// <summary>
44 /// A curve that defines insulation between the inner and outer boxes- the x-value is how far between the inner and outer boxes the output is
45 /// </summary>
46 [SerializeField, CurveRange(0, 0, 1, 1)]
47 private AnimationCurve insulationCurve = AnimationCurve.Linear(0, 0, 1, 1);
48
49 /// <summary>
50 /// Effectively makes this insulator global- when this is true, any output outside of the outer box's range will be affected by the x-value on \ref insulation
51 ///
52 /// This only shows when the x-value of insulation is above 0
53 /// </summary>
54 [SerializeField, AllowNesting, ShowIf("ShowApplyToAllOutputs")]
55 private bool applyToAllOutputsOutside = false;
56
57 /// <summary>
58 /// The position of the insulator in the previous frame. We cannot access transform.position in the audio thread, so we cache it to this
59 /// </summary>
60 private Vector3 cachedPos;
61
62 // the inner and outer boxes with transform.localScale applied
63 /// The \ref innerBoxSize but adjusted with `transform.localScale` in \ref Update()
64 public Vector3 InnerBoxSizeAdjusted { get; private set; }
65 /// The \ref outerBoxSize but adjusted with `transform.localScale` in \ref Update()
66 public Vector3 OuterBoxSizeAdjusted { get; private set; }
67
68 /// <summary>
69 /// Shows \ref applyToAllOutputsOutside when the x-value of \ref insulation is greater than 0
70 /// </summary>
71 private bool ShowApplyToAllOutputs => insulation.x > 0;
72
73
74 /// <summary>
75 /// Updates cached position and adjusted box sizes
76 /// </summary>
77 private void Update()
78 {
79 // applies the local scale to the inner and outer boxes
80 InnerBoxSizeAdjusted = transform.localToWorldMatrix * innerBoxSize;
81 OuterBoxSizeAdjusted = transform.localToWorldMatrix * outerBoxSize;
82
83 // caches position for this frame
84 cachedPos = transform.position;
85 }
86
87 /// <summary>
88 /// Links this insulator to a track
89 /// </summary>
90 /// <param name="_track">The track to link to</param>
91 protected override void AssignToTrack(RadioTrackWrapper _track)
92 {
93 _track.insulators.Add(this);
94 _track.OnAddInsulator(this, _track);
95 }
96
97 /// <summary>
98 /// Unlinks this insulator from a track
99 /// </summary>
100 /// <param name="_track">The track to unlink from</param>
101 protected override void RemoveFromTrack(RadioTrackWrapper _track)
102 {
103 _track.insulators.Remove(this);
104 _track.OnRemoveInsulator(this, _track);
105 }
106
107 /// <summary>
108 /// Gets the power of this insulator at a specific position
109 /// </summary>
110 /// <param name="_position">The position to evaluate with</param>
111 /// <returns>The insulation multiplier at the position. The lower the number, the stronger the insulation- it's a multiplier intended to shrink the samples rather than grow them</returns>
112 public float GetPower(Vector3 _position)
113 {
114 float power = 0;
115
116 // converts the boxes to bounds so that we can use the basic methods in the bounds class
117 Bounds innerBounds = new Bounds(cachedPos, InnerBoxSizeAdjusted);
118 Bounds outerBounds = new Bounds(cachedPos, OuterBoxSizeAdjusted);
119
120 // if the output is in the inner bounds, insulation is at maximum
121 if (innerBounds.Contains(_position))
122 power = 1;
123
124 // if the output is outside the outer bounds, insulation is at minimum
125 else if (!outerBounds.Contains(_position))
126 power = 0;
127
128 // if the output is between the inner and outer bounds, calculate how far between them it is
129 else
130 {
131 // originally i used a signed distance field for this, but for reasons i do not recall it didn't end up working as i wanted-
132 // i eventually worked out a way to calculate how far between a and b the point is using rays and bounds
133
134 // get the direction from the center of the boxes towards the given position
135 Vector3 dir = (_position - outerBounds.center).normalized;
136
137 // scale that distance by the size of the larger box so that it sits just outside (or on the corner of) the largest box
138 Vector3 scaledDir = new Vector3(dir.x * outerBounds.size.x, dir.y * outerBounds.size.y, dir.z * outerBounds.size.z);
139
140 // create a ray from the center of the box to the point just outside
141 Ray ray = new Ray(outerBounds.center, scaledDir);
142
143 // use this ray to find the distance from the center of the closest point on the outside of the inner and outer boxes
144 innerBounds.IntersectRay(ray, out float distance2);
145 outerBounds.IntersectRay(ray, out float distance);
146
147 // find the closest points on the faces of the boxes using this distance
148 Vector3 closestOnInner = innerBounds.center + ray.direction.normalized * -distance2;
149 Vector3 closestOnOuter = outerBounds.center + ray.direction.normalized * -distance;
150
151 // get the distance between the outer and inner points
152 float outerInnerDistance = Vector3.Distance(closestOnOuter, closestOnInner);
153
154 // get the distance from the inner to the given position
155 float d = Vector3.Distance(_position, closestOnInner);
156
157 // work out how far between the inner and outer points the given position is
158 power = 1 - d / outerInnerDistance;
159 }
160
161 // adjust the power by the insulation curve
162 float adjustedT = insulationCurve.Evaluate(power);
163
164 // if it's outside the boxes and does not universally apply, set the insulation to 0
165 if (adjustedT <= 0 && (ShowApplyToAllOutputs && !applyToAllOutputsOutside))
166 return 0;
167
168 // return the actual insulation using the min and max values
169 return Mathf.Lerp(insulation.x, insulation.y, adjustedT);
170 }
171 }
172
173}
An extension of RadioComponent that accesses specific tracks on the stored RadioData.
An "insulator" for a RadioTrackWrapper - if a RadioOutput is inside the bounds of this object,...
bool ShowApplyToAllOutputs
Shows applyToAllOutputsOutside when the x-value of insulation is greater than 0.
override void RemoveFromTrack(RadioTrackWrapper _track)
Unlinks this insulator from a track.
float GetPower(Vector3 _position)
Gets the power of this insulator at a specific position.
bool applyToAllOutputsOutside
Effectively makes this insulator global- when this is true, any output outside of the outer box's ran...
Vector3 OuterBoxSizeAdjusted
The outerBoxSize but adjusted with transform.localScale in Update()
Vector3 outerBoxSize
The size of the outer box of the insulator- outside of this box, insulation is 0- between this and th...
Vector3 innerBoxSize
The size of the inner box of the insulator- inside of this box, insulation is the highest.
Vector2 insulation
The max and min insulation in the outer and inner boxes.
Vector3 InnerBoxSizeAdjusted
The innerBoxSize but adjusted with transform.localScale in Update()
override void AssignToTrack(RadioTrackWrapper _track)
Links this insulator to a track.
void Update()
Updates cached position and adjusted box sizes.
Vector3 cachedPos
The position of the insulator in the previous frame. We cannot access transform.position in the audio...
AnimationCurve insulationCurve
A curve that defines insulation between the inner and outer boxes- the x-value is how far between the...
A wrapper class for RadioTrack so that track types can be switched between in the inspector!...
Action< RadioInsulator, RadioTrackWrapper > OnRemoveInsulator
An event called when an insulator is removed from this track.
Action< RadioInsulator, RadioTrackWrapper > OnAddInsulator
An event called when an insulator is added to the track.
List< RadioInsulator > insulators
The insulators in the scene that have this track selected.
Base interfaces and classes for components, e.g: track accessors, output accessors.
Components to be placed on scene objects, e.g: Outputs, Broadcasters, Observers.
Tracks to be used on a radio- includes base classes.
Definition RadioUtils.cs:20