Skip to content
Snippets Groups Projects
DisplayFacts.cs 9.43 KiB
Newer Older
  • Learn to ignore specific revisions
  • MaZiFAU's avatar
    MaZiFAU committed
    using MoreLinq;
    
    MaZiFAU's avatar
    MaZiFAU committed
    using System.Collections.Generic;
    
    using System.ComponentModel;
    
    MaZiFAU's avatar
    MaZiFAU committed
    using System.Linq;
    
    using UnityEditor;
    
    MaZiFAU's avatar
    MaZiFAU committed
    using UnityEngine;
    using UnityEngine.UI;
    
    using static CommunicationEvents;
    
    BenniHome's avatar
    BenniHome committed
    
    
    public class DisplayFacts : MonoBehaviour, ISerializationCallbackReceiver
    
    BenniHome's avatar
    BenniHome committed
    {
    
        private static DisplayFacts _instance;
        public static DisplayFacts Instance
        {
            get => _instance;
            private set { _instance ??= value; }
        }
    
    
    MaZiFAU's avatar
    MaZiFAU committed
        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();
    
    BenniHome's avatar
    BenniHome committed
    
    
        [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();
    
    MaZiFAU's avatar
    MaZiFAU committed
    
    
    MaZiFAU's avatar
    MaZiFAU committed
            _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
    
    MaZiFAU's avatar
    MaZiFAU committed
                    ? POdefault
    
                    : 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
    
        #region UnityMethods
    
        void Awake()
    
    BenniHome's avatar
    BenniHome committed
        {
    
            Instance = this; //first come, first serve
    
            displayedFacts = new(); // reset static properties
    
    John Schihada's avatar
    John Schihada committed
    
    
        private void OnEnable()
        {
    
            AddFactEvent.AddListener(AddFact);
    
            RemoveFactEvent.AddListener(RemoveFact);
    
            FactFavorisation.ChangeFavoriteEvent.AddListener(OnFavoriteChange);
    
    BenniHome's avatar
    BenniHome committed
        }
    
    
        private void OnDisable()
        {
            AddFactEvent.RemoveListener(AddFact);
            RemoveFactEvent.RemoveListener(RemoveFact);
            FactFavorisation.ChangeFavoriteEvent.RemoveListener(OnFavoriteChange);
        }
    
        private void RemoveFact(Fact fact)
            => displayedFacts.Remove(fact.Id);
    
        #endregion UnityMethods
    
    BenniHome's avatar
    BenniHome committed
    
    
        public void AddFact(Fact fact)
        {
    
            // 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;
                }
    
    MaZiFAU's avatar
    MaZiFAU committed
            var display = CreateDisplay(fact, factscreenContent);
    
            display.transform.localPosition = Vector3.zero;
    
            displayedFacts.TryAdd(fact.Id, display);
    
    MaZiFAU's avatar
    MaZiFAU committed
            display.transform.parent.gameObject.SetActive(
                !showOnlyFavorites
                || display.GetComponent<FactFavorisation>().IsFavorite
            );
    
            display.transform.parent.transform.SetSiblingIndex(siblingIdx);
    
    MaZiFAU's avatar
    MaZiFAU committed
        public static GameObject CreateDisplay(Fact fact, Transform transform)
        {
            var spot = Instantiate(FactSpotPrefab, transform);
            spot.GetComponent<FactWrapper>().Fact = fact;
    
    MaZiFAU's avatar
    MaZiFAU committed
            return InstantiateDisplay(fact, spot.transform);
    
        }
    
        public static GameObject InstantiateDisplay(Fact fact, Transform transform)
    
            Type fact_type = fact.GetType();
    
            if (fact_type.IsConstructedGenericType)
    
                fact_type = fact_type.GetGenericTypeDefinition();
    
    
            var ret = Instantiate(PrefabDictionary[fact_type], transform);
            ret.GetComponent<FactObject>().Fact = fact;
    
            return ret;
    
    BenniHome's avatar
    BenniHome committed
        }
    
    
        #region Sorting
        #region AscDesc
        public void AscDescChanged(Toggle t)
    
    BenniHome's avatar
    BenniHome committed
        {
    
    MaZiFAU's avatar
    MaZiFAU committed
            sortDescending = !sortDescending; // t.isOn
    
            factscreenContent.gameObject.ForAllChildren(child => child.transform.SetAsFirstSibling());
    
    
        #region Grouping
        public void GroupingChanged(Toggle t)
        {
            showGrouped = t.isOn;
    
    
            var vals = factscreenContent.gameObject.GetDirectChildren();
    
            var ordered = showGrouped
    
    MaZiFAU's avatar
    MaZiFAU committed
                ? 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;
        }
    
    
    MaZiFAU's avatar
    MaZiFAU committed
        private class FactTypeComparer : IComparer<Fact>
    
        {
            /// <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)
            {
    
    MaZiFAU's avatar
    MaZiFAU committed
                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))) ;
    
    MaZiFAU's avatar
    MaZiFAU committed
    
    #pragma warning restore CS0642 // Möglicherweise falsche leere Anweisung
    
                return ret;
    
    MaZiFAU's avatar
    MaZiFAU committed
    
            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 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
    
    MaZiFAU's avatar
    MaZiFAU committed
                     .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;
    
    
    MaZiFAU's avatar
    MaZiFAU committed
            if (displayedFacts.TryGetValue(changedFact.Id, out GameObject display))
                display.transform.parent.gameObject.SetActive(isFavourite);
    
    
        #endregion Implementation