using System.Collections; using System.Collections.Generic; using UnityEngine; using TMPro; using UnityEngine.Networking; using Newtonsoft.Json; using System.Linq; using static CommunicationEvents; using static SOMDocManager; public class ScrollDetails : MonoBehaviour { public WorldCursor cursor; public GameObject parameterDisplayPrefab; public Scroll ActiveScroll; public GameObject mmtAnswerPopUp; private PopupBehavior Popup; public static List<RenderedScrollFact> ParameterDisplays; private static List<Scroll.ScrollAssignment> LatestCompletions; private static List<Fact> LatestRenderedHints; public string currentMmtAnswer; public bool DynamicScrollDescriptionsActive = true; public bool AutomaticHintGenerationActive = true; void Awake() { if (cursor == null) cursor = FindObjectOfType<WorldCursor>(); (Popup = mmtAnswerPopUp.GetComponent<PopupBehavior>()) .hidePopUp(); } private void OnEnable() { ScrollFactHintEvent.AddListener(animateHint); NewAssignmentEvent.AddListener(NewAssignmentTrigger); RemoveFactEvent.AddListener(removeFactFromAssignment); } private void OnDisable() { ScrollFactHintEvent.RemoveListener(animateHint); NewAssignmentEvent.RemoveListener(NewAssignmentTrigger); RemoveFactEvent.RemoveListener(removeFactFromAssignment); } public void SetScroll(Scroll scroll_to_set) { ActiveScroll = scroll_to_set; Transform originalScroll = gameObject.transform.GetChild(1); Transform originalScrollView = originalScroll.GetChild(1); Transform originalViewport = originalScrollView.GetChild(0); //Clear all current ScrollFacts originalViewport.GetChild(0).gameObject.DestroyAllChildren(); originalScroll.GetChild(0).GetComponent<TextMeshProUGUI>().text = ActiveScroll.description; //ParameterDisplays.ForEach(gameObj => Destroy(gameObj)); ParameterDisplays = new(); for (int i = 0; i < ActiveScroll.requiredFacts.Count; i++) { GameObject originalObj = Instantiate(parameterDisplayPrefab, originalViewport.GetChild(0)); RenderedScrollFact originalRSF = originalObj.GetComponentInChildren<RenderedScrollFact>(); ParameterDisplays.Add(originalRSF); originalRSF.Populate(ActiveScroll, i); } foreach (int i in PrePopulateActiveScroll()) ParameterDisplays[i].gameObject.SetActive(false); //set active scroll for ErrorMessagePopup Popup.setScroll(ActiveScroll); Popup.setParameterDisplays(ParameterDisplays.Select(RSF => RSF.gameObject).ToList()); } /// <summary> /// Secretly populates <see cref="Scroll"/>s /// </summary> /// <returns><c>Array</c> containing indicis of <see cref="Scroll.requiredFacts"/> to be hidden.</returns> private int[] PrePopulateActiveScroll() { switch (ActiveScroll.@ref) { case MMT_OMS_URI.ScrollAngleSum: return new int[0]; default: return new int[0]; } } public void MagicButtonTrigger() { StartCoroutine(_MagicButton()); IEnumerator _MagicButton() { yield return SendView("/scroll/apply"); if (currentMmtAnswer == null) { Debug.LogError("Magic FAILED"); PushoutFactFailEvent.Invoke(null, null); } else { if (VerboseURI) Debug.Log("Magic answers:\n" + currentMmtAnswer); Scroll.ScrollApplicationInfo pushout = JsonConvert.DeserializeObject<Scroll.ScrollApplicationInfo>(currentMmtAnswer); if (pushout.acquiredFacts.Count == 0) PushoutFactFailEvent.Invoke(null, pushout); ReadPushout(pushout.acquiredFacts); } } } public void NewAssignmentTrigger() { if (AutomaticHintGenerationActive || DynamicScrollDescriptionsActive) StartCoroutine(_NewAssignment()); IEnumerator _NewAssignment() { //Non blocking wait till sendView() is finished yield return SendView("/scroll/dynamic"); if (currentMmtAnswer == null) { Debug.LogError("Dynamic Scroll FAILED"); } else { Scroll.ScrollDynamicInfo scrollDynamicInfo = JsonConvert.DeserializeObject<Scroll.ScrollDynamicInfo>(currentMmtAnswer); processScrollDynamicInfo(scrollDynamicInfo); } } } private IEnumerator SendView(string endpoint) { while (ParameterDisplays == null) // Wait for server yield return null; string body = prepareScrollAssignments(); using UnityWebRequest www = UnityWebRequest.Put(ServerAdress + endpoint, body); www.method = UnityWebRequest.kHttpVerbPOST; www.SetRequestHeader("Content-Type", "application/json"); System.DateTime sendTime = System.DateTime.UtcNow; yield return www.SendWebRequest(); if (VerboseURI) Debug.LogFormat("Server answerd in : {0}ms" , (System.DateTime.UtcNow - sendTime).TotalMilliseconds); if (www.result == UnityWebRequest.Result.ConnectionError || www.result == UnityWebRequest.Result.ProtocolError) { Debug.Log(www.error); currentMmtAnswer = null; } else { string answer = www.downloadHandler.text; currentMmtAnswer = answer; } string prepareScrollAssignments() { List<Scroll.ScrollAssignment> assignmentList = new(); for (int i = 0; i < ParameterDisplays.Count; i++) { Fact tempFact = ParameterDisplays[i].Fact; if (tempFact != null) assignmentList.Add(new Scroll.ScrollAssignment(ActiveScroll.requiredFacts[i].@ref.uri, tempFact.Id)); } return JsonConvert.SerializeObject(new Scroll.FilledScroll(ActiveScroll.@ref, assignmentList)); } } private void ReadPushout(List<MMTDeclaration> pushoutFacts) { Popup.hidePopUp(); //close error Window bool samestep = false; for (int i = 0; i < pushoutFacts.Count; i++) { Fact newFact = ParsingDictionary.parseFactDictionary[pushoutFacts[i].getType()].Invoke(pushoutFacts[i]); if (newFact != null) { AnimateExistingFactEvent.Invoke (FactManager.AddFactIfNotFound(newFact, out _, samestep, null, ActiveScroll.label).Id , FactWrapper.FactMaterials.Solution); samestep = true; } else Debug.Log("Parsing on pushout-fact returned null -> One of the dependent facts does not exist"); } } private void processScrollDynamicInfo(Scroll.ScrollDynamicInfo scrollDynamicInfo) { LatestCompletions = scrollDynamicInfo.completions.Count > 0 ? scrollDynamicInfo.completions[0] : new List<Scroll.ScrollAssignment>(); List<string> hintUris = LatestCompletions .Select(completion => completion.fact.uri) .ToList(); //Update Scroll, process data for later hints and update Uri-List for which hints are available _processRenderedScroll(scrollDynamicInfo.rendered, hintUris); if (AutomaticHintGenerationActive) //Show that Hint is available for ScrollParameter HintAvailableEvent.Invoke(hintUris); return; void _processRenderedScroll(Scroll rendered, List<string> hintUris) { if (DynamicScrollDescriptionsActive) { // Update scroll-description Transform scroll = gameObject.transform.GetChild(1).transform; scroll.GetChild(0).GetComponent<TextMeshProUGUI>().text = rendered.description; } LatestRenderedHints = new(); for (int i = 0; i < rendered.requiredFacts.Count; i++) { RenderedScrollFact RenderedScrollFact = ParameterDisplays .Find(RSF => RSF.ScrollFactURI == rendered.requiredFacts[i].@ref.uri); if (DynamicScrollDescriptionsActive) //Update ScrollParameter label RenderedScrollFact.Scroll = rendered; //If ScrollFact is assigned -> No Hint if (RenderedScrollFact.Fact == null) { Fact HintFact = ParsingDictionary.parseFactDictionary[rendered.requiredFacts[i].getType()] .Invoke(rendered.requiredFacts[i]); //If the fact could not be parsed -> Therefore not all dependent Facts exist -> No Hint if (HintFact != null) { hintUris.Add(HintFact.Id); LatestRenderedHints.Add(HintFact); } } } return; } } public void animateHint(ImageHintAnimation scrollHintImage, string scrollParameterUri) { if (FactOrganizer.AllFacts.ContainsKey(scrollParameterUri)) AnimateExistingFactEvent.Invoke( scrollParameterUri, FactWrapper.FactMaterials.Hint ); Scroll.ScrollAssignment suitableCompletion = LatestCompletions.Find(x => x.fact.uri == scrollParameterUri); Fact fact; if (suitableCompletion != null) { if (FactOrganizer.AllFacts.ContainsKey(suitableCompletion.assignment.uri)) { AnimateExistingFactEvent.Invoke( suitableCompletion.assignment.uri, FactWrapper.FactMaterials.Hint ); } } else if (null != (fact = LatestRenderedHints.Find(x => x.Id == scrollParameterUri))) { if (FactOrganizer.AllFacts.ContainsKey(fact.Id)) // existing fact -> Animate that AnimateExistingFactEvent.Invoke( fact.Id, FactWrapper.FactMaterials.Hint ); else { // Generate new FactRepresentation and animate it AnimateNonExistingFactEvent.Invoke(fact); AnimateExistingFactEvent.Invoke( scrollParameterUri, FactWrapper.FactMaterials.Hint ); } } } //this is called whenever a Fact is Deleted in the world, to make sure it is removed from the scroll public void removeFactFromAssignment(Fact fact) { Transform originalScroll = gameObject.transform.GetChild(1).transform; Transform originalScrollView = originalScroll.GetChild(1); Transform originalViewport = originalScrollView.GetChild(0); for (int i = 0; i < originalViewport.GetChild(0).childCount; i++) { RenderedScrollFact scrollFact = originalViewport.GetChild(0).transform.GetChild(i).GetChild(0).gameObject.GetComponent<RenderedScrollFact>(); if (scrollFact.ScrollFactLabel == fact.Label) scrollFact.OnPointerClick(null); } } }