Newer
Older
using System;
using static CommunicationEvents;
public class DisplayFacts : MonoBehaviour, ISerializationCallbackReceiver
private static DisplayFacts _instance;
public static DisplayFacts Instance
{
get => _instance;
private set { _instance ??= value; }
}
public static Transform FactscreenContent => Instance.factscreenContent;
public static GameObject FactSpotPrefab => Instance.factSpotPrefab;
//cannot populate static dict while serialization => "singelton"
public static Dictionary<Type, GameObject> PrefabDictionary { get => Instance._PrefabDictionary; }
private Dictionary<Type, GameObject> _PrefabDictionary = new();
public static Dictionary<string, GameObject> displayedFacts = new();
[SerializeField] private Transform factscreenContent;
[SerializeField] private GameObject factSpotPrefab;
private bool sortDescending = false;
private bool showGrouped = false;
private bool showOnlyFavorites = false;
#region ISerializationCallbackReceiver
[ReadOnly(true), SerializeField]
private List<string> PrefabtTypeReadonly;
[SerializeField]
private List<GameObject> PrefabDataConfig;
public void OnBeforeSerialize()
{
PrefabtTypeReadonly = TypeExtensions<Fact>.UAssemblyInheritenceTypes.Select(type => type.ToString()).ToList();
PrefabtTypeReadonly.Sort(); //for convinience
// if order has changed => do not forget
var keys = _PrefabDictionary.Keys.Select(type => type.ToString()).ToList();
var keys_permutation = PrefabtTypeReadonly.Select(type => keys.IndexOf(type)).ToArray();
_PrefabDictionary.TryGetValue(typeof(TestFact), out GameObject POdefault);
var vals = _PrefabDictionary.Values.ToArray();
PrefabDataConfig = new(keys_permutation.Length);
for (int i = 0; i < keys_permutation.Length; i++)
{
GameObject data = keys_permutation[i] < 0
: vals[keys_permutation[i]];
if (PrefabDataConfig.Count <= i)
PrefabDataConfig.Add(data);
else
PrefabDataConfig[i] = data;
}
}
public void OnAfterDeserialize()
{
_PrefabDictionary = new();
for (int i = 0; i != Math.Min(PrefabtTypeReadonly.Count, PrefabDataConfig.Count); i++)
{
//// No Idea how to reproduce
//if (TypeExtensions<Fact>.UAssemblyInheritenceTypes.FirstOrDefault(type => type.ToString() == PrefabtTypeReadonly[i]) == null)
// continue;
_PrefabDictionary.TryAdd(
TypeExtensions<Fact>.UAssemblyInheritenceTypes.FirstOrDefault(type => type.ToString() == PrefabtTypeReadonly[i]),
PrefabDataConfig[i]
);
}
#endregion ISerializationCallbackReceiver
displayedFacts = new(); // reset static properties
AddFactEvent.AddListener(AddFact);
RemoveFactEvent.AddListener(RemoveFact);
FactFavorisation.ChangeFavoriteEvent.AddListener(OnFavoriteChange);
private void OnDisable()
{
AddFactEvent.RemoveListener(AddFact);
RemoveFactEvent.RemoveListener(RemoveFact);
FactFavorisation.ChangeFavoriteEvent.RemoveListener(OnFavoriteChange);
}
private void RemoveFact(Fact fact)
=> displayedFacts.Remove(fact.Id);
#region Implementation
// index where the new display will be inserted
int siblingIdx = sortDescending ? 0 : factscreenContent.childCount;
var facts = factscreenContent.GetComponentsInChildren<FactObject>().Select(f => f.Fact).ToList();
if (!sortDescending)
siblingIdx = GetIndexInSortedList(fact, facts);
else
{
facts.Reverse();
var _siblingIdx = GetIndexInSortedList(fact, facts);
siblingIdx = factscreenContent.childCount - _siblingIdx;
}
}
// create display
var display = CreateDisplay(fact, factscreenContent);
display.transform.localPosition = Vector3.zero;
displayedFacts.TryAdd(fact.Id, display);
display.transform.parent.gameObject.SetActive(
!showOnlyFavorites
|| display.GetComponent<FactFavorisation>().IsFavorite
);
display.transform.parent.transform.SetSiblingIndex(siblingIdx);
public static GameObject CreateDisplay(Fact fact, Transform transform)
{
var spot = Instantiate(FactSpotPrefab, transform);
spot.GetComponent<FactWrapper>().Fact = fact;
}
public static GameObject InstantiateDisplay(Fact fact, Transform transform)
if (fact_type.IsConstructedGenericType)
fact_type = fact_type.GetGenericTypeDefinition();
var ret = Instantiate(PrefabDictionary[fact_type], transform);
ret.GetComponent<FactObject>().Fact = fact;
return ret;
#region Sorting
#region AscDesc
public void AscDescChanged(Toggle t)
factscreenContent.gameObject.ForAllChildren(child => child.transform.SetAsFirstSibling());
#endregion AscDesc
#region Grouping
public void GroupingChanged(Toggle t)
{
showGrouped = t.isOn;
var vals = factscreenContent.gameObject.GetDirectChildren();
? vals.OrderBy(tr => tr.GetComponent<FactWrapper>().Fact, new FactTypeComparer()).ToList()
: vals.OrderBy(tr =>
displayedFacts.Keys.ToList()
.IndexOf(
tr.GetComponent<FactWrapper>().URI
)).ToList();
if (sortDescending)
ordered.Reverse();
for (int i = 0; i < ordered.Count; i++)
ordered[i].transform.SetSiblingIndex(i);
}
private int GetIndexInSortedList(Fact f, List<Fact> toCheck)
{
var index = toCheck.BinarySearch(f, new FactTypeComparer());
if (index < 0) index = ~index;
return index;
}
{
/// <summary>
/// Compare two facts by type and label
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
public int Compare(Fact x, Fact y)
{
int ret, index_x;
#pragma warning disable CS0642 // Möglicherweise falsche leere Anweisung
if (0 != (ret = (index_x = TypeRank.IndexOf(x.GetType())) - TypeRank.IndexOf(y.GetType()))) ;
else
if (index_x < 0) // Types not in List and same
if (0 != (ret = x.DependentFactIds.Length - y.DependentFactIds.Length)) ;
else
if (0 != (ret = string.Compare(x.GetType().ToString(), y.GetType().ToString()))) ;
else;
else if (true) // keep auto format // Types in List and same
if (0 != (ret = x.DependentFactIds.Zip(y.DependentFactIds, (x, y) => string.Compare(x, y)).Aggregate(0, (r1, r2) => r1 + r2))) ;
else
if (0 != (ret = string.Compare(x._LastLabel, y._LastLabel))) ;
#pragma warning restore CS0642 // Möglicherweise falsche leere Anweisung
return ret;
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
private List<Type> TypeRank = new()
{
typeof(PointFact),
typeof(OnLineFact),
typeof(LineFact),
typeof(RayFact),
typeof(ParallelLineFact),
typeof(RightAngleFact),
typeof(AngleFact),
typeof(CircleFact),
typeof(RadiusFact),
typeof(AreaCircleFact),
typeof(EqualCirclesFact),
typeof(UnEqualCirclesFact),
typeof(OnCircleFact),
typeof(AngleCircleLineFact),
typeof(OrthogonalCircleLineFact),
typeof(CylinderVolumeFact),
typeof(ConeVolumeFact),
typeof(TruncatedConeVolumeFact),
typeof(FunctionFact),
typeof(FunctionCallFact),
typeof(TestFact),
};
}
#endregion Grouping
#endregion Sorting
#region Favorites
public void FavoritesFilterChanged(Toggle t)
{
showOnlyFavorites = t.isOn;
if (!showOnlyFavorites) // show all
displayedFacts.Values.ForEach(nFav => nFav.transform.parent.gameObject.SetActive(true));
{ // hide not favorites
displayedFacts.Values
.Where(gO => gO != null && !gO.GetComponent<FactFavorisation>().IsFavorite)
.ForEach(nFav => nFav.transform.parent.gameObject.SetActive(false));
}
}
private void OnFavoriteChange(Fact changedFact, bool isFavourite)
{
if (!showOnlyFavorites)
return;
if (displayedFacts.TryGetValue(changedFact.Id, out GameObject display))
display.transform.parent.gameObject.SetActive(isFavourite);
}
#endregion Favorites
#endregion Implementation