@@ -590,106 +700,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -819,49 +829,8 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
@@ -917,27 +886,9 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
@@ -945,21 +896,7 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
@@ -985,93 +922,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -1086,75 +936,121 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
+
+
+
+
-
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
+
+
@@ -1166,5 +1062,182 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/UnityProject/Assembly-CSharp-Editor.csproj b/UnityProject/Assembly-CSharp-Editor.csproj
index 0a28f42..b40cf12 100644
--- a/UnityProject/Assembly-CSharp-Editor.csproj
+++ b/UnityProject/Assembly-CSharp-Editor.csproj
@@ -64,6 +64,7 @@
+
diff --git a/UnityProject/Assets/Editor/PdBackendEditor.cs b/UnityProject/Assets/Editor/PdBackendEditor.cs
index 5b767b7..a8650d3 100644
--- a/UnityProject/Assets/Editor/PdBackendEditor.cs
+++ b/UnityProject/Assets/Editor/PdBackendEditor.cs
@@ -43,9 +43,7 @@ namespace cylvester
GUILayout.Label("Main Patch");
pdBackend_.mainPatch = GUILayout.TextField(pdBackend_.mainPatch, 30);
GUILayout.EndHorizontal();
-
- pdBackend_.inchannels = EditorGUILayout.Popup("Number of input channels", pdBackend_.inchannels, channels_);
-
+
if (Application.isPlaying)
{
RenderSamplePlayback();
diff --git a/UnityProject/Assets/Editor/PdSpectrumBindEditor.cs b/UnityProject/Assets/Editor/PdSpectrumBindEditor.cs
index d00f96e..6a62b18 100644
--- a/UnityProject/Assets/Editor/PdSpectrumBindEditor.cs
+++ b/UnityProject/Assets/Editor/PdSpectrumBindEditor.cs
@@ -18,8 +18,7 @@ namespace cylvester
private SerializedProperty selectionProperty_;
private SerializedProperty pdBackendProperty_;
-
-
+
public void OnEnable()
{
spectrumGenerator_ = new SpectrumGenerator(TextureWidth, TextureHeight);
@@ -27,7 +26,6 @@ namespace cylvester
pdBackendProperty_ = serializedObject.FindProperty("pdBackend");
selectionProperty_ = serializedObject.FindProperty("selection");
-
}
public override void OnInspectorGUI()
@@ -40,13 +38,11 @@ namespace cylvester
RenderSpectrumExtractor(behaviour);
serializedObject.ApplyModifiedProperties();
-
}
private void RenderSpectrumExtractor(IPdSpectrumBind behaviour)
{
- UpdateSelection(behaviour);
-
+ RenderSelection();
GUILayout.Space(5);
GUILayout.Label("Spectrum Extractor", EditorStyles.boldLabel);
@@ -63,32 +59,36 @@ namespace cylvester
GUI.DrawTexture(paintSpace_, spectrumGenerator_.Spectrum);
}
- GUILayout.BeginHorizontal();
- GUILayout.Label("Extracted Energy", EditorStyles.boldLabel);
- GUILayout.Label(behaviour.Energy.ToString());
- GUILayout.EndHorizontal();
-
Repaint();
+ RenderExtractedEnergy(behaviour.Energy);
+
}
- private void UpdateSelection(IPdSpectrumBind behaviour)
+ private void RenderSelection()
{
- if (Event.current.isMouse && Event.current.button == 0)
+ if (!Event.current.isMouse || Event.current.button != 0) return;
+ switch (Event.current.type)
{
- switch (Event.current.type)
+ case EventType.MouseDown:
{
- case EventType.MouseDown:
- {
- rectangularSelection_.Start(Event.current.mousePosition);
- break;
- }
- case EventType.MouseDrag:
- {
- selectionProperty_.rectValue = rectangularSelection_.Update(Event.current.mousePosition, ref paintSpace_);
- break;
- }
+ rectangularSelection_.Start(Event.current.mousePosition);
+ break;
+ }
+ case EventType.MouseDrag:
+ {
+ selectionProperty_.rectValue = rectangularSelection_.Update(Event.current.mousePosition, ref paintSpace_);
+ break;
}
}
}
+
+ private void RenderExtractedEnergy(int energy)
+ {
+ GUILayout.BeginHorizontal();
+ GUILayout.Label("Extracted Energy", EditorStyles.boldLabel);
+ GUILayout.Label(energy.ToString());
+ GUILayout.EndHorizontal();
+ }
+
}
}
diff --git a/UnityProject/Assets/Editor/SpectrumGenerator.cs b/UnityProject/Assets/Editor/SpectrumGenerator.cs
index 0478b2d..373e15b 100644
--- a/UnityProject/Assets/Editor/SpectrumGenerator.cs
+++ b/UnityProject/Assets/Editor/SpectrumGenerator.cs
@@ -10,20 +10,19 @@ namespace cylvester
public class SpectrumGenerator : ISpectrumGenerator
{
- private Texture2D texture_;
- public Texture2D Spectrum => texture_;
-
+ public Texture2D Spectrum { get; }
+
public SpectrumGenerator(int width, int height)
{
- texture_ = new Texture2D(width, height);
+ Spectrum = new Texture2D(width, height);
}
public int Update(IPdArray pdArray, Rect selectionRect)
{
var numPixels = 0;
- for (var x = 0; x < texture_.width; x++)
+ for (var x = 0; x < Spectrum.width; x++)
{
- for (var y = 0; y < texture_.height; y++)
+ for (var y = 0; y < Spectrum.height; y++)
{
var color = Color.black;
var validPixel = false;
@@ -35,23 +34,28 @@ namespace cylvester
color = validPixel ? Color.green : Color.black;
}
- var mY = texture_.height - selectionRect.y;
- if ((selectionRect.x < x && x < (selectionRect.x + selectionRect.width)) &&
- (mY - selectionRect.height < y && y < mY))
+ if (IsInSelection(x, y, ref selectionRect))
{
color.a = 1f;
if (validPixel)
numPixels++;
}
else
- {
color.a = 0.2f;
- }
- texture_.SetPixel(x, y, color);
+
+ Spectrum.SetPixel(x, y, color);
}
}
- texture_.Apply();
+ Spectrum.Apply();
return numPixels;
}
+
+ private bool IsInSelection(int x, int y, ref Rect selectionRect)
+ {
+ var inRectHorizontally = selectionRect.x < x && x < selectionRect.x + (selectionRect.width-1);
+ var mY = Spectrum.height - selectionRect.y;
+ var inRectVertically = mY - (selectionRect.height-1) < y && y < mY;
+ return inRectHorizontally && inRectVertically;
+ }
}
}
\ No newline at end of file
diff --git a/UnityProject/Assets/Editor/UnitTest/UnitTest_SpectrumGenerator.cs b/UnityProject/Assets/Editor/UnitTest/UnitTest_SpectrumGenerator.cs
new file mode 100644
index 0000000..e3418f8
--- /dev/null
+++ b/UnityProject/Assets/Editor/UnitTest/UnitTest_SpectrumGenerator.cs
@@ -0,0 +1,87 @@
+using NUnit.Framework;
+using NSubstitute;
+using UnityEngine;
+
+namespace cylvester
+{
+ [TestFixture]
+ public class UnitTest_SpectrumGenerator
+ {
+ private IPdArray pdArray_;
+ private Rect selectionRect_;
+ private float[] dummyData_;
+ private Color standardColor_;
+ private Color selectedColor_;
+
+ [SetUp]
+ public void SetUp()
+ {
+ pdArray_ = Substitute.For();
+ selectionRect_ = new Rect {x = 9, y = 9, width = 3, height = 3};
+ dummyData_ = new float[100];
+
+ for (var i = 0; i < dummyData_.Length; ++i)
+ {
+ dummyData_[i] = i / (float)dummyData_.Length;
+ }
+
+ standardColor_ = new Color(0f, 0f, 0f, 0.2f);
+ selectedColor_ = new Color(0f, 0f, 0f, 1f);
+ }
+
+ [Test]
+ public void Construction()
+ {
+ var spectrumGenerator = new SpectrumGenerator(100, 101);
+
+ Assert.AreEqual(100, spectrumGenerator.Spectrum.width);
+ Assert.AreEqual(101, spectrumGenerator.Spectrum.height);
+ }
+
+ [Test]
+ public void Update_array_available()
+ {
+ var spectrumGenerator = new SpectrumGenerator(100, 100);
+ spectrumGenerator.Update(pdArray_, selectionRect_);
+
+
+ }
+
+ [Test]
+ public void Update_array_unavailable()
+ {
+ var noSelection = new Rect {width = 0, height = 0};
+ var spectrumGenerator = new SpectrumGenerator(100, 100);
+ var validPixels = spectrumGenerator.Update(null, noSelection);
+
+ Assert.AreEqual(0, validPixels);
+ var texture = spectrumGenerator.Spectrum;
+ var pixels = texture.GetPixels();
+
+ foreach (var pixel in pixels)
+ Assert.AreEqual(standardColor_, pixel);
+ }
+
+ [Test]
+ public void Update_array_unavailable_with_selection()
+ {
+ var spectrumGenerator = new SpectrumGenerator(100, 100);
+ var validPixels = spectrumGenerator.Update(null, selectionRect_);
+
+ Assert.AreEqual(0, validPixels);
+ var texture = spectrumGenerator.Spectrum;
+
+ for (var x = 0; x < 100; x++)
+ {
+ for (var y = 0; y < 100; y++)
+ {
+ if(x == 10 && y == 90) // because vertically inverted
+ Assert.AreEqual(selectedColor_, texture.GetPixel(x, y));
+ else
+ Assert.AreEqual(standardColor_, texture.GetPixel(x, y));
+
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/UnityProject/Assets/Editor/UnitTest/UnitTest_SpectrumGenerator.cs.meta b/UnityProject/Assets/Editor/UnitTest/UnitTest_SpectrumGenerator.cs.meta
new file mode 100644
index 0000000..ed4aab1
--- /dev/null
+++ b/UnityProject/Assets/Editor/UnitTest/UnitTest_SpectrumGenerator.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 569cb1b5c266408cb26f97a8e7510191
+timeCreated: 1569957130
\ No newline at end of file
diff --git a/UnityProject/Assets/Plugins/NSubstitute.XML b/UnityProject/Assets/Plugins/NSubstitute.XML
new file mode 100644
index 0000000..4bd55c1
--- /dev/null
+++ b/UnityProject/Assets/Plugins/NSubstitute.XML
@@ -0,0 +1,259 @@
+
+
+
+ NSubstitute
+
+
+
+
+ Argument matchers used for specifying calls to substitutes.
+
+
+
+
+ Match any argument value compatible with type .
+
+
+
+
+
+
+ Match argument that is equal to .
+
+
+
+
+
+
+
+ Match argument that satisfies .
+ If the throws an exception for an argument it will be treated as non-matching.
+
+
+
+
+
+
+
+ Invoke any argument as soon as a matching call is made to the substitute.
+
+
+
+
+
+ Invoke any argument with specified argument as soon as a matching call is made to the substitute.
+
+
+
+
+
+
+
+ Invoke any argument with specified arguments as soon as a matching call is made to the substitute.
+
+
+
+
+
+
+
+
+
+ Invoke any argument with specified arguments as soon as a matching call is made to the substitute.
+
+
+
+
+
+
+
+
+
+
+
+ Invoke any argument with specified arguments as soon as a matching call is made to the substitute.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Invoke any argument with specified arguments as soon as a matching call is made to the substitute.
+
+
+ Arguments to pass to delegate.
+
+
+
+
+ Capture any argument compatible with type and use it to call the function
+ as soon as a matching call is made to the substitute.
+
+
+
+
+
+
+
+ Provides a specification for arguments for use with .
+ Can additionally implement to give descriptions when arguments do not match.
+
+
+
+
+ Checks whether the satisfies the condition of the matcher.
+ If this throws an exception the argument will be treated as non-matching.
+
+
+
+
+
+
+ Describes how the does not match the condition specified by this class, or
+ if a detailed description can not be provided for the argument.
+
+
+ Description of the non-match, or if no description can be provided.
+
+
+
+ Combines two enumerables into a new enumerable using the given selector.
+
+
+
+
+
+
+
+
+
+ This implementation was sanity-checked against the
+ Edulinq implementation and
+ Eric Lippert's implementation.
+
+
+
+
+ Checks if the instance can be used when a is expected.
+
+
+
+
+
+
+
+ Join the using .
+
+
+
+
+
+
+
+ Delegates to ThreadLocal<T>, but wraps Value property access in try/catch to swallow ObjectDisposedExceptions.
+ These can occur if the Value property is accessed from the finalizer thread. Because we can't detect this, we'll
+ just swallow the exception (the finalizer thread won't be using any of the values from thread local storage anyway).
+
+
+
+
+
+ Provides a specification for arguments for use with .
+ Can additionally implement to give descriptions when arguments do not match.
+
+ Matches arguments of type or compatible type.
+
+
+
+ Checks whether the satisfies the condition of the matcher.
+ If this throws an exception the argument will be treated as non-matching.
+
+
+
+
+
+
+ Raise an event for an EventHandler<TEventArgs> event with the provided and .
+
+
+
+
+ Raise an event for an EventHandler<TEventArgs> event with the substitute as the sender and the provided .
+
+
+
+
+ Raise an event for an EventHandler<EventArgsT> event with the substitute as the sender
+ and with a default instance of .
+
+
+
+
+ Raise an event for an EventHandler or EventHandler<EventArgs> event with the substitute
+ as the sender and with empty EventArgs.
+
+
+
+
+ Raise an event of type with the provided arguments. If no arguments are provided
+ NSubstitute will try and provide reasonble defaults.
+
+
+
+
+ Create a substitute for one or more types. For example: Substitute.For<ISomeType>()
+
+
+
+
+ Substitute for an interface or class.
+ Be careful when specifying a class, as all non-virtual members will actually be executed. Only virtual members
+ can be recorded or have return values specified.
+
+ The type of interface or class to substitute.
+ Arguments required to construct a class being substituted. Not required for interfaces or classes with default constructors.
+ A substitute for the interface or class.
+
+
+
+ Substitute for multiple interfaces or a class that implements an interface. At most one class can be specified.
+ Be careful when specifying a class, as all non-virtual members will actually be executed. Only virtual members
+ can be recorded or have return values specified.
+
+ The type of interface or class to substitute.
+ An additional interface or class (maximum of one class) the substitute should implement.
+ Arguments required to construct a class being substituted. Not required for interfaces or classes with default constructors.
+ A substitute of type T1, that also implements T2.
+
+
+
+ Substitute for multiple interfaces or a class that implements multiple interfaces. At most one class can be specified.
+ If additional interfaces are required use the overload.
+ Be careful when specifying a class, as all non-virtual members will actually be executed. Only virtual members
+ can be recorded or have return values specified.
+
+ The type of interface or class to substitute.
+ An additional interface or class (maximum of one class) the substitute should implement.
+ An additional interface or class (maximum of one class) the substitute should implement.
+ Arguments required to construct a class being substituted. Not required for interfaces or classes with default constructors.
+ A substitute of type T1, that also implements T2 and T3.
+
+
+
+ Substitute for multiple interfaces or a class that implements multiple interfaces. At most one class can be specified.
+ Be careful when specifying a class, as all non-virtual members will actually be executed. Only virtual members
+ can be recorded or have return values specified.
+
+ The types of interfaces or a type of class and multiple interfaces the substitute should implement.
+ Arguments required to construct a class being substituted. Not required for interfaces or classes with default constructors.
+ A substitute implementing the specified types.
+
+
+
diff --git a/UnityProject/Assets/Plugins/NSubstitute.XML.meta b/UnityProject/Assets/Plugins/NSubstitute.XML.meta
new file mode 100644
index 0000000..0cae869
--- /dev/null
+++ b/UnityProject/Assets/Plugins/NSubstitute.XML.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: bdc35bfcd6b707f4fb1a603ebd847600
+TextScriptImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/UnityProject/Assets/Plugins/NSubstitute.dll b/UnityProject/Assets/Plugins/NSubstitute.dll
index 39eec94..fba0966 100644
Binary files a/UnityProject/Assets/Plugins/NSubstitute.dll and b/UnityProject/Assets/Plugins/NSubstitute.dll differ
diff --git a/UnityProject/Assets/Scenes/Examples/PdBackendDemo/PdBackendDemo.unity b/UnityProject/Assets/Scenes/Examples/PdBackendDemo/PdBackendDemo.unity
index 910b961..5ba08cc 100644
--- a/UnityProject/Assets/Scenes/Examples/PdBackendDemo/PdBackendDemo.unity
+++ b/UnityProject/Assets/Scenes/Examples/PdBackendDemo/PdBackendDemo.unity
@@ -202,7 +202,13 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 54ab37d032df403e881d6a7a78141815, type: 3}
m_Name:
m_EditorClassIdentifier:
- pdBackend: {fileID: 987772533}
+ pdBackend: {fileID: 0}
+ selection:
+ serializedVersion: 2
+ x: 297.75885
+ y: 55
+ width: 101.67376
+ height: 102
--- !u!1 &267275365
GameObject:
m_ObjectHideFlags: 0
@@ -315,7 +321,7 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
mainPatch: analyzer.pd
- inchannels: 2
+ samplePlayback: 0
--- !u!4 &987772534
Transform:
m_ObjectHideFlags: 0
diff --git a/UnityProject/Assets/Scripts/PdConnection/PdBackend.cs b/UnityProject/Assets/Scripts/PdConnection/PdBackend.cs
index 72fcbf2..af188cf 100644
--- a/UnityProject/Assets/Scripts/PdConnection/PdBackend.cs
+++ b/UnityProject/Assets/Scripts/PdConnection/PdBackend.cs
@@ -6,10 +6,9 @@ namespace cylvester
public class PdBackend : MonoBehaviour
{
public string mainPatch = "analyzer.pd";
- public int inchannels = 2;
public int samplePlayback = 0;
public PdArray levelMeterArray;
- public FftArrayContainer fftArrayContainer;
+ public IFftArrayContainer fftArrayContainer;
private IChangeObserver samplePlaybackObserver_;
private Action onSamplePlaybackChanged_;
@@ -18,7 +17,7 @@ namespace cylvester
private void Start()
{
- PdProcess.Instance.Start(mainPatch, inchannels);
+ PdProcess.Instance.Start(mainPatch);
levelMeterArray = new PdArray("levelmeters", PdConstant.NumMaxInputChannels);
fftArrayContainer = new FftArrayContainer();
pdSocket_ = new PdSocket(PdConstant.ip, PdConstant.port);
@@ -27,7 +26,7 @@ namespace cylvester
onSamplePlaybackChanged_ = () =>
{
- var bytes = new byte[]{(byte)PdMessage.SampleSound, (byte)samplePlayback};
+ var bytes = new[]{(byte)PdMessage.SampleSound, (byte)samplePlayback};
pdSocket_.Send(bytes);
};
@@ -48,7 +47,6 @@ namespace cylvester
levelMeterArray.Update();
fftArrayContainer.Update();
-
samplePlaybackObserver_.Value = samplePlayback;
}
}
diff --git a/UnityProject/Assets/Scripts/PdConnection/PdConstant.cs b/UnityProject/Assets/Scripts/PdConnection/PdConstant.cs
index a02c948..ae37d9c 100644
--- a/UnityProject/Assets/Scripts/PdConnection/PdConstant.cs
+++ b/UnityProject/Assets/Scripts/PdConnection/PdConstant.cs
@@ -10,8 +10,5 @@ namespace cylvester
public static readonly int NumMaxInputChannels = 16;
public static readonly string ip = "127.0.0.1";
public static readonly int port = 54345;
-
-
-
}
}
\ No newline at end of file
diff --git a/UnityProject/Assets/Scripts/PdConnection/PdProcess.cs b/UnityProject/Assets/Scripts/PdConnection/PdProcess.cs
index 54625a4..81ee649 100644
--- a/UnityProject/Assets/Scripts/PdConnection/PdProcess.cs
+++ b/UnityProject/Assets/Scripts/PdConnection/PdProcess.cs
@@ -6,14 +6,7 @@ using Debug = UnityEngine.Debug;
namespace cylvester
{
- interface IPdProcess
- {
- void Start(string mainPatch, int numInputChannels);
- void Stop();
- bool Running { get; }
- }
-
- public class PdProcess : IPdProcess
+ public class PdProcess
{
private static PdProcess instance_ = null;
private Process pdProcess_;
@@ -22,10 +15,9 @@ namespace cylvester
{
} // cannot be instantiate normally
-
public static PdProcess Instance => instance_ ?? (instance_ = new PdProcess());
- public void Start(string mainPatch, int numInputChannels)
+ public void Start(string mainPatch)
{
if (pdProcess_ != null)
@@ -41,7 +33,7 @@ namespace cylvester
pdProcess_.StartInfo.FileName = Application.streamingAssetsPath + "/pd/win/pd.com";
var path = Application.streamingAssetsPath + "/pd/patch/" + mainPatch;
- pdProcess_.StartInfo.Arguments = "-nogui -rt -inchannels " + numInputChannels + " " + path;
+ pdProcess_.StartInfo.Arguments = "-nogui -rt " + path;
if (!pdProcess_.Start())
{
@@ -59,7 +51,6 @@ namespace cylvester
pdProcess_.Kill();
pdProcess_ = null;
Debug.Log("Pd Process stopped");
-
}
public bool Running
diff --git a/UnityProject/UnityProject.sln.DotSettings.user b/UnityProject/UnityProject.sln.DotSettings.user
index a375aad..73db7fa 100644
--- a/UnityProject/UnityProject.sln.DotSettings.user
+++ b/UnityProject/UnityProject.sln.DotSettings.user
@@ -1,3 +1,6 @@
+ <AssemblyExplorer>
+ <Assembly Path="C:\Users\chikashi\Development\Soundvision\UnityProject\Assets\Plugins\NSubstitute.dll" />
+</AssemblyExplorer>TrueTrue
\ No newline at end of file