Skip to content
Snippets Groups Projects
FactExplorer.cs 3.58 KiB
Newer Older
  • Learn to ignore specific revisions
  • using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Reflection;
    using UnityEngine;
    using System.Linq;
    using UnityEngine.UI;
    
    public class FactExplorer : MonoBehaviour
    {
        [Header("PrefabComponents")]
        [SerializeField] private Transform factParentsUI;
        [SerializeField] private Transform mainFactUI;
        [SerializeField] private Transform factChildrenUI;
        [SerializeField] private Transform linesUI;
    
        [Header("Prefabs")]
        [SerializeField] private GameObject factSpotPrefab;
    
    
        private Fact mainFact;
        private List<Fact> parentFacts;
        private List<Fact> childFacts;
    
    
        private void Update()
        {
            DestroyIfClickedOutside();
        }
    
        public void Initialize(Fact fact)
        {
    
            mainFact = fact;
            parentFacts = GetParentFacts();
            childFacts = GetChildFacts();
    
            Debug.Log($"Parents of {mainFact.Label}:  {string.Join(", ", parentFacts.Select(cf => cf.Label))}");
            Debug.Log($"Children of {mainFact.Label}: {string.Join(", ", childFacts.Select(cf => cf.Label))}");
    
            UpdateFactExplorerUI();
        }
    
        #region Implementation
        private List<Fact> GetParentFacts()
        {   
            //TODO: TSC how to get all current facts without this dumb workaround
            var allFacts = DisplayFacts.displayedFacts.Values.Select(x => x.GetComponent<FactWrapper>().fact);
            List<Fact> _parentFacts = new();
    
            // get all facts that reference the mainFact
            foreach (Fact f in allFacts)
                if (GetReferencedPids(f).Contains(mainFact.Id)) // if f contains reference to mainFact
                    _parentFacts.Add(f);
    
            return _parentFacts;
        }
    
        private List<Fact> GetChildFacts()
        {
            List<Fact> childFacts = new();
    
            // get all properties of Type mainFactType that are strings and start with "pid"
            foreach (string factId in GetReferencedPids(mainFact))
                childFacts.Add(StageStatic.stage.factState[factId]);
    
            return childFacts;
        }
    
        private void UpdateFactExplorerUI()
        {
            SpawnUIFacts(factParentsUI, parentFacts);
            SpawnUIFacts(mainFactUI, new List<Fact>() { mainFact });
            SpawnUIFacts(factChildrenUI, childFacts);
        }
    
        private void DestroyIfClickedOutside()
        {
            if ((Input.GetMouseButtonDown(0) || Input.GetMouseButtonDown(1)) &&
                !RectTransformUtility.RectangleContainsScreenPoint(transform.GetComponent<RectTransform>(), Input.mousePosition, null))
            {
                Destroy(gameObject);
            }
        }
        #endregion Implementation
    
        #region Helper
        /// <summary>
        /// Check all fields of a Fact for references to other facts and return their ids
        /// </summary>
        /// <param name="f"></param>
        /// <returns>An Enumerable containing the ids of facts referenced by the input fact</returns>
        private static IEnumerable<string> GetReferencedPids(Fact f)
        {
            return (f.GetType().GetFields()
                .Where(field => field.FieldType == typeof(string) && field.Name.ToLower().StartsWith("pid"))
            ).Select(fi => (string)fi.GetValue(f));
        }
    
        private void SpawnUIFacts(Transform uiParent, List<Fact> toSpawn)
        {
            uiParent.gameObject.DestroyAllChildren();
            foreach (Fact f in toSpawn)
            {
                var spot = Instantiate(factSpotPrefab, uiParent);
    
                // TODO: this link to DisplayFacts is not ideal: maybe refactor to SciptableObject or such
                var display = f.instantiateDisplay(DisplayFacts.prefabDictionary[f.GetType()], spot.transform);
                display.transform.localPosition = Vector3.zero;
            }
        }
        #endregion Helper
    }