diff --git a/Assets/Plugins/x86_64/Linux/libEEGFormat.so b/Assets/Plugins/x86_64/Linux/libEEGFormat.so index d53e5ffa0..cec284a29 100644 Binary files a/Assets/Plugins/x86_64/Linux/libEEGFormat.so and b/Assets/Plugins/x86_64/Linux/libEEGFormat.so differ diff --git a/Assets/Plugins/x86_64/Linux/libhbp_export.so b/Assets/Plugins/x86_64/Linux/libhbp_export.so index c79521a63..657aa6b23 100644 Binary files a/Assets/Plugins/x86_64/Linux/libhbp_export.so and b/Assets/Plugins/x86_64/Linux/libhbp_export.so differ diff --git a/Assets/Plugins/x86_64/MacOS/EEGFormat.bundle/Contents/MacOS/libEEGFormat b/Assets/Plugins/x86_64/MacOS/EEGFormat.bundle/Contents/MacOS/libEEGFormat index cbaa0003a..9be2d72c0 100644 Binary files a/Assets/Plugins/x86_64/MacOS/EEGFormat.bundle/Contents/MacOS/libEEGFormat and b/Assets/Plugins/x86_64/MacOS/EEGFormat.bundle/Contents/MacOS/libEEGFormat differ diff --git a/Assets/Plugins/x86_64/MacOS/hbp_export.bundle/Contents/MacOS/libhbp_export b/Assets/Plugins/x86_64/MacOS/hbp_export.bundle/Contents/MacOS/libhbp_export index d5c457d11..92af82fc3 100644 Binary files a/Assets/Plugins/x86_64/MacOS/hbp_export.bundle/Contents/MacOS/libhbp_export and b/Assets/Plugins/x86_64/MacOS/hbp_export.bundle/Contents/MacOS/libhbp_export differ diff --git a/Assets/Plugins/x86_64/Windows/EEGFormat.dll b/Assets/Plugins/x86_64/Windows/EEGFormat.dll index fc843476a..55814af68 100644 Binary files a/Assets/Plugins/x86_64/Windows/EEGFormat.dll and b/Assets/Plugins/x86_64/Windows/EEGFormat.dll differ diff --git a/Assets/Plugins/x86_64/Windows/hbp_export.dll b/Assets/Plugins/x86_64/Windows/hbp_export.dll index 3b0ccb8a2..fc89569ac 100644 Binary files a/Assets/Plugins/x86_64/Windows/hbp_export.dll and b/Assets/Plugins/x86_64/Windows/hbp_export.dll differ diff --git a/Assets/Prefabs/3D/UI/3D Menu.prefab b/Assets/Prefabs/3D/UI/3D Menu.prefab index 86a2090d6..451a8917f 100644 Binary files a/Assets/Prefabs/3D/UI/3D Menu.prefab and b/Assets/Prefabs/3D/UI/3D Menu.prefab differ diff --git a/Assets/Prefabs/CustomUI/Range Slider.prefab b/Assets/Prefabs/CustomUI/Range Slider.prefab index 51809598d..62bba7eee 100644 Binary files a/Assets/Prefabs/CustomUI/Range Slider.prefab and b/Assets/Prefabs/CustomUI/Range Slider.prefab differ diff --git a/Assets/Prefabs/Elements/Content/Sections/Fields/Range Slider With Values.prefab b/Assets/Prefabs/Elements/Content/Sections/Fields/Range Slider With Values.prefab index e51de3981..accb76f7d 100644 Binary files a/Assets/Prefabs/Elements/Content/Sections/Fields/Range Slider With Values.prefab and b/Assets/Prefabs/Elements/Content/Sections/Fields/Range Slider With Values.prefab differ diff --git a/Assets/Prefabs/Informations/Informations.prefab b/Assets/Prefabs/Informations/Informations.prefab index 8010fbd75..c6ea9b13e 100644 Binary files a/Assets/Prefabs/Informations/Informations.prefab and b/Assets/Prefabs/Informations/Informations.prefab differ diff --git a/Assets/Prefabs/Informations/SitesInformations.prefab b/Assets/Prefabs/Informations/SitesInformations.prefab index 026a6aaa1..c397f6fa1 100644 Binary files a/Assets/Prefabs/Informations/SitesInformations.prefab and b/Assets/Prefabs/Informations/SitesInformations.prefab differ diff --git a/Assets/Prefabs/Project/Project item.prefab b/Assets/Prefabs/Project/Project item.prefab index 1672fafd9..7ecf610e0 100644 Binary files a/Assets/Prefabs/Project/Project item.prefab and b/Assets/Prefabs/Project/Project item.prefab differ diff --git a/Assets/Scripts/HBP/Core/Data/Loaded/DynamicData.cs b/Assets/Scripts/HBP/Core/Data/Loaded/DynamicData.cs index e9c6d0095..30ab743c2 100644 --- a/Assets/Scripts/HBP/Core/Data/Loaded/DynamicData.cs +++ b/Assets/Scripts/HBP/Core/Data/Loaded/DynamicData.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using UnityEngine; namespace HBP.Core.Data { @@ -76,8 +77,16 @@ public DynamicData(DataInfo dataInfo) : this() List channels = file.Electrodes; foreach (var channel in channels) { - ValuesByChannel.Add(channel.Label, channel.Data); - UnitByChannel.Add(channel.Label, channel.Unit); + try + { + ValuesByChannel.Add(channel.Label, channel.Data); + UnitByChannel.Add(channel.Label, channel.Unit); + } + catch (ArgumentException e) + { + Debug.LogException(e); + throw new Exception(string.Format("The data file contains multiple {0} channels.", channel.Label)); + } } Frequency = file.SamplingFrequency; m_OccurencesByCode = new Dictionary>(); diff --git a/Assets/Scripts/HBP/Core/Data/Patient/BaseMesh.cs b/Assets/Scripts/HBP/Core/Data/Patient/BaseMesh.cs index f64fbf6b7..925009985 100644 --- a/Assets/Scripts/HBP/Core/Data/Patient/BaseMesh.cs +++ b/Assets/Scripts/HBP/Core/Data/Patient/BaseMesh.cs @@ -147,11 +147,12 @@ public static BaseMesh[] LoadFromDirectory(string path) { List meshes = new List(); DirectoryInfo parent = new DirectoryInfo(path); - DirectoryInfo t1mr1 = new DirectoryInfo(Path.Combine(path, "t1mri")); + DirectoryInfo t1mri = new DirectoryInfo(Path.Combine(path, "t1mri")); + DirectoryInfo ct = new DirectoryInfo(Path.Combine(path, "ct")); DirectoryInfo preimplantationDirectory = null, preTransformationsDirectory = null; FileInfo preTransformation = null; - preimplantationDirectory = t1mr1.GetDirectories("T1pre_*").FirstOrDefault(); + if (t1mri.Exists) preimplantationDirectory = t1mri.GetDirectories("T1pre_*").FirstOrDefault(); if (preimplantationDirectory != null && preimplantationDirectory.Exists) { preTransformationsDirectory = new DirectoryInfo(Path.Combine(preimplantationDirectory.FullName, "registration")); @@ -165,7 +166,7 @@ public static BaseMesh[] LoadFromDirectory(string path) // Post DirectoryInfo postimplantationDirectory = null, postTransformationsDirectory = null; FileInfo postTransformation = null; - postimplantationDirectory = t1mr1.GetDirectories("T1post_*").FirstOrDefault(); + if (t1mri.Exists) postimplantationDirectory = t1mri.GetDirectories("T1post_*").FirstOrDefault(); if (postimplantationDirectory != null && postimplantationDirectory.Exists) { postTransformationsDirectory = new DirectoryInfo(Path.Combine(postimplantationDirectory.FullName, "registration")); @@ -176,6 +177,20 @@ public static BaseMesh[] LoadFromDirectory(string path) } string postTransformationPath = string.Empty; if (postTransformation != null && postTransformation.Exists) postTransformationPath = postTransformation.FullName; + // CT + DirectoryInfo ctDirectory = null, ctTransformationsDirectory = null; + FileInfo ctTransformation = null; + if (ct.Exists) ctDirectory = ct.GetDirectories("CTpost_*").FirstOrDefault(); + if (ctDirectory != null && ctDirectory.Exists) + { + ctTransformationsDirectory = new DirectoryInfo(Path.Combine(ctDirectory.FullName, "registration")); + if (ctTransformationsDirectory != null && ctTransformationsDirectory.Exists) + { + ctTransformation = ctTransformationsDirectory.GetFiles("CT-" + parent.Name + "_" + ctDirectory.Name + "_TO_Scanner_Based.trm").FirstOrDefault(); + } + } + string ctTransformationPath = string.Empty; + if (ctTransformation != null && ctTransformation.Exists) ctTransformationPath = ctTransformation.FullName; // Mesh DirectoryInfo meshDirectory = new DirectoryInfo(Path.Combine(preimplantationDirectory.FullName, "default_analysis", "segmentation", "mesh")); if(meshDirectory.Exists) @@ -189,6 +204,10 @@ public static BaseMesh[] LoadFromDirectory(string path) { meshes.Add(new LeftRightMesh("Grey matter post", postTransformationPath, greyMatterLeftHemisphere.FullName, greyMatterRightHemisphere.FullName, string.Empty, string.Empty)); } + if (!string.IsNullOrEmpty(ctTransformationPath)) + { + meshes.Add(new LeftRightMesh("Grey matter CT", ctTransformationPath, greyMatterLeftHemisphere.FullName, greyMatterRightHemisphere.FullName, string.Empty, string.Empty)); + } } FileInfo whiteMatterLeftHemisphere = new FileInfo(Path.Combine(meshDirectory.FullName, parent.Name + "_Lwhite" + MESH_EXTENSION)); @@ -205,6 +224,10 @@ public static BaseMesh[] LoadFromDirectory(string path) { meshes.Add(new LeftRightMesh("White matter post", postTransformationPath, whiteMatterLeftHemisphere.FullName, whiteMatterRightHemisphere.FullName, marsAtlasLeftHemispherePath, marsAtlasRightHemispherePath)); } + if (!string.IsNullOrEmpty(ctTransformationPath)) + { + meshes.Add(new LeftRightMesh("White matter CT", ctTransformationPath, whiteMatterLeftHemisphere.FullName, whiteMatterRightHemisphere.FullName, marsAtlasLeftHemispherePath, marsAtlasRightHemispherePath)); + } } } return meshes.ToArray(); diff --git a/Assets/Scripts/HBP/Core/Data/Patient/MRI.cs b/Assets/Scripts/HBP/Core/Data/Patient/MRI.cs index 0bd9d2bfa..8d53ca84e 100644 --- a/Assets/Scripts/HBP/Core/Data/Patient/MRI.cs +++ b/Assets/Scripts/HBP/Core/Data/Patient/MRI.cs @@ -141,6 +141,7 @@ public static MRI[] LoadFromDirectory(string path) if (string.IsNullOrEmpty(path) || !Directory.Exists(path)) return MRIs.ToArray(); DirectoryInfo directoryInfo = new DirectoryInfo(path); DirectoryInfo t1mriDirectoy = directoryInfo.GetDirectories("t1mri", SearchOption.TopDirectoryOnly).FirstOrDefault(); + DirectoryInfo ct = directoryInfo.GetDirectories("ct", SearchOption.TopDirectoryOnly).FirstOrDefault(); if (t1mriDirectoy != null && t1mriDirectoy.Exists) { @@ -165,6 +166,20 @@ public static MRI[] LoadFromDirectory(string path) MRIs.Add(new MRI("Postimplantation", postimplantationMRIFile.FullName)); } } + + // CT + if (ct != null && ct.Exists) + { + DirectoryInfo ctDirectory = ct.GetDirectories("CTpost_*", SearchOption.TopDirectoryOnly).FirstOrDefault(); + if (ctDirectory != null && ctDirectory.Exists) + { + FileInfo ctMRIFile = ctDirectory.GetFiles(directoryInfo.Name + "-CTPost_*" + EXTENSION).FirstOrDefault(); + if (ctMRIFile != null && ctMRIFile.Exists) + { + MRIs.Add(new MRI("CT", ctMRIFile.FullName)); + } + } + } } return MRIs.ToArray(); } diff --git a/Assets/Scripts/HBP/Core/Data/Patient/Site.cs b/Assets/Scripts/HBP/Core/Data/Patient/Site.cs index 7e83b7783..2ded3d587 100644 --- a/Assets/Scripts/HBP/Core/Data/Patient/Site.cs +++ b/Assets/Scripts/HBP/Core/Data/Patient/Site.cs @@ -123,6 +123,10 @@ public static List LoadFromIntranatDirectory(string path) { referenceSystem = "Post"; } + else if (referenceSystem.Contains("CTPost")) + { + referenceSystem = "CT"; + } var ptsSites = LoadSitesFromPTSFile(referenceSystem, file.FullName); foreach (var site in ptsSites) { @@ -175,11 +179,11 @@ public static List LoadImplantationFromBIDSFile(string referenceSystem, st int marsAtlasIndex = splittedLines[0].IndexOf("MarsAtlas"); if (marsAtlasIndex != -1) { - splittedLines[0].Insert(marsAtlasIndex + 1, "Hemisphere (MarsAtlas)"); - splittedLines[0].Insert(marsAtlasIndex + 2, "Lobe (MarsAtlas)"); - splittedLines[0].Insert(marsAtlasIndex + 3, "Name_FS (MarsAtlas)"); - splittedLines[0].Insert(marsAtlasIndex + 4, "Full name (MarsAtlas)"); - splittedLines[0].Insert(marsAtlasIndex + 5, "Brodmann Area (MarsAtlas)"); + splittedLines[0].Insert(marsAtlasIndex + 1, "Hemisphere-MarsAtlas"); + splittedLines[0].Insert(marsAtlasIndex + 2, "Lobe-MarsAtlas"); + splittedLines[0].Insert(marsAtlasIndex + 3, "NameFS-MarsAtlas"); + splittedLines[0].Insert(marsAtlasIndex + 4, "Fullname-MarsAtlas"); + splittedLines[0].Insert(marsAtlasIndex + 5, "BrodmannArea-MarsAtlas"); for (int i = 1; i < splittedLines.Count; ++i) { int marsAtlasLabel = Object3DManager.MarsAtlas.Label(splittedLines[i][marsAtlasIndex]); @@ -410,11 +414,11 @@ public static List LoadSitesFromCSVFile(string csvFile) int marsAtlasIndex = splittedLines[0].IndexOf("MarsAtlas"); if (marsAtlasIndex != -1) { - splittedLines[0].Insert(marsAtlasIndex + 1, "Hemisphere (MarsAtlas)"); - splittedLines[0].Insert(marsAtlasIndex + 2, "Lobe (MarsAtlas)"); - splittedLines[0].Insert(marsAtlasIndex + 3, "Name_FS (MarsAtlas)"); - splittedLines[0].Insert(marsAtlasIndex + 4, "Full name (MarsAtlas)"); - splittedLines[0].Insert(marsAtlasIndex + 5, "Brodmann Area (MarsAtlas)"); + splittedLines[0].Insert(marsAtlasIndex + 1, "Hemisphere-MarsAtlas"); + splittedLines[0].Insert(marsAtlasIndex + 2, "Lobe-MarsAtlas"); + splittedLines[0].Insert(marsAtlasIndex + 3, "NameFS-MarsAtlas"); + splittedLines[0].Insert(marsAtlasIndex + 4, "Fullname-MarsAtlas"); + splittedLines[0].Insert(marsAtlasIndex + 5, "Brodmann-MarsAtlas"); for (int i = 1; i < splittedLines.Count; ++i) { int marsAtlasLabel = Object3DManager.MarsAtlas.Label(splittedLines[i][marsAtlasIndex]); diff --git a/Assets/Scripts/HBP/Core/Data/Project/Alias.cs b/Assets/Scripts/HBP/Core/Data/Project/Alias.cs index fc798c6f5..9ccc84f0b 100644 --- a/Assets/Scripts/HBP/Core/Data/Project/Alias.cs +++ b/Assets/Scripts/HBP/Core/Data/Project/Alias.cs @@ -33,10 +33,12 @@ public Alias(string key, string value) : base() #region Public Methods public void ConvertKeyToValue(ref string s) { + if (string.IsNullOrEmpty(Value)) return; s = s.Replace(Key, Value); } public void ConvertValueToKey(ref string s) { + if (string.IsNullOrEmpty(Value)) return; s = s.Replace(Value, Key); } #endregion diff --git a/Assets/Scripts/HBP/Core/Data/Project/Project.cs b/Assets/Scripts/HBP/Core/Data/Project/Project.cs index 5109e23da..ee13b0ced 100644 --- a/Assets/Scripts/HBP/Core/Data/Project/Project.cs +++ b/Assets/Scripts/HBP/Core/Data/Project/Project.cs @@ -9,6 +9,7 @@ using UnityEngine; using HBP.Core.Exceptions; using HBP.Core.Tools; +using HBP.Core.Interfaces; namespace HBP.Core.Data { @@ -404,6 +405,89 @@ public string GetProject(string path, string ID) } return projectsDirectories.FirstOrDefault((project) => new ProjectInfo(project).Settings.ID == ID); } + public Dictionary>> CheckProjectIDs() + { + Dictionary>> dataByID = new Dictionary>>(); + void addToDict(BaseData data, string name) + { + if (dataByID.ContainsKey(data.ID)) dataByID[data.ID].Add(new Tuple(data, name)); + else dataByID.Add(data.ID, new List>(new Tuple[] { new Tuple(data, name) })); + } + string getName(INameable data) + { + return string.Format("{0} ({1})", data.Name, getType(data as BaseData)); + } + string getType(BaseData data) + { + return data.GetType().ToString().Split('.').Last(); + } + // Settings + addToDict(Preferences, getType(Preferences)); + foreach (var alias in Preferences.Aliases) addToDict(alias, string.Format("{0} ({1})", alias.Key, getType(alias))); + foreach (var tag in Preferences.Tags) addToDict(tag, getName(tag)); + // Patients + foreach (var patient in m_Patients) + { + addToDict(patient, getName(patient)); + foreach (var mesh in patient.Meshes) addToDict(mesh, string.Format("{0} / {1}", getName(patient), getName(mesh))); + foreach (var mri in patient.MRIs) addToDict(mri, string.Format("{0} / {1}", getName(patient), getName(mri))); + foreach (var site in patient.Sites) + { + addToDict(site, string.Format("{0} / {1}", getName(patient), getName(site))); + foreach (var coordinate in site.Coordinates) addToDict(coordinate, string.Format("{0} / {1} / {2}", getName(patient), getName(site), string.Format("{0} ({1})", coordinate.ReferenceSystem, getType(coordinate)))); + foreach (var tagValue in site.Tags) addToDict(tagValue, string.Format("{0} / {1} / {2}", getName(patient), getName(site), string.Format("{0} ({1})", tagValue.Tag.Name, getType(tagValue)))); + } + foreach (var tagValue in patient.Tags) addToDict(tagValue, string.Format("{0} / {1}", getName(patient), string.Format("{0} ({1})", tagValue.Tag.Name, getType(tagValue)))); + } + // Groups + foreach (var group in m_Groups) addToDict(group, getName(group)); + // Protocols + foreach (var protocol in m_Protocols) + { + addToDict(protocol, getName(protocol)); + foreach (var bloc in protocol.Blocs) + { + addToDict(bloc, string.Format("{0} / {1}", getName(protocol), getName(bloc))); + foreach (var subBloc in bloc.SubBlocs) + { + addToDict(subBloc, string.Format("{0} / {1} / {2}", getName(protocol), getName(bloc), getName(subBloc))); + foreach (var ev in subBloc.Events) addToDict(ev, string.Format("{0} / {1} / {2} / {3}", getName(protocol), getName(bloc), getName(subBloc), getName(ev))); + foreach (var icon in subBloc.Icons) addToDict(icon, string.Format("{0} / {1} / {2} / {3}", getName(protocol), getName(bloc), getName(subBloc), getName(icon))); + foreach (var treatment in subBloc.Treatments) addToDict(treatment, string.Format("{0} / {1} / {2} / {3}", getName(protocol), getName(bloc), getName(subBloc), getType(treatment))); + } + } + } + // Datasets + foreach (var dataset in m_Datasets) + { + addToDict(dataset, getName(dataset)); + foreach (var data in dataset.Data) + { + addToDict(data, string.Format("{0} / {1}", getName(dataset), getName(data))); + addToDict(data.DataContainer, string.Format("{0} / {1} / {2}", getName(dataset), getName(data), getType(data.DataContainer))); + } + } + // Visualizations + foreach (var visualization in m_Visualizations) + { + addToDict(visualization, getName(visualization)); + foreach (var column in visualization.Columns) + { + addToDict(column, string.Format("{0} / {1}", getName(visualization), getName(column))); + addToDict(column.BaseConfiguration, string.Format("{0} / {1} / {2}", getName(visualization), getName(column), getType(column.BaseConfiguration))); + foreach (var siteConfig in column.BaseConfiguration.ConfigurationBySite) addToDict(siteConfig.Value, string.Format("{0} / {1} / {2})", getName(visualization), getName(column), string.Format("{0} ({1})", siteConfig.Key, getType(siteConfig.Value)))); + } + foreach (var anatomicColumn in visualization.AnatomicColumns) addToDict(anatomicColumn.AnatomicConfiguration, string.Format("{0} / {1} / {2}", getName(visualization), getName(anatomicColumn), getType(anatomicColumn.AnatomicConfiguration))); + foreach (var ieegColumn in visualization.IEEGColumns) addToDict(ieegColumn.DynamicConfiguration, string.Format("{0} / {1} / {2}", getName(visualization), getName(ieegColumn), getType(ieegColumn.DynamicConfiguration))); + foreach (var ccepColumn in visualization.CCEPColumns) addToDict(ccepColumn.DynamicConfiguration, string.Format("{0} / {1} / {2}", getName(visualization), getName(ccepColumn), getType(ccepColumn.DynamicConfiguration))); + foreach (var fmriColumn in visualization.FMRIColumns) addToDict(fmriColumn.FMRIConfiguration, string.Format("{0} / {1} / {2}", getName(visualization), getName(fmriColumn), getType(fmriColumn.FMRIConfiguration))); + foreach (var megColumn in visualization.MEGColumns) addToDict(megColumn.MEGConfiguration, string.Format("{0} / {1} / {2}", getName(visualization), getName(megColumn), getType(megColumn.MEGConfiguration))); + } + // Check unicity and return error string + Dictionary>> problematicData = new Dictionary>>(); + foreach (var kv in dataByID) if (kv.Value.Count > 1) problematicData.Add(kv.Key, kv.Value); + return problematicData; + } public IEnumerator c_Load(ProjectInfo projectInfo, Action onChangeProgress) { diff --git a/Assets/Scripts/HBP/Core/Data/Project/ProjectInfo.cs b/Assets/Scripts/HBP/Core/Data/Project/ProjectInfo.cs index 1ba9c9cc9..d63b069fe 100644 --- a/Assets/Scripts/HBP/Core/Data/Project/ProjectInfo.cs +++ b/Assets/Scripts/HBP/Core/Data/Project/ProjectInfo.cs @@ -2,6 +2,7 @@ using Ionic.Zip; using HBP.Core.Exceptions; using HBP.Core.Tools; +using UnityEngine; namespace HBP.Core.Data { @@ -64,7 +65,16 @@ public ProjectInfo(string path) : base() FileInfo settingsFile = new FileInfo(System.IO.Path.Combine(ApplicationState.TMPFolder, entry.FileName)); if (settingsFile.Exists) settingsFile.Delete(); entry.Extract(ApplicationState.TMPFolder); - Settings = ClassLoaderSaver.LoadFromJson(settingsFile.FullName); + try + { + Settings = ClassLoaderSaver.LoadFromJson(settingsFile.FullName); + } + catch (System.Exception e) + { + Debug.LogException(e); + Settings = new ProjectPreferences(System.IO.Path.GetFileNameWithoutExtension(path)); + Settings.CanLoadProject = false; + } settingsFile.Directory.Delete(true); } } diff --git a/Assets/Scripts/HBP/Core/Data/Project/ProjectPreferences.cs b/Assets/Scripts/HBP/Core/Data/Project/ProjectPreferences.cs index 9eee458f9..dd669b1ad 100644 --- a/Assets/Scripts/HBP/Core/Data/Project/ProjectPreferences.cs +++ b/Assets/Scripts/HBP/Core/Data/Project/ProjectPreferences.cs @@ -47,6 +47,7 @@ public ReadOnlyCollection Tags [IgnoreDataMember] public static string DefaultName = "New Project"; [IgnoreDataMember] public static string DefaultPatientDatabase = ""; [IgnoreDataMember] public static string DefaultLocalizerDatabase = ""; + [IgnoreDataMember] public bool CanLoadProject = true; #endregion #region Constructors diff --git a/Assets/Scripts/HBP/Core/Data/Visualization/Columns/AnatomicColumn.cs b/Assets/Scripts/HBP/Core/Data/Visualization/Columns/AnatomicColumn.cs index 3d7fef63f..857b04e30 100644 --- a/Assets/Scripts/HBP/Core/Data/Visualization/Columns/AnatomicColumn.cs +++ b/Assets/Scripts/HBP/Core/Data/Visualization/Columns/AnatomicColumn.cs @@ -29,6 +29,17 @@ public AnatomicColumn(string name, BaseConfiguration baseConfiguration, Anatomic #endregion #region Public Methods + public override void GenerateID() + { + base.GenerateID(); + AnatomicConfiguration.GenerateID(); + } + public override List GetAllIdentifiable() + { + List IDs = base.GetAllIdentifiable(); + IDs.AddRange(AnatomicConfiguration.GetAllIdentifiable()); + return IDs; + } public override object Clone() { return new AnatomicColumn(Name, BaseConfiguration.Clone() as BaseConfiguration, AnatomicConfiguration.Clone() as AnatomicConfiguration, ID); diff --git a/Assets/Scripts/HBP/Core/Data/Visualization/Columns/CCEPColumn.cs b/Assets/Scripts/HBP/Core/Data/Visualization/Columns/CCEPColumn.cs index 7ef4b4e99..729fbfa8e 100644 --- a/Assets/Scripts/HBP/Core/Data/Visualization/Columns/CCEPColumn.cs +++ b/Assets/Scripts/HBP/Core/Data/Visualization/Columns/CCEPColumn.cs @@ -134,6 +134,17 @@ public CCEPColumn(string name, BaseConfiguration baseConfiguration, IEnumerable< #endregion #region Public Methods + public override void GenerateID() + { + base.GenerateID(); + DynamicConfiguration.GenerateID(); + } + public override List GetAllIdentifiable() + { + List IDs = base.GetAllIdentifiable(); + IDs.AddRange(DynamicConfiguration.GetAllIdentifiable()); + return IDs; + } public override bool IsCompatible(IEnumerable patients) { CCEPDataInfo[] ccepDataInfos = Dataset?.GetCCEPDataInfos(); @@ -143,11 +154,6 @@ public override void Unload() { Data.Unload(); } - public override void GenerateID() - { - base.GenerateID(); - DynamicConfiguration.GenerateID(); - } #endregion #region Operators diff --git a/Assets/Scripts/HBP/Core/Data/Visualization/Columns/Column.cs b/Assets/Scripts/HBP/Core/Data/Visualization/Columns/Column.cs index 9b7d1884b..780a01b34 100644 --- a/Assets/Scripts/HBP/Core/Data/Visualization/Columns/Column.cs +++ b/Assets/Scripts/HBP/Core/Data/Visualization/Columns/Column.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using HBP.Core.Interfaces; +using System.Collections.Generic; using System.Runtime.Serialization; namespace HBP.Core.Data @@ -13,7 +14,7 @@ namespace HBP.Core.Data * \detail Visualization column is a class which contains the base information of the visualization column. */ [DataContract] - public abstract class Column : BaseData + public abstract class Column : BaseData, INameable { #region Properties /// diff --git a/Assets/Scripts/HBP/Core/Data/Visualization/Columns/FMRIColumn.cs b/Assets/Scripts/HBP/Core/Data/Visualization/Columns/FMRIColumn.cs index 902bd66e7..a820b8674 100644 --- a/Assets/Scripts/HBP/Core/Data/Visualization/Columns/FMRIColumn.cs +++ b/Assets/Scripts/HBP/Core/Data/Visualization/Columns/FMRIColumn.cs @@ -61,6 +61,17 @@ public FMRIColumn(string name, BaseConfiguration baseConfiguration, Dataset data #endregion #region Public Methods + public override void GenerateID() + { + base.GenerateID(); + FMRIConfiguration.GenerateID(); + } + public override List GetAllIdentifiable() + { + List IDs = base.GetAllIdentifiable(); + IDs.AddRange(FMRIConfiguration.GetAllIdentifiable()); + return IDs; + } public override object Clone() { return new FMRIColumn(Name, BaseConfiguration.Clone() as BaseConfiguration, Dataset, FMRIConfiguration.Clone() as FMRIConfiguration, ID); diff --git a/Assets/Scripts/HBP/Core/Data/Visualization/Columns/IEEGColumn.cs b/Assets/Scripts/HBP/Core/Data/Visualization/Columns/IEEGColumn.cs index 46389d882..be587ff28 100644 --- a/Assets/Scripts/HBP/Core/Data/Visualization/Columns/IEEGColumn.cs +++ b/Assets/Scripts/HBP/Core/Data/Visualization/Columns/IEEGColumn.cs @@ -134,6 +134,17 @@ public IEEGColumn(string name, BaseConfiguration baseConfiguration, IEnumerable< #endregion #region Public Methods + public override void GenerateID() + { + base.GenerateID(); + DynamicConfiguration.GenerateID(); + } + public override List GetAllIdentifiable() + { + List IDs = base.GetAllIdentifiable(); + IDs.AddRange(DynamicConfiguration.GetAllIdentifiable()); + return IDs; + } public override bool IsCompatible(IEnumerable patients) { IEEGDataInfo[] iEEGDataInfos = Dataset?.GetIEEGDataInfos(); @@ -143,11 +154,6 @@ public override void Unload() { Data.Unload(); } - public override void GenerateID() - { - base.GenerateID(); - DynamicConfiguration.GenerateID(); - } #endregion #region Operators diff --git a/Assets/Scripts/HBP/Core/Data/Visualization/Columns/MEGColumn.cs b/Assets/Scripts/HBP/Core/Data/Visualization/Columns/MEGColumn.cs index 25b93970e..1fc32847d 100644 --- a/Assets/Scripts/HBP/Core/Data/Visualization/Columns/MEGColumn.cs +++ b/Assets/Scripts/HBP/Core/Data/Visualization/Columns/MEGColumn.cs @@ -61,6 +61,17 @@ public MEGColumn(string name, BaseConfiguration baseConfiguration, Dataset datas #endregion #region Public Methods + public override void GenerateID() + { + base.GenerateID(); + MEGConfiguration.GenerateID(); + } + public override List GetAllIdentifiable() + { + List IDs = base.GetAllIdentifiable(); + IDs.AddRange(MEGConfiguration.GetAllIdentifiable()); + return IDs; + } public override object Clone() { return new MEGColumn(Name, BaseConfiguration.Clone() as BaseConfiguration, Dataset, MEGConfiguration.Clone() as MEGConfiguration, ID); diff --git a/Assets/Scripts/HBP/Core/Data/Visualization/Visualization.cs b/Assets/Scripts/HBP/Core/Data/Visualization/Visualization.cs index 26ac886fb..8e445feb7 100644 --- a/Assets/Scripts/HBP/Core/Data/Visualization/Visualization.cs +++ b/Assets/Scripts/HBP/Core/Data/Visualization/Visualization.cs @@ -418,8 +418,6 @@ IEnumerator c_LoadData(Dictionary> dataInfoByColum yield return Ninja.JumpBack; Exception exception = null; - string additionalInformation = ""; - IEnumerable dataInfoCollection = dataInfoByColumn.SelectMany(d => d.Value).Distinct(); int count = 0; int length = dataInfoCollection.Count(); @@ -441,16 +439,14 @@ IEnumerator c_LoadData(Dictionary> dataInfoByColum { if(epochedData.DataByBloc.TryGetValue(iEEGColumn.Bloc, out BlocData blocData) && !blocData.IsValid) { - additionalInformation = "No bloc " + iEEGColumn.Bloc.Name + " could be epoched."; - throw new Exception(); + throw new Exception("No bloc " + iEEGColumn.Bloc.Name + " could be epoched."); } } else if (column is CCEPColumn ccepColumn) { if (epochedData.DataByBloc.TryGetValue(ccepColumn.Bloc, out BlocData blocData) && !blocData.IsValid) { - additionalInformation = "No bloc " + ccepColumn.Bloc.Name + " could be epoched."; - throw new Exception(); + throw new Exception("No bloc " + ccepColumn.Bloc.Name + " could be epoched."); } } } @@ -458,15 +454,14 @@ IEnumerator c_LoadData(Dictionary> dataInfoByColum } catch (CannotEpochAllTrialsException e) { - additionalInformation = string.Format("You are trying to epoch a bloc from index {0} to index {1} while the minimum possible index is {2} and the maximum possible index is {3}.", e.StartIndex, e.EndIndex, 0, e.Length); UnityEngine.Debug.LogException(e); - exception = new CannotLoadDataInfoException(string.Format("{0} ({1})", dataInfo.Name, dataInfo.Dataset.Name), (dataInfo is PatientDataInfo pDataInfo ? pDataInfo.Patient.Name : "Unkwown patient"), additionalInformation); + exception = new CannotLoadDataInfoException(string.Format("{0} ({1})", dataInfo.Name, dataInfo.Dataset.Name), (dataInfo is PatientDataInfo pDataInfo ? pDataInfo.Patient.Name : "Unkwown patient"), string.Format("You are trying to epoch a bloc from index {0} to index {1} while the minimum possible index is {2} and the maximum possible index is {3}.", e.StartIndex, e.EndIndex, 0, e.Length)); break; } catch (Exception e) { UnityEngine.Debug.LogException(e); - exception = new CannotLoadDataInfoException(string.Format("{0} ({1})", dataInfo.Name, dataInfo.Dataset.Name), (dataInfo is PatientDataInfo pDataInfo ? pDataInfo.Patient.Name : "Unkwown patient"), additionalInformation); + exception = new CannotLoadDataInfoException(string.Format("{0} ({1})", dataInfo.Name, dataInfo.Dataset.Name), (dataInfo is PatientDataInfo pDataInfo ? pDataInfo.Patient.Name : "Unkwown patient"), e.Message); break; } count++; diff --git a/Assets/Scripts/HBP/Core/Exceptions.cs b/Assets/Scripts/HBP/Core/Exceptions.cs index 94232bc7d..85d7ad0ac 100644 --- a/Assets/Scripts/HBP/Core/Exceptions.cs +++ b/Assets/Scripts/HBP/Core/Exceptions.cs @@ -43,7 +43,7 @@ protected CannotFindDataInfoException( public class CannotLoadDataInfoException : HBPException { public CannotLoadDataInfoException() { } - public CannotLoadDataInfoException(string data, string patient, string additionalInformation = "") : base("Can not load " + data + " for " + patient + ".\n\n" + additionalInformation + "\n\nPlease check your data files.") + public CannotLoadDataInfoException(string data, string patient, string additionalInformation = "") : base("Can not load " + data + " for " + patient + ".\nException thrown: " + additionalInformation + "\n\nPlease check your data files.") { Title = "Data can not be loaded"; } diff --git a/Assets/Scripts/HBP/Core/Tools/ClassLoaderSaver.cs b/Assets/Scripts/HBP/Core/Tools/ClassLoaderSaver.cs index 89a3fd5cf..5ba95f384 100644 --- a/Assets/Scripts/HBP/Core/Tools/ClassLoaderSaver.cs +++ b/Assets/Scripts/HBP/Core/Tools/ClassLoaderSaver.cs @@ -11,50 +11,20 @@ public static class ClassLoaderSaver public static T LoadFromXML(string path) where T : new() { T result = new T(); - try - { - using (StreamReader streamReader = new StreamReader(path)) - { - XmlSerializer serializer = new XmlSerializer(typeof(T)); - result = (T)serializer.Deserialize(streamReader.BaseStream); - streamReader.Close(); - } - } - catch (Exception e) + using (StreamReader streamReader = new StreamReader(path)) { - Debug.LogException(e); + XmlSerializer serializer = new XmlSerializer(typeof(T)); + result = (T)serializer.Deserialize(streamReader.BaseStream); + streamReader.Close(); } return result; } public static T LoadFromJson(string path) where T : new() { T result = new T(); - try - { - using (StreamReader streamReader = new StreamReader(path)) - { - result = JsonConvert.DeserializeObject(streamReader.ReadToEnd(), new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.Auto }); - } - } - catch (Exception e) - { - Debug.LogException(e); - } - return result; - } - public static T LoadFromJson2(string path) where T : new() - { - T result = new T(); - try + using (StreamReader streamReader = new StreamReader(path)) { - using (StreamReader streamReader = new StreamReader(path)) - { - result = JsonConvert.DeserializeObject(streamReader.ReadToEnd(), new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.Auto }); - } - } - catch (Exception e) - { - Debug.LogException(e); + result = JsonConvert.DeserializeObject(streamReader.ReadToEnd(), new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.Auto }); } return result; } diff --git a/Assets/Scripts/HBP/Data/Module3D/Base3DScene.cs b/Assets/Scripts/HBP/Data/Module3D/Base3DScene.cs index f052de7ef..bb9b8f669 100644 --- a/Assets/Scripts/HBP/Data/Module3D/Base3DScene.cs +++ b/Assets/Scripts/HBP/Data/Module3D/Base3DScene.cs @@ -1733,7 +1733,7 @@ public void PassiveRaycastOnScene(Ray ray, Column3D column) RaycastHitResult raycastResult = column.Raycast(ray, layerMask, out RaycastHit hit); Vector3 hitPoint = raycastResult != RaycastHitResult.None ? hit.point - transform.position : Vector3.zero; - m_AtlasManager.DisplayAtlasInformation(raycastResult == RaycastHitResult.Cut || raycastResult == RaycastHitResult.Mesh, hitPoint); + m_AtlasManager.DisplayAtlasInformation((raycastResult == RaycastHitResult.Cut || raycastResult == RaycastHitResult.Mesh) && MeshManager.SelectedMesh.Type == MeshType.MNI, hitPoint); // FIXME when we have hoverable atlases in single patient scenes m_ImplantationManager.DisplaySiteInformation(raycastResult == RaycastHitResult.Site, column, hit); } /// @@ -2262,14 +2262,16 @@ private IEnumerator c_UpdateMeshesColliders() } yield return Ninja.JumpToUnity; m_DisplayedObjects.SimplifiedBrain.GetComponent().sharedMesh = null; - m_DisplayedObjects.SimplifiedBrain.GetComponent().sharedMesh = m_DisplayedObjects.SimplifiedBrain.GetComponent().sharedMesh; + if (m_DisplayedObjects.SimplifiedBrain.GetComponent().sharedMesh.triangles.Length > 0) + m_DisplayedObjects.SimplifiedBrain.GetComponent().sharedMesh = m_DisplayedObjects.SimplifiedBrain.GetComponent().sharedMesh; // update cuts colliders for (int ii = 0; ii < m_DisplayedObjects.BrainCutMeshes.Count; ++ii) { yield return Ninja.JumpToUnity; m_DisplayedObjects.BrainCutMeshes[ii].GetComponent().sharedMesh = null; - m_DisplayedObjects.BrainCutMeshes[ii].GetComponent().sharedMesh = m_DisplayedObjects.BrainCutMeshes[ii].GetComponent().mesh; + if (m_DisplayedObjects.BrainCutMeshes[ii].GetComponent().mesh.triangles.Length > 0) + m_DisplayedObjects.BrainCutMeshes[ii].GetComponent().sharedMesh = m_DisplayedObjects.BrainCutMeshes[ii].GetComponent().mesh; yield return Ninja.JumpBack; } diff --git a/Assets/Scripts/HBP/Data/Module3D/Modules/AtlasManager.cs b/Assets/Scripts/HBP/Data/Module3D/Modules/AtlasManager.cs index 65e5f8a32..77febbaae 100644 --- a/Assets/Scripts/HBP/Data/Module3D/Modules/AtlasManager.cs +++ b/Assets/Scripts/HBP/Data/Module3D/Modules/AtlasManager.cs @@ -167,7 +167,7 @@ public void DisplayAtlasInformation(bool canDisplay, Vector3 hitPoint) string[] information = SelectedAtlas.GetInformation(HoveredArea); if (information.Length == 5) { - Module3DMain.OnDisplayAtlasInformation.Invoke(new AtlasInfo(true, Input.mousePosition, SelectedAtlas is Core.DLL.MarsAtlas ? AtlasInfo.AtlasType.MarsAtlas : AtlasInfo.AtlasType.JuBrainAtlas, information[0] + "(" + HoveredArea + ")", information[1], information[2], information[3], information[4])); + Module3DMain.OnDisplayAtlasInformation.Invoke(new AtlasInfo(true, Input.mousePosition, SelectedAtlas is Core.DLL.MarsAtlas ? AtlasInfo.AtlasType.MarsAtlas : AtlasInfo.AtlasType.JuBrainAtlas, information[0] + " - ID:" + HoveredArea, information[1], information[2], information[3], information[4])); } else { diff --git a/Assets/Scripts/HBP/Data/Preferences/PreferencesManager.cs b/Assets/Scripts/HBP/Data/Preferences/PreferencesManager.cs index a7c91bfd8..e1073eef0 100644 --- a/Assets/Scripts/HBP/Data/Preferences/PreferencesManager.cs +++ b/Assets/Scripts/HBP/Data/Preferences/PreferencesManager.cs @@ -1,4 +1,5 @@ using HBP.Core.Tools; +using System; using System.IO; using UnityEngine; @@ -27,7 +28,15 @@ private void Awake() if (new FileInfo(UserPreferences.PATH).Exists) { - m_UserPreferences = ClassLoaderSaver.LoadFromJson(UserPreferences.PATH); + try + { + m_UserPreferences = ClassLoaderSaver.LoadFromJson(UserPreferences.PATH); + } + catch (Exception e) + { + Debug.LogException(e); + m_UserPreferences = new UserPreferences(); + } } else { diff --git a/Assets/Scripts/HBP/UI/Main/File/ProjectItem.cs b/Assets/Scripts/HBP/UI/Main/File/ProjectItem.cs index 69a7d8de4..3f8077c13 100644 --- a/Assets/Scripts/HBP/UI/Main/File/ProjectItem.cs +++ b/Assets/Scripts/HBP/UI/Main/File/ProjectItem.cs @@ -41,6 +41,7 @@ public override Core.Data.ProjectInfo Object m_ProtocolsText.SetIEnumerableFieldInItem(value.Protocols, m_EmptyState); m_DatasetsText.SetIEnumerableFieldInItem(value.Datasets, m_EmptyState); m_VisualizationsText.SetIEnumerableFieldInItem(value.Visualizations, m_EmptyState); + Interactable = value.Settings.CanLoadProject; } } #endregion diff --git a/Assets/Scripts/HBP/UI/Module3D/Cuts/CutParametersController.cs b/Assets/Scripts/HBP/UI/Module3D/Cuts/CutParametersController.cs index 34d3e3a08..f8f3bf166 100644 --- a/Assets/Scripts/HBP/UI/Module3D/Cuts/CutParametersController.cs +++ b/Assets/Scripts/HBP/UI/Module3D/Cuts/CutParametersController.cs @@ -193,7 +193,7 @@ private void AddListeners() Cut.OnUpdateGUITextures.AddListener(() => { Destroy(m_Image.sprite); - Texture2D texture = Module3DMain.SelectedColumn.CutTextures.GUIBrainCutTextures[Cut.ID]; + Texture2D texture = m_Scene.SelectedColumn.CutTextures.GUIBrainCutTextures[Cut.ID]; m_Image.sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0, 0)); m_Image.sprite.texture.filterMode = FilterMode.Trilinear; m_Image.sprite.texture.anisoLevel = 9; diff --git a/Assets/Scripts/HBP/UI/Module3D/Sites/AdvancedSiteConditions.cs b/Assets/Scripts/HBP/UI/Module3D/Sites/AdvancedSiteConditions.cs index 74cdee072..5330626b2 100644 --- a/Assets/Scripts/HBP/UI/Module3D/Sites/AdvancedSiteConditions.cs +++ b/Assets/Scripts/HBP/UI/Module3D/Sites/AdvancedSiteConditions.cs @@ -26,6 +26,7 @@ public class AdvancedSiteConditions : BaseSiteConditions public const string IN_LEFT_HEMISPHERE = "L"; public const string IN_RIGHT_HEMISPHERE = "R"; public const string ON_PLANE = "CUT"; + public const string ATLAS_AREA = "ATLAS_AREA"; public const string NAME = "NAME"; public const string PATIENT_NAME = "PAT_NAME"; public const string PATIENT_PLACE = "PAT_PLACE"; @@ -113,6 +114,10 @@ private bool ParseConditionAndCheckValue(Core.Object3D.Site site, string s) { return CheckPatientDate(site, deblankedValue); } + else if (label == ATLAS_AREA) + { + return CheckAtlas(site, deblankedValue); + } else if (label == TAG) { string[] splits = deblankedValue.Split(':'); diff --git a/Assets/Scripts/HBP/UI/Module3D/Sites/BaseSiteConditions.cs b/Assets/Scripts/HBP/UI/Module3D/Sites/BaseSiteConditions.cs index d9e80e45a..715956f36 100644 --- a/Assets/Scripts/HBP/UI/Module3D/Sites/BaseSiteConditions.cs +++ b/Assets/Scripts/HBP/UI/Module3D/Sites/BaseSiteConditions.cs @@ -143,6 +143,44 @@ protected bool CheckOnPlane(Core.Object3D.Site site) return m_Scene.ImplantationManager.SelectedImplantation.RawSiteList.IsSiteOnAnyPlane(site, from cut in m_Scene.Cuts select cut as Core.Object3D.Plane, 1.0f); } /// + /// Check if the site is in a specific area of the selected atlas + /// + /// Site to check + /// Name to use for the checking + /// True if the site is in the specified area of the selected atlas + protected bool CheckAtlas(Core.Object3D.Site site, string areaName) + { + if (m_Scene.AtlasManager.SelectedAtlas != null) + { + int areaID = m_Scene.AtlasManager.SelectedAtlas.GetClosestAreaIndex(site.Information.DefaultPosition); + if (int.TryParse(areaName, out int comparedID)) + { + if (areaID == comparedID) return true; + } + string[] areaInformation = m_Scene.AtlasManager.SelectedAtlas.GetInformation(areaID); + if (areaInformation.Length == 5) + { + if (m_Scene.AtlasManager.SelectedAtlas is MarsAtlas) + { + // Check in name + if (areaInformation[0].ToUpper().Contains(areaName.ToUpper())) return true; + // Check in full name + if (areaInformation[4].ToUpper().Contains(areaName.ToUpper())) return true; + } + else + { + // Check in region + if (areaInformation[0].ToUpper().Contains(areaName.ToUpper())) return true; + // Check in location + if (areaInformation[1].ToUpper().Contains(areaName.ToUpper())) return true; + // Check in area label + if (areaInformation[2].ToUpper().Contains(areaName.ToUpper())) return true; + } + } + } + return false; + } + /// /// Check if the site name contains the input string /// /// Site to check @@ -156,7 +194,7 @@ protected bool CheckName(Core.Object3D.Site site, string name) /// Check if the site patient name contains the input string /// /// Site to check - /// Name to use for the checking + /// Name to use for the checking /// True if the site patient name contains the input string protected bool CheckPatientName(Core.Object3D.Site site, string patientName) { diff --git a/Assets/Scripts/HBP/UI/Module3D/Sites/BasicSiteConditions.cs b/Assets/Scripts/HBP/UI/Module3D/Sites/BasicSiteConditions.cs index 08600217b..e5cb12d0d 100644 --- a/Assets/Scripts/HBP/UI/Module3D/Sites/BasicSiteConditions.cs +++ b/Assets/Scripts/HBP/UI/Module3D/Sites/BasicSiteConditions.cs @@ -29,6 +29,8 @@ public class BasicSiteConditions : BaseSiteConditions [SerializeField] Toggle m_RightHemisphere; [SerializeField] Toggle m_OnPlane; [SerializeField] Toggle m_NotOnPlane; + [SerializeField] Toggle m_Atlas; + [SerializeField] InputField m_AtlasFilter; // Information [SerializeField] Toggle m_SiteName; @@ -124,6 +126,7 @@ private bool CheckPosition(Core.Object3D.Site site) if (m_RightHemisphere.isOn) result &= CheckInRightHemisphere(site); if (m_OnPlane.isOn) result &= CheckOnPlane(site); if (m_NotOnPlane.isOn) result &= !CheckOnPlane(site); + if (m_Atlas.isOn) result &= CheckAtlas(site, m_AtlasFilter.text); return result; } /// diff --git a/Assets/Scripts/HBP/UI/Module3D/Sites/SiteActions.cs b/Assets/Scripts/HBP/UI/Module3D/Sites/SiteActions.cs index 6ab02dcd7..2ebc9c83e 100644 --- a/Assets/Scripts/HBP/UI/Module3D/Sites/SiteActions.cs +++ b/Assets/Scripts/HBP/UI/Module3D/Sites/SiteActions.cs @@ -1,15 +1,15 @@ -using ThirdParty.CielaSpike; +using HBP.Core.Data; +using HBP.Core.Tools; +using HBP.Data.Module3D; +using HBP.UI.Tools; using System; using System.Collections; using System.Collections.Generic; using System.Linq; +using ThirdParty.CielaSpike; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; -using HBP.Core.Data; -using HBP.Data.Module3D; -using HBP.UI.Tools; -using HBP.Core.Tools; namespace HBP.UI.Module3D { @@ -23,15 +23,6 @@ public class SiteActions : MonoBehaviour /// Associated 3D scene /// private Base3DScene m_Scene; - /// - /// Currently computing coroutine (for the export of the sites to a csv file) - /// - private Coroutine m_Coroutine; - - /// - /// Progress bar used to display a feedback when filtering or applying an action - /// - [SerializeField] private SiteConditionsProgressBar m_ProgressBar; /// /// Toggle used to display or hide the actions panel @@ -107,28 +98,31 @@ public class SiteActions : MonoBehaviour /// Toggle to choose to apply the modifications in the states of the filtered sites to the selected column or to all columns at once /// [SerializeField] private Toggle m_AllColumnsToggle; + /// + /// Button to trigger the application of the action + /// + [SerializeField] private Button m_ApplyChangesButton; /// - /// Toggle to specify that the action to be apply is an export to a csv file + /// Button to specify that the action to be apply is an export to a csv file /// - [SerializeField] private Toggle m_ExportSitesToggle; + [SerializeField] private Button m_ExportSitesButton; /// - /// Toggle to specify that the action to be apply is a group creation + /// Button to specify that the action to be apply is a group creation /// - [SerializeField] private Toggle m_CreateGroupToggle; + [SerializeField] private Button m_CreateGroupButton; /// - /// Inputfield to specify the name of the newly created group + /// Button to specify that the action to be apply is a graph display /// - [SerializeField] private InputField m_GroupNameInputField; + [SerializeField] private Button m_DisplayGraphsButton; /// - /// Toggle to specify that the action to be apply is a graph display + /// Currently computing coroutine (for the export of the sites to a csv file) /// - [SerializeField] private Toggle m_DisplayGraphsToggle; - + private Coroutine m_Coroutine; /// - /// Button to trigger the application of the action + /// Progress bar used to display a feedback when filtering or applying an action /// - [SerializeField] private Button m_ApplyButton; + [SerializeField] private SiteConditionsProgressBar m_ExportSitesProgressBar; /// /// Do we need an update in the progress bar ? @@ -159,33 +153,7 @@ public void ApplyAction() { try { - if (m_ChangeStateToggle.isOn) - { - ChangeSitesStates(); - } - else if (m_OtherToggle.isOn) - { - if (m_ExportSitesToggle.isOn) - { - if (m_Coroutine != null) - { - StopCoroutine(m_Coroutine); - StopExport(); - } - else - { - ExportSites(); - } - } - else if (m_CreateGroupToggle.isOn) - { - CreateGroup(); - } - else if (m_DisplayGraphsToggle.isOn) - { - DisplayGraphs(); - } - } + ChangeSitesStates(); } catch (Exception e) { @@ -201,7 +169,10 @@ private void Awake() m_OnOffToggle.onValueChanged.AddListener(m_ActionsPanel.gameObject.SetActive); m_ChangeStateToggle.onValueChanged.AddListener(m_ChangeStatePanel.SetActive); m_OtherToggle.onValueChanged.AddListener(m_OtherPanel.SetActive); - m_ApplyButton.onClick.AddListener(ApplyAction); + m_ApplyChangesButton.onClick.AddListener(ApplyAction); + m_CreateGroupButton.onClick.AddListener(CreateGroup); + m_DisplayGraphsButton.onClick.AddListener(DisplayGraphs); + m_ExportSitesButton.onClick.AddListener(ExportSites); m_ColorPickerButton.onClick.AddListener(() => { @@ -210,7 +181,6 @@ private void Awake() m_AddLabelToggle.onValueChanged.AddListener(isOn => m_LabelInputField.interactable = m_AddLabelToggle.isOn || m_RemoveLabelToggle.isOn); m_RemoveLabelToggle.onValueChanged.AddListener(isOn => m_LabelInputField.interactable = m_AddLabelToggle.isOn || m_RemoveLabelToggle.isOn); m_ColorToggle.onValueChanged.AddListener(isOn => m_ColorPickerButton.interactable = isOn); - m_CreateGroupToggle.onValueChanged.AddListener(isOn => m_GroupNameInputField.interactable = isOn); } private void Update() { @@ -253,23 +223,31 @@ private void ChangeSitesStates() /// private void ExportSites() { -#if UNITY_STANDALONE_OSX - FileBrowser.GetSavedFileNameAsync((csvPath) => + if (m_Coroutine != null) + { + StopCoroutine(m_Coroutine); + StopExport(); + } + else { - if (string.IsNullOrEmpty(csvPath)) return; +#if UNITY_STANDALONE_OSX + FileBrowser.GetSavedFileNameAsync((csvPath) => + { + if (string.IsNullOrEmpty(csvPath)) return; - m_ProgressBar.Begin(); - List sites = m_Scene.SelectedColumn.Sites.Where(s => s.State.IsFiltered).ToList(); - m_Coroutine = this.StartCoroutineAsync(c_ExportSites(sites, csvPath)); - }, new string[] { "csv" }, "Save sites to"); + m_ExportSitesProgressBar.Begin(); + List sites = m_Scene.SelectedColumn.Sites.Where(s => s.State.IsFiltered).ToList(); + m_Coroutine = this.StartCoroutineAsync(c_ExportSites(sites, csvPath)); + }, new string[] { "csv" }, "Save sites to"); #else string csvPath = FileBrowser.GetSavedFileName(new string[] { "csv" }, "Save sites to"); if (string.IsNullOrEmpty(csvPath)) return; - m_ProgressBar.Begin(); + m_ExportSitesProgressBar.Begin(); List sites = m_Scene.SelectedColumn.Sites.Where(s => s.State.IsFiltered).ToList(); m_Coroutine = this.StartCoroutineAsync(c_ExportSites(sites, csvPath)); #endif + } } /// /// Create a group from all patients of filtered sites @@ -277,22 +255,26 @@ private void ExportSites() private void CreateGroup() { var patients = m_Scene.SelectedColumn.Sites.Where(s => s.State.IsFiltered).Select(s => s.Information.Patient).Distinct(); - Group group = new Group(m_GroupNameInputField.text, patients); - // Generate unique name - var projectGroups = ApplicationState.ProjectLoaded.Groups; - if (projectGroups.Any(g => g.Name == group.Name)) + Group group = new Group("New group", patients); + ObjectModifier modifier = WindowsManager.OpenModifier(group); + modifier.OnOk.AddListener(() => { - int count = 1; - string name = string.Format("{0}({1})", group.Name, count); - while (projectGroups.Any(g => g.Name == name)) + // Generate unique name + var projectGroups = ApplicationState.ProjectLoaded.Groups; + if (projectGroups.Any(g => g.Name == group.Name)) { - count++; - name = string.Format("{0}({1})", group.Name, count); + int count = 1; + string name = string.Format("{0}({1})", group.Name, count); + while (projectGroups.Any(g => g.Name == name)) + { + count++; + name = string.Format("{0}({1})", group.Name, count); + } + group.Name = name; } - group.Name = name; - } - ApplicationState.ProjectLoaded.AddGroup(group); - DialogBoxManager.Open(DialogBoxManager.AlertType.Informational, "Group added to project", string.Format("The group {0} containing the {1} patients of the filtered sites has been added to the project.", group.Name, patients.Count())); + ApplicationState.ProjectLoaded.AddGroup(group); + DialogBoxManager.Open(DialogBoxManager.AlertType.Informational, "Group added to project", string.Format("The group {0} containing the {1} patients of the filtered sites has been added to the project.", group.Name, patients.Count())); + }); } /// /// Cancel the export of the filtered sites @@ -300,7 +282,7 @@ private void CreateGroup() private void StopExport() { m_Coroutine = null; - m_ProgressBar.End(); + m_ExportSitesProgressBar.End(); } private void DisplayGraphs() { @@ -341,7 +323,7 @@ private IEnumerator c_ExportSites(List sites, string csvPath if (m_UpdateUI || i == length - 1) { yield return Ninja.JumpToUnity; - m_ProgressBar.Progress(0.5f * ((float)(i + 1) / length)); + m_ExportSitesProgressBar.Progress(0.5f * ((float)(i + 1) / length)); m_UpdateUI = false; yield return Ninja.JumpBack; } @@ -440,7 +422,7 @@ private IEnumerator c_ExportSites(List sites, string csvPath if (m_UpdateUI || i == length - 1) { yield return Ninja.JumpToUnity; - m_ProgressBar.Progress(0.5f * (1 + (float)(i + 1) / length)); + m_ExportSitesProgressBar.Progress(0.5f * (1 + (float)(i + 1) / length)); m_UpdateUI = false; yield return Ninja.JumpBack; } diff --git a/Assets/Scripts/HBP/UI/Module3D/Sites/SiteLabels.cs b/Assets/Scripts/HBP/UI/Module3D/Sites/SiteLabels.cs index 127406383..92462791c 100644 --- a/Assets/Scripts/HBP/UI/Module3D/Sites/SiteLabels.cs +++ b/Assets/Scripts/HBP/UI/Module3D/Sites/SiteLabels.cs @@ -70,7 +70,7 @@ public void Initialize(Core.Object3D.Site site) return; } - List labels = Module3DMain.SelectedColumn.Sites.SelectMany(s => s.State.Labels).Distinct().ToList(); + List labels = Module3DMain.Scenes.SelectMany(sc => sc.Columns.SelectMany(c => c.Sites.SelectMany(s => s.State.Labels))).Distinct().ToList(); string existingLabel = labels.Find(s => s.StartsWith(text)); if (!string.IsNullOrEmpty(existingLabel)) { diff --git a/Assets/Scripts/HBP/UI/Module3D/Sites/SitesInformations.cs b/Assets/Scripts/HBP/UI/Module3D/Sites/SitesInformations.cs index 923c51109..c8ddf6641 100644 --- a/Assets/Scripts/HBP/UI/Module3D/Sites/SitesInformations.cs +++ b/Assets/Scripts/HBP/UI/Module3D/Sites/SitesInformations.cs @@ -1,5 +1,7 @@ using HBP.Data.Module3D; +using HBP.UI.Tools; using HBP.UI.Tools.ResizableGrids; +using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEngine.UI; @@ -19,7 +21,14 @@ public class SitesInformations : MonoBehaviour [SerializeField] private Toggle m_SiteActionsToggle; [SerializeField] private SiteActions m_SiteActions; [SerializeField] private GameObject m_MinimizedGameObject; - + + [SerializeField] private Tooltip m_SiteTooltip; + [SerializeField] private Tooltip m_PatientsTooltip; + [SerializeField] private Tooltip m_LabelsTooltip; + [SerializeField] private Tooltip m_HighlightedTooltip; + [SerializeField] private Tooltip m_BlacklistedTooltip; + [SerializeField] private Tooltip m_ColorTooltip; + public bool IsMinimized { get @@ -83,6 +92,50 @@ public void Initialize(Base3DScene scene) UpdateList(); m_SiteList.ScrollToObject(s); }); + m_SiteTooltip.OnBeforeDisplayTooltip.AddListener(() => + { + m_SiteTooltip.Text = string.Format("Number of sites: {0}", m_SiteList.Objects.Count); + }); + m_PatientsTooltip.OnBeforeDisplayTooltip.AddListener(() => + { + m_PatientsTooltip.Text = string.Format("Number of distinct patients: {0}", m_SiteList.Objects.Select(s => s.Information.Patient).Distinct().Count()); + }); + m_LabelsTooltip.OnBeforeDisplayTooltip.AddListener(() => + { + string labelsTooltip = "Number of sites with"; + Dictionary countByNumberOfLabels = new Dictionary(); + foreach (var site in m_SiteList.Objects) + { + if (!countByNumberOfLabels.ContainsKey(site.State.Labels.Count)) + { + countByNumberOfLabels.Add(site.State.Labels.Count, 1); + } + else + { + countByNumberOfLabels[site.State.Labels.Count]++; + } + } + foreach (var kv in countByNumberOfLabels) + { + if (kv.Key == 1) + labelsTooltip += string.Format("\n{0} label: {1}", kv.Key, kv.Value); + else + labelsTooltip += string.Format("\n{0} labels: {1}", kv.Key, kv.Value); + } + m_LabelsTooltip.Text = labelsTooltip; + }); + m_HighlightedTooltip.OnBeforeDisplayTooltip.AddListener(() => + { + m_HighlightedTooltip.Text = string.Format("Number of highlighted sites: {0}", m_SiteList.Objects.Count(s => s.State.IsHighlighted)); + }); + m_BlacklistedTooltip.OnBeforeDisplayTooltip.AddListener(() => + { + m_BlacklistedTooltip.Text = string.Format("Number of blacklisted sites: {0}", m_SiteList.Objects.Count(s => s.State.IsBlackListed)); + }); + m_ColorTooltip.OnBeforeDisplayTooltip.AddListener(() => + { + m_ColorTooltip.Text = string.Format("Number of distinct colors: {0}", m_SiteList.Objects.Select(s => s.State.Color).Distinct().Count()); + }); foreach (var column in m_Scene.Columns) { column.OnSelect.AddListener(SetList); diff --git a/Assets/Scripts/HBP/UI/Toolbar/ROI/ROIExport.cs b/Assets/Scripts/HBP/UI/Toolbar/ROI/ROIExport.cs index 6d4c1ac0e..4a62badae 100644 --- a/Assets/Scripts/HBP/UI/Toolbar/ROI/ROIExport.cs +++ b/Assets/Scripts/HBP/UI/Toolbar/ROI/ROIExport.cs @@ -2,6 +2,7 @@ using UnityEngine; using UnityEngine.UI; using HBP.UI.Tools; +using System; namespace HBP.UI.Toolbar { @@ -54,11 +55,19 @@ private void LoadROI() { if (!string.IsNullOrEmpty(loadPath)) { - Core.Data.RegionOfInterest serializedROI = ClassLoaderSaver.LoadFromJson(loadPath); - Core.Object3D.ROI roi = SelectedScene.ROIManager.AddROI(serializedROI.Name); - foreach (Core.Data.Sphere sphere in serializedROI.Spheres) + try { - roi.AddSphere(SelectedColumn.Layer, "Sphere", sphere.Position.ToVector3(), sphere.Radius); + Core.Data.RegionOfInterest serializedROI = ClassLoaderSaver.LoadFromJson(loadPath); + Core.Object3D.ROI roi = SelectedScene.ROIManager.AddROI(serializedROI.Name); + foreach (Core.Data.Sphere sphere in serializedROI.Spheres) + { + roi.AddSphere(SelectedColumn.Layer, "Sphere", sphere.Position.ToVector3(), sphere.Radius); + } + } + catch (Exception e) + { + Debug.LogException(e); + DialogBoxManager.Open(DialogBoxManager.AlertType.Error, "Can not load ROI", "The ROI file you are trying to load is not valid."); } } }, new string[] { "roi" }, "Load ROI file"); @@ -66,11 +75,19 @@ private void LoadROI() string loadPath = FileBrowser.GetExistingFileName(new string[] { "roi" }, "Load ROI file"); if (!string.IsNullOrEmpty(loadPath)) { - Core.Data.RegionOfInterest serializedROI = ClassLoaderSaver.LoadFromJson(loadPath); - Core.Object3D.ROI roi = SelectedScene.ROIManager.AddROI(serializedROI.Name); - foreach (Core.Data.Sphere sphere in serializedROI.Spheres) + try + { + Core.Data.RegionOfInterest serializedROI = ClassLoaderSaver.LoadFromJson(loadPath); + Core.Object3D.ROI roi = SelectedScene.ROIManager.AddROI(serializedROI.Name); + foreach (Core.Data.Sphere sphere in serializedROI.Spheres) + { + roi.AddSphere(SelectedColumn.Layer, "Sphere", sphere.Position.ToVector3(), sphere.Radius); + } + } + catch (Exception e) { - roi.AddSphere(SelectedColumn.Layer, "Sphere", sphere.Position.ToVector3(), sphere.Radius); + Debug.LogException(e); + DialogBoxManager.Open(DialogBoxManager.AlertType.Error, "Can not load ROI", "The ROI file you are trying to load is not valid."); } } #endif diff --git a/Assets/Scripts/HBP/UI/Toolbar/Site/OpenInteractiveViewer.cs b/Assets/Scripts/HBP/UI/Toolbar/Site/OpenInteractiveViewer.cs index d26237b65..b73143c61 100644 --- a/Assets/Scripts/HBP/UI/Toolbar/Site/OpenInteractiveViewer.cs +++ b/Assets/Scripts/HBP/UI/Toolbar/Site/OpenInteractiveViewer.cs @@ -25,9 +25,9 @@ public class OpenInteractiveViewer : Tool private void Open() { // TODO : replace by correct values - Vector3 sitePosition = Module3DMain.SelectedColumn.SelectedSite.transform.localPosition; + Vector3 sitePosition = SelectedColumn.SelectedSite.transform.localPosition; Quaternion quaternion = new Quaternion(-0.3f, 0.7f, -0.5f, 0.2f); - View3D view = Module3DMain.SelectedView; + View3D view = SelectedView; if (view) { quaternion = view.LocalCameraRotation * Quaternion.Euler(0, 180, 0); diff --git a/Assets/Scripts/HBP/UI/Tools/ProjectLoaderSaver.cs b/Assets/Scripts/HBP/UI/Tools/ProjectLoaderSaver.cs index 6a1dedc92..e966759aa 100644 --- a/Assets/Scripts/HBP/UI/Tools/ProjectLoaderSaver.cs +++ b/Assets/Scripts/HBP/UI/Tools/ProjectLoaderSaver.cs @@ -5,6 +5,10 @@ using HBP.Core.Tools; using HBP.Core.Data; using HBP.Data.Module3D; +using System.Collections.Generic; +using HBP.Core.Interfaces; +using System.Linq; +using System; namespace HBP.UI.Tools { @@ -34,6 +38,48 @@ public void Load(ProjectInfo projectInfo) if (taskState == TaskState.Done) { FindObjectOfType().SetInteractables(); + Dictionary>> problematicData = ApplicationState.ProjectLoaded.CheckProjectIDs(); + if (problematicData.Count > 0) + { + string displayedString = ""; + foreach (var kv in problematicData) + { + displayedString += string.Format("{0}\n{1}\n\n", kv.Key, string.Join("\n", kv.Value.Select(t => string.Format(" - {0}", t.Item2)))); + } + Debug.Log(displayedString); + string[] lines = displayedString.Split("\n"); + if (lines.Length > 20) + { + string duplicateFilePath = Path.Combine(ApplicationState.ProjectLoadedLocation, string.Format("{0}_duplicate_IDs.txt", ApplicationState.ProjectLoaded.Preferences.Name)); + displayedString = ""; + for (int i = 0; i < 18; ++i) + { + displayedString += lines[i]; + displayedString += "\n"; + } + displayedString += "[...]\n"; + using (StreamWriter sw = new StreamWriter(duplicateFilePath)) + { + for (int i = 0; i < lines.Length; ++i) + { + sw.WriteLine(lines[i]); + } + } + displayedString += string.Format("\nFull report has been saved at {0}\n\n", duplicateFilePath); + } + DialogBoxManager.Open(DialogBoxManager.AlertType.WarningMultiOptions, "ID issue", string.Format("Some IDs of this project are used by multiple different objects:\n\n{0}You have two options: you can regenerate the IDs of problematic objects automatically, but this can unlink some of your objects (for example, some datasets may not be linked to the right protocol), or you can leave them as is but you may encounter issues and will need to fix the IDs manually later. If you did not unzip the project and modify files using a text editor, please send a bug report.\nWhat do you want to do?", displayedString), + () => + { + foreach (var kv in problematicData) + { + for (int i = 1; i < kv.Value.Count; ++i) + { + kv.Value[i].Item1.GenerateID(); + } + } + DialogBoxManager.Open(DialogBoxManager.AlertType.Informational, "New IDs generated", "New IDs have been generated for duplicates. Do not forget to save the project to keep the new IDs."); + }, "Regenerate IDs", () => { }, "Leave IDs as is"); + } } else { diff --git a/Assets/Scripts/HBP/UI/Tools/Tooltip.cs b/Assets/Scripts/HBP/UI/Tools/Tooltip.cs index 1cee736fa..1a0c4b404 100644 --- a/Assets/Scripts/HBP/UI/Tools/Tooltip.cs +++ b/Assets/Scripts/HBP/UI/Tools/Tooltip.cs @@ -1,4 +1,5 @@ using UnityEngine; +using UnityEngine.Events; using UnityEngine.EventSystems; namespace HBP.UI.Tools @@ -48,6 +49,10 @@ public bool FollowMouse private float m_TimeSinceEntered = 0.0f; #endregion + #region Events + public UnityEvent OnBeforeDisplayTooltip = new UnityEvent(); + #endregion + #region Private Methods private void Update() { @@ -56,6 +61,7 @@ private void Update() m_TimeSinceEntered += Time.deltaTime; if ((m_TimeSinceEntered > TooltipManager.TIME_TO_DISPLAY || (TooltipManager.TooltipHasBeenDisplayedRecently && m_TimeSinceEntered > TooltipManager.TIME_TO_DISPLAY/3)) && !TooltipManager.IsTooltipDisplayed) { + OnBeforeDisplayTooltip.Invoke(); TooltipManager.ShowTooltip(m_Text, m_Image, m_FollowMouse); } if (Input.GetAxis("Mouse X") !=0 && Input.GetAxis("Mouse Y") != 0) diff --git a/Assets/Scripts/HBP/UI/Tools/TooltipManager.cs b/Assets/Scripts/HBP/UI/Tools/TooltipManager.cs index 7b07090cf..09a750655 100644 --- a/Assets/Scripts/HBP/UI/Tools/TooltipManager.cs +++ b/Assets/Scripts/HBP/UI/Tools/TooltipManager.cs @@ -62,6 +62,10 @@ private void Update() { MoveAtMousePosition(); } + if (IsTooltipDisplayed) + { + ClampToCanvas(); + } } private void ClampToCanvas() { @@ -80,7 +84,6 @@ private void ClampToCanvas() private void MoveAtMousePosition() { m_Tooltip.position = Input.mousePosition + m_Offset; - ClampToCanvas(); } #endregion diff --git a/Assets/_Scenes/HiBoP.unity b/Assets/_Scenes/HiBoP.unity index 93b30cc87..33afa6b4d 100644 Binary files a/Assets/_Scenes/HiBoP.unity and b/Assets/_Scenes/HiBoP.unity differ diff --git a/ProjectSettings/ProjectSettings.asset b/ProjectSettings/ProjectSettings.asset index d7afd3b1d..440d67bdb 100644 Binary files a/ProjectSettings/ProjectSettings.asset and b/ProjectSettings/ProjectSettings.asset differ diff --git a/UserSettings/Layouts/default-2021.dwlt b/UserSettings/Layouts/default-2021.dwlt index 82cb8aa52..22bbd4bde 100644 --- a/UserSettings/Layouts/default-2021.dwlt +++ b/UserSettings/Layouts/default-2021.dwlt @@ -19,12 +19,39 @@ MonoBehaviour: width: 2560 height: 1357 m_ShowMode: 4 - m_Title: Console - m_RootView: {fileID: 2} + m_Title: Game + m_RootView: {fileID: 3} m_MinSize: {x: 875, y: 300} m_MaxSize: {x: 10000, y: 10000} m_Maximized: 1 --- !u!114 &2 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0} + m_Name: ConsoleWindow + m_EditorClassIdentifier: + m_Children: [] + m_Position: + serializedVersion: 2 + x: 1054 + y: 0 + width: 1083 + height: 332 + m_MinSize: {x: 102, y: 121} + m_MaxSize: {x: 4002, y: 4021} + m_ActualView: {fileID: 18} + m_Panes: + - {fileID: 18} + - {fileID: 19} + m_Selected: 0 + m_LastSelected: 1 +--- !u!114 &3 MonoBehaviour: m_ObjectHideFlags: 52 m_CorrespondingSourceObject: {fileID: 0} @@ -37,9 +64,9 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: m_Children: - - {fileID: 3} - - {fileID: 5} - {fileID: 4} + - {fileID: 6} + - {fileID: 5} m_Position: serializedVersion: 2 x: 0 @@ -52,7 +79,7 @@ MonoBehaviour: m_TopViewHeight: 30 m_UseBottomView: 1 m_BottomViewHeight: 20 ---- !u!114 &3 +--- !u!114 &4 MonoBehaviour: m_ObjectHideFlags: 52 m_CorrespondingSourceObject: {fileID: 0} @@ -74,7 +101,7 @@ MonoBehaviour: m_MinSize: {x: 0, y: 0} m_MaxSize: {x: 0, y: 0} m_LastLoadedLayoutName: ---- !u!114 &4 +--- !u!114 &5 MonoBehaviour: m_ObjectHideFlags: 52 m_CorrespondingSourceObject: {fileID: 0} @@ -95,7 +122,7 @@ MonoBehaviour: height: 20 m_MinSize: {x: 0, y: 0} m_MaxSize: {x: 0, y: 0} ---- !u!114 &5 +--- !u!114 &6 MonoBehaviour: m_ObjectHideFlags: 52 m_CorrespondingSourceObject: {fileID: 0} @@ -108,7 +135,7 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: m_Children: - - {fileID: 6} + - {fileID: 7} - {fileID: 13} m_Position: serializedVersion: 2 @@ -119,8 +146,8 @@ MonoBehaviour: m_MinSize: {x: 300, y: 200} m_MaxSize: {x: 24288, y: 16192} vertical: 0 - controlID: 130 ---- !u!114 &6 + controlID: 157 +--- !u!114 &7 MonoBehaviour: m_ObjectHideFlags: 52 m_CorrespondingSourceObject: {fileID: 0} @@ -133,19 +160,19 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: m_Children: - - {fileID: 7} - - {fileID: 10} + - {fileID: 8} + - {fileID: 11} m_Position: serializedVersion: 2 x: 0 y: 0 - width: 2081 + width: 2137 height: 1307 m_MinSize: {x: 200, y: 200} m_MaxSize: {x: 16192, y: 16192} vertical: 1 - controlID: 131 ---- !u!114 &7 + controlID: 22 +--- !u!114 &8 MonoBehaviour: m_ObjectHideFlags: 52 m_CorrespondingSourceObject: {fileID: 0} @@ -158,19 +185,19 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: m_Children: - - {fileID: 8} - {fileID: 9} + - {fileID: 10} m_Position: serializedVersion: 2 x: 0 y: 0 - width: 2081 - height: 1031 + width: 2137 + height: 975 m_MinSize: {x: 200, y: 100} m_MaxSize: {x: 16192, y: 8096} vertical: 0 - controlID: 132 ---- !u!114 &8 + controlID: 23 +--- !u!114 &9 MonoBehaviour: m_ObjectHideFlags: 52 m_CorrespondingSourceObject: {fileID: 0} @@ -187,8 +214,8 @@ MonoBehaviour: serializedVersion: 2 x: 0 y: 0 - width: 319 - height: 1031 + width: 306 + height: 975 m_MinSize: {x: 201, y: 221} m_MaxSize: {x: 4001, y: 4021} m_ActualView: {fileID: 15} @@ -196,7 +223,7 @@ MonoBehaviour: - {fileID: 15} m_Selected: 0 m_LastSelected: 0 ---- !u!114 &9 +--- !u!114 &10 MonoBehaviour: m_ObjectHideFlags: 52 m_CorrespondingSourceObject: {fileID: 0} @@ -211,10 +238,10 @@ MonoBehaviour: m_Children: [] m_Position: serializedVersion: 2 - x: 319 + x: 306 y: 0 - width: 1762 - height: 1031 + width: 1831 + height: 975 m_MinSize: {x: 202, y: 221} m_MaxSize: {x: 4002, y: 4021} m_ActualView: {fileID: 14} @@ -223,7 +250,7 @@ MonoBehaviour: - {fileID: 14} m_Selected: 1 m_LastSelected: 0 ---- !u!114 &10 +--- !u!114 &11 MonoBehaviour: m_ObjectHideFlags: 52 m_CorrespondingSourceObject: {fileID: 0} @@ -236,19 +263,19 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: m_Children: - - {fileID: 11} - {fileID: 12} + - {fileID: 2} m_Position: serializedVersion: 2 x: 0 - y: 1031 - width: 2081 - height: 276 + y: 975 + width: 2137 + height: 332 m_MinSize: {x: 200, y: 100} m_MaxSize: {x: 16192, y: 8096} vertical: 0 - controlID: 53 ---- !u!114 &11 + controlID: 121 +--- !u!114 &12 MonoBehaviour: m_ObjectHideFlags: 52 m_CorrespondingSourceObject: {fileID: 0} @@ -265,8 +292,8 @@ MonoBehaviour: serializedVersion: 2 x: 0 y: 0 - width: 1317 - height: 276 + width: 1054 + height: 332 m_MinSize: {x: 231, y: 271} m_MaxSize: {x: 10001, y: 10021} m_ActualView: {fileID: 17} @@ -274,33 +301,6 @@ MonoBehaviour: - {fileID: 17} m_Selected: 0 m_LastSelected: 0 ---- !u!114 &12 -MonoBehaviour: - m_ObjectHideFlags: 52 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0} - m_Name: ConsoleWindow - m_EditorClassIdentifier: - m_Children: [] - m_Position: - serializedVersion: 2 - x: 1317 - y: 0 - width: 764 - height: 276 - m_MinSize: {x: 102, y: 121} - m_MaxSize: {x: 4002, y: 4021} - m_ActualView: {fileID: 18} - m_Panes: - - {fileID: 18} - - {fileID: 19} - m_Selected: 0 - m_LastSelected: 1 --- !u!114 &13 MonoBehaviour: m_ObjectHideFlags: 52 @@ -316,9 +316,9 @@ MonoBehaviour: m_Children: [] m_Position: serializedVersion: 2 - x: 2081 + x: 2137 y: 0 - width: 479 + width: 423 height: 1307 m_MinSize: {x: 276, y: 71} m_MaxSize: {x: 4001, y: 4021} @@ -348,10 +348,10 @@ MonoBehaviour: m_Tooltip: m_Pos: serializedVersion: 2 - x: 319 + x: 306 y: 73 - width: 1760 - height: 1010 + width: 1829 + height: 954 m_ViewDataDictionary: {fileID: 0} m_OverlayCanvas: m_LastAppliedPresetName: Default @@ -362,7 +362,7 @@ MonoBehaviour: m_ShowGizmos: 0 m_TargetDisplay: 0 m_ClearColor: {r: 0, g: 0, b: 0, a: 0} - m_TargetSize: {x: 1760, y: 989} + m_TargetSize: {x: 1829, y: 933} m_TextureFilterMode: 0 m_TextureHideFlags: 61 m_RenderIMGUI: 1 @@ -377,10 +377,10 @@ MonoBehaviour: m_VRangeLocked: 0 hZoomLockedByDefault: 0 vZoomLockedByDefault: 0 - m_HBaseRangeMin: -880 - m_HBaseRangeMax: 880 - m_VBaseRangeMin: -494.5 - m_VBaseRangeMax: 494.5 + m_HBaseRangeMin: -914.5 + m_HBaseRangeMax: 914.5 + m_VBaseRangeMin: -466.5 + m_VBaseRangeMax: 466.5 m_HAllowExceedBaseRangeMin: 1 m_HAllowExceedBaseRangeMax: 1 m_VAllowExceedBaseRangeMin: 1 @@ -398,23 +398,23 @@ MonoBehaviour: serializedVersion: 2 x: 0 y: 21 - width: 1760 - height: 989 + width: 1829 + height: 933 m_Scale: {x: 1, y: 1} - m_Translation: {x: 880, y: 494.5} + m_Translation: {x: 914.5, y: 466.5} m_MarginLeft: 0 m_MarginRight: 0 m_MarginTop: 0 m_MarginBottom: 0 m_LastShownAreaInsideMargins: serializedVersion: 2 - x: -880 - y: -494.5 - width: 1760 - height: 989 + x: -914.5 + y: -466.5 + width: 1829 + height: 933 m_MinimalGUI: 1 m_defaultScale: 1 - m_LastWindowPixelSize: {x: 1760, y: 1010} + m_LastWindowPixelSize: {x: 1829, y: 954} m_ClearInEditMode: 1 m_NoCameraWarning: 1 m_LowResolutionForAspectRatios: 01000000000000000000 @@ -443,8 +443,8 @@ MonoBehaviour: serializedVersion: 2 x: 0 y: 73 - width: 318 - height: 1010 + width: 305 + height: 954 m_ViewDataDictionary: {fileID: 0} m_OverlayCanvas: m_LastAppliedPresetName: Default @@ -454,7 +454,7 @@ MonoBehaviour: scrollPos: {x: 0, y: 0} m_SelectedIDs: m_LastClickedID: 0 - m_ExpandedIDs: ae3bfffff83bffff8662ffff7c6affffc66affff5291ffff4899ffff9299ffffa0c3ffff04fbffff + m_ExpandedIDs: f6faffff m_RenameOverlay: m_UserAcceptedRename: 0 m_Name: @@ -470,7 +470,7 @@ MonoBehaviour: m_IsRenaming: 0 m_OriginalEventType: 11 m_IsRenamingFilename: 0 - m_ClientGUIView: {fileID: 8} + m_ClientGUIView: {fileID: 9} m_SearchString: m_ExpandedScenes: [] m_CurrenRootInstanceID: 0 @@ -499,10 +499,10 @@ MonoBehaviour: m_Tooltip: m_Pos: serializedVersion: 2 - x: 319 + x: 306 y: 73 - width: 1760 - height: 1010 + width: 1829 + height: 767 m_ViewDataDictionary: {fileID: 0} m_OverlayCanvas: m_LastAppliedPresetName: Default @@ -726,9 +726,9 @@ MonoBehaviour: m_PlayAudio: 0 m_AudioPlay: 0 m_Position: - m_Target: {x: 715.2682, y: 614.89905, z: -1.1473461} + m_Target: {x: 914.5, y: 621, z: 0} speed: 2 - m_Value: {x: 715.2682, y: 614.89905, z: -1.1473461} + m_Value: {x: 914.5, y: 621, z: 0} m_RenderMode: 0 m_CameraMode: drawMode: 0 @@ -759,7 +759,7 @@ MonoBehaviour: m_Fade: m_Target: 0 speed: 2 - m_Value: 1 + m_Value: 0 m_Color: {r: 0.5, g: 0.5, b: 0.5, a: 0.4} m_Pivot: {x: 0, y: 0, z: 0} m_Size: {x: 1, y: 1} @@ -767,7 +767,7 @@ MonoBehaviour: m_Fade: m_Target: 1 speed: 2 - m_Value: 0.9918524 + m_Value: 1 m_Color: {r: 0.5, g: 0.5, b: 0.5, a: 0.4} m_Pivot: {x: 0, y: 0, z: 0} m_Size: {x: 1, y: 1} @@ -779,9 +779,9 @@ MonoBehaviour: speed: 2 m_Value: {x: 0, y: 0, z: 0, w: 1} m_Size: - m_Target: 657.44696 + m_Target: 914.658 speed: 2 - m_Value: 657.44696 + m_Value: 914.658 m_Ortho: m_Target: 1 speed: 2 @@ -828,9 +828,9 @@ MonoBehaviour: m_Pos: serializedVersion: 2 x: 0 - y: 1104 - width: 1316 - height: 255 + y: 1048 + width: 1053 + height: 311 m_ViewDataDictionary: {fileID: 0} m_OverlayCanvas: m_LastAppliedPresetName: Default @@ -861,9 +861,9 @@ MonoBehaviour: m_IsLocked: 0 m_FolderTreeState: scrollPos: {x: 0, y: 0} - m_SelectedIDs: 30a80000 - m_LastClickedID: 43056 - m_ExpandedIDs: 0000000030a8000032a8000034a8000036a8000038a800003aa800003ca800003ea8000040a8000042a8000044a8000046a8000048a800004aa800004ca800004ea8000050a8000052a8000054a8000056a8000058a800005aa800005ca800005ea8000060a8000062a8000064a8000066a8000068a800006aa800006ca800006ea8000070a8000072a8000074a8000076a8000078a800007aa800007ca800007ea8000080a8000082a8000084a8000086a8000088a800008aa800008ca800008ea8000090a8000092a8000094a8000096a8000098a800009aa800009ca800009ea80000a0a80000a2a80000a4a80000a6a80000a8a80000aaa80000aca80000aea80000b0a80000b2a80000b4a80000b6a80000b8a80000baa80000bca80000bea80000c0a80000c2a80000c4a80000c6a80000c8a80000caa80000cca80000cea80000d0a80000d2a80000d4a80000d6a80000d8a80000daa80000dca80000dea8000000ca9a3bffffff7f + m_SelectedIDs: 76a80000 + m_LastClickedID: 43126 + m_ExpandedIDs: 0000000076a8000078a800007aa800007ca800007ea8000080a8000082a8000084a8000086a8000088a800008aa800008ca800008ea8000090a8000092a8000094a8000096a8000098a800009aa800009ca800009ea80000a0a80000a2a80000a4a80000a6a80000a8a80000aaa80000aca80000aea80000b0a80000b2a80000b4a80000b6a80000b8a80000baa80000bca80000bea80000c0a80000c2a80000c4a80000c6a80000c8a80000caa80000cca80000cea80000d0a80000d2a80000d4a80000d6a80000d8a80000daa80000dca80000dea80000e0a80000e2a80000e4a80000e6a80000e8a80000eaa80000eca80000eea80000f0a80000f2a80000f4a80000f6a80000f8a80000faa80000fca80000fea8000000a9000002a9000004a9000006a9000008a900000aa900000ca900000ea9000010a9000012a9000014a9000016a9000018a900001aa900001ca900001ea9000020a9000022a9000024a9000000ca9a3bffffff7f m_RenameOverlay: m_UserAcceptedRename: 0 m_Name: @@ -891,7 +891,7 @@ MonoBehaviour: scrollPos: {x: 0, y: 0} m_SelectedIDs: m_LastClickedID: 0 - m_ExpandedIDs: 0000000030a8000032a8000034a8000036a8000038a800003aa800003ca800003ea8000040a8000042a8000044a8000046a8000048a800004aa800004ca800004ea8000050a8000052a8000054a8000056a8000058a800005aa800005ca800005ea8000060a8000062a8000064a8000066a8000068a800006aa800006ca800006ea8000070a8000072a8000074a8000076a8000078a800007aa800007ca800007ea8000080a8000082a8000084a8000086a8000088a800008aa800008ca800008ea8000090a8000092a8000094a8000096a8000098a800009aa800009ca800009ea80000a0a80000a2a80000a4a80000a6a80000a8a80000aaa80000aca80000aea80000b0a80000b2a80000b4a80000b6a80000b8a80000baa80000bca80000bea80000c0a80000c2a80000c4a80000c6a80000c8a80000caa80000cca80000cea80000d0a80000d2a80000d4a80000d6a80000d8a80000daa80000dca80000dea80000 + m_ExpandedIDs: 0000000076a8000078a800007aa800007ca800007ea8000080a8000082a8000084a8000086a8000088a800008aa800008ca800008ea8000090a8000092a8000094a8000096a8000098a800009aa800009ca800009ea80000a0a80000a2a80000a4a80000a6a80000a8a80000aaa80000aca80000aea80000b0a80000b2a80000b4a80000b6a80000b8a80000baa80000bca80000bea80000c0a80000c2a80000c4a80000c6a80000c8a80000caa80000cca80000cea80000d0a80000d2a80000d4a80000d6a80000d8a80000daa80000dca80000dea80000e0a80000e2a80000e4a80000e6a80000e8a80000eaa80000eca80000eea80000f0a80000f2a80000f4a80000f6a80000f8a80000faa80000fca80000fea8000000a9000002a9000004a9000006a9000008a900000aa900000ca900000ea9000010a9000012a9000014a9000016a9000018a900001aa900001ca900001ea9000020a9000022a9000024a90000 m_RenameOverlay: m_UserAcceptedRename: 0 m_Name: @@ -968,10 +968,10 @@ MonoBehaviour: m_Tooltip: m_Pos: serializedVersion: 2 - x: 1317 - y: 1104 - width: 762 - height: 255 + x: 1054 + y: 1048 + width: 1081 + height: 311 m_ViewDataDictionary: {fileID: 0} m_OverlayCanvas: m_LastAppliedPresetName: Default @@ -997,10 +997,10 @@ MonoBehaviour: m_Tooltip: m_Pos: serializedVersion: 2 - x: 1303 - y: 1083 - width: 650 - height: 276 + x: 1054 + y: 1050 + width: 1081 + height: 309 m_ViewDataDictionary: {fileID: 0} m_OverlayCanvas: m_LastAppliedPresetName: Default @@ -1037,16 +1037,16 @@ MonoBehaviour: m_PaneScroll: {x: 0, y: 0} m_ViewType: 0 updateViewLive: 1 - m_CurrentFrameIndex: -1 + m_CurrentFrameIndex: 9246 m_HierarchyOverruledThreadFromSelection: 0 m_ProfilerViewFilteringOptions: 1 m_FrameDataHierarchyView: m_Serialized: 1 m_TreeViewState: scrollPos: {x: 0, y: 0} - m_SelectedIDs: 37000000 - m_LastClickedID: 0 - m_ExpandedIDs: 04000000 + m_SelectedIDs: f7000000 + m_LastClickedID: 247 + m_ExpandedIDs: 0400000037000000 m_RenameOverlay: m_UserAcceptedRename: 0 m_Name: @@ -1066,7 +1066,7 @@ MonoBehaviour: m_SearchString: m_MultiColumnHeaderState: m_Columns: - - width: 2042 + - width: 391 sortedAscending: 1 headerContent: m_Text: Overview @@ -1493,7 +1493,7 @@ MonoBehaviour: m_SortedColumns: 03000000 m_FullThreadName: Main Thread m_ThreadName: Main Thread - k__BackingField: 16776 + k__BackingField: 13408 k__BackingField: 0 m_GroupName: - rid: 594599679321178113 @@ -2019,9 +2019,9 @@ MonoBehaviour: m_Tooltip: m_Pos: serializedVersion: 2 - x: 2081 + x: 2137 y: 73 - width: 478 + width: 422 height: 1286 m_ViewDataDictionary: {fileID: 0} m_OverlayCanvas: @@ -2034,7 +2034,7 @@ MonoBehaviour: m_ControlHash: -371814159 m_PrefName: Preview_InspectorPreview m_LastInspectedObjectInstanceID: -1 - m_LastVerticalScrollValue: 0 + m_LastVerticalScrollValue: 190 m_GlobalObjectId: m_InspectorMode: 0 m_LockTracker: