public void pushForward(ElimRule rule, LayoutTracker TopSymbol) { Term term = currentTerm; if (rule is CombinatorElim cElim) { var copy = Instantiate(AccessTransfrom(TopSymbol.transform, cElim.Target()).GetChild(0).gameObject, AccessTransfrom(TopSymbol.transform, cElim.Target()).GetChild(0).position, Quaternion.identity); copy.transform.SetParent(GetComponentInParent <Canvas>().transform.GetChild(0), true); copy.SetActive(false); backwardUndoStack.Push(Sum <BackwardTermData, BackwardParenData> .Inl(new BackwardTermData(term , () => { copy.SetActive(true); copy.transform.SetParent(AccessTransfrom(TopSymbol.transform, cElim.Target())); copy.transform.localScale = Vector3.one; return(copy.GetComponent <LayoutTracker>()); } , cElim.c, cElim.Target(), TopSymbol ))); } else if (rule is ParenElim pElim) { var copy = Instantiate(AccessTransfrom(TopSymbol.transform, pElim.Target()).gameObject); copy.transform.position = TopSymbol.transform.position; foreach (Transform t in copy.transform) { Destroy(t.gameObject); } copy.transform.SetParent(GetComponentInParent <Canvas>().transform.GetChild(0), true); copy.SetActive(false); int size = AccessTransfrom(TopSymbol.transform, pElim.Target()).GetChild(0).childCount; backwardUndoStack.Push(Sum <BackwardTermData, BackwardParenData> .Inr(new BackwardParenData( pElim.Target(), size , () => { copy.SetActive(true); copy.transform.localScale = Vector3.one; return(copy.GetComponent <LayoutTracker>()); }, TopSymbol, term ))); } }
Shrub <GameObject> TransferTerm(Term term, Shrub <GameObject> objs, ElimRule rule) //REQUIRES: term and objs share a shape { var paths_shrub = NewLocations(term, rule); var new_term = rule.evaluate(term); var new_leftsides = findLeftSides(new_term, 0); GameObject lookup(Path p) { GameObject go = null; paths_shrub.IterateI(new Path(), (List <List <int> > targets, List <int> source) => { if (targets.Exists(target => target.SequenceEqual(p))) { //the shapes must match if (targets.FindIndex(target => target.SequenceEqual(p)) == 0) { go = objs.Access(source).Match(l => null, r => r); } else { go = GameObject.Instantiate(objs.Access(source).Match(l => null, r => r)); } } }); return(go); } return(new_term.MapI <GameObject>(new Path(), (_, path) => { GameObject g = lookup(path); StartCoroutine(MoveTo(g, Vector3.right * new_leftsides.Item1.Access(path).Match(l => - 0, r => r))); return g; })); }
private IEnumerator _Transition(ElimRule rule, LayoutTracker TopSymbol) //no moving in topsymbol { pushForward(rule, TopSymbol); var oldTerm = currentTerm; /********* replace skeleton ***********/ Term newTerm = rule.evaluate(oldTerm); currentTerm = newTerm; foreach (Transform t in skeletonRoot) { Destroy(t.gameObject); } CreateSkeleton(newTerm, skeletonRoot); /********* Find symbol where rule applies ***********/ var index = rule.Target(); var affectedSymbol = AccessTransfrom(TopSymbol.transform, index).GetComponent <LayoutTracker>(); var leftmostchild = affectedSymbol.transform.GetChild(0).position; /********* case on the rule **********/ if (rule is CombinatorElim CElim) { //Play the combinator Animation with usecombinator function affectedSymbol.transform.GetChild(0).GetComponent <AnimateCombinator>().UseCombinator(); //Plays the appropriate combinator sound effect combinatorEffectPlay(CElim); /********** unpack the elim rule ***********/ { (var debruijn, var arity) = Util.ParseCombinator(CElim.c) .Match( pi => pi, u => throw new Exception(u.ToString()) ); //keep track of the arguments that we need to destroy or whether //they are the first use of an arg so we don't need to spawn a new one bool[] argumentsThatHaveBeenUsed = new bool[arity + 1]; /* + 1 for possible recursion at A[0]*/ //get all the symbols at the affected level in a list for easier management List <LayoutTracker> symbols = new List <LayoutTracker>(); foreach (Transform t in affectedSymbol.transform) { symbols.Add(t.GetComponent <LayoutTracker>()); } /**************** map over transforms to adjust indices ***************/ /******* find the new symbols to replace the arguments with ***********/ var detatchedSymbols = debruijn.MapI(index.Append(0).ToList(), (ind, path) => { if (!argumentsThatHaveBeenUsed[ind + 1 /* +1 for recursion*/]) { symbols[ind + 1].transform.SetParent(GetComponentInParent <Canvas>().transform, true); symbols[ind + 1].index = path; IterateTransform(symbols[ind + 1].transform, t => t.GetComponent <LayoutTracker>().index = path.Concat(t.GetComponent <LayoutTracker>().index.Skip(index.Count + 2)).ToList()); argumentsThatHaveBeenUsed[ind + 1] = true; return(symbols[ind + 1]); } else { IterateTransform(symbols[ind + 1].transform, t => t.GetComponent <LayoutTracker>().index = path.Concat(t.GetComponent <LayoutTracker>().index.Skip(index.Count + 2)).ToList()); var newSymbol = Instantiate(symbols[ind + 1], GetComponentInChildren <LayoutTracker>().transform.position, Quaternion.identity, transform); newSymbol.index = path; return(newSymbol); } }); /************** Cleanup unused argument symbols **************/ for (var i = 0; i < argumentsThatHaveBeenUsed.Length; i++) { if (!argumentsThatHaveBeenUsed[i]) { Destroy(symbols[i].gameObject); } } /******* Create Paren objects and set up hierarchy *********/ Transform CreateParens(Shrub <LayoutTracker> symbolShrub, List <int> totalPath) { return(symbolShrub.Match <Transform>(l => { var paren = Instantiate(parenSymbol, leftmostchild, Quaternion.identity, GetComponentInParent <Canvas>().transform); paren.index = totalPath; paren.root = skeletonRoot; for (var i = 0; i < l.Count; i++) { CreateParens(l[i], totalPath.Append(i).ToList()).SetParent(paren.transform, true); } return paren.transform; }, sym => sym.transform)); } //create the paren object on a dummy object then move the new terms //to the appropriate place in the appropriate order Transform dummyParen = CreateParens(detatchedSymbols, index.Append(0).ToList()); //TODO verify List <Transform> ts = new List <Transform>(); for (int i = dummyParen.childCount - 1; 0 <= i; i--) { ts.Add(dummyParen.GetChild(i)); } foreach (var t in ts) { t.SetParent(affectedSymbol.transform, true); t.SetSiblingIndex(0); t.GetComponent <LayoutTracker>().LockDown(.15f); } Destroy(dummyParen.gameObject); /****** adjust unused symbols indices ********/ for (int i = arity + 1; false; i++) { int new_pos = i - arity - 1 + detatchedSymbols.Match(l => l.Count, v => 1); symbols[i].index[symbols[i].index.Count - 1] = new_pos; IterateTransform(symbols[i].transform, t => t.GetComponent <LayoutTracker>().index[index.Count - 1] = new_pos); //TODO verify } } } if (rule is ParenElim PElim) { affectedSymbol.gameObject.name = "affected boi"; var old_paren = affectedSymbol.transform.GetChild(0); var children = new List <Transform>(); for (int i = old_paren.childCount - 1; i >= 0; i--) { children.Add(old_paren.GetChild(i)); } for (int child = 0; child < children.Count; child++) { LayoutTracker lt = children[child].GetComponent <LayoutTracker>(); lt.index.RemoveAt(lt.index.Count - 1); lt.index[lt.index.Count - 1] += child; children[child].SetParent(affectedSymbol.transform, true); children[child].SetSiblingIndex(0); } //TODO fade these out Destroy(old_paren.gameObject); } yield return(new WaitUntil(() => { bool moving = false; IterateTransform(TopSymbol.transform, t => { if (t.GetComponent <LayoutTracker>()) { moving |= t.GetComponent <LayoutTracker>().Moving(); } }); return !moving; })); }
public IEnumerator Transition(ElimRule rule, LayoutTracker TopSymbol) { forwardUndoStack = new Stack <ForwardData>(); yield return(_Transition(rule, TopSymbol)); }