public void LayoutTracker_leak_test() { RunInMainThread(() => { AssertIsGarbageCollected( () => { BehaviorSubject <IEnumerable <IControl> > innerControls = new BehaviorSubject <IEnumerable <IControl> >(Enumerable.Empty <IControl>()); var container = LayoutTracker.Create( x => innerControls.CachePerElement(y => x.TrackVisualBounds(frame => { }, y)).StackFromLeft()); container.MountRoot(); return(new { innerControls, container }); }, env => { var innerControls = env.innerControls; var rectangleHeight = new BehaviorSubject <Points>(33); var rectangle = Shapes.Rectangle(fill: Brush.Transparent).WithWidth(rectangleHeight); Assert.That(rectangleHeight.HasObservers, Is.False); innerControls.OnNext(new[] { rectangle }); Assert.That(rectangleHeight.HasObservers, Is.True); innerControls.OnNext(Enumerable.Empty <IControl>()); Assert.That(rectangleHeight.HasObservers, Is.False); return(rectangle); }); }); }
private void spawnSpell(LayoutTracker prefab, Combinator combinator) { LayoutTracker newSpell = Instantiate(prefab, transform); newSpell.enabled = false; newSpell.gameObject.AddComponent <LayoutElement>(); }
// Call this to pop the undo stack onto the goal public void undo() { // Invoke the undoTermEvent with the top term, so that the real goal symbol manager can update itself if (stack.Count < 1) { Debug.LogWarning("Tried to undo when there's nothing on the undo stack. Ignoring it."); return; } undoTermEvent.Invoke(stack.Pop()); // Delete the current term if (currentLayoutTracker) { Destroy(currentLayoutTracker.gameObject); currentLayoutTracker = null; } // If there's no next undo term, that's fine if (stack.Count < 1) { return; } // Place the next undo term Term nextUndoTerm = stack.Peek(); currentLayoutTracker = symbolManager.Initialize(nextUndoTerm); }
// Set the alpha of the currentLayout parens (top level parens) to 0 private void resetParensAlpha(LayoutTracker layoutTracker) { Image image = layoutTracker.GetComponent <Image>(); Color c = image.color; image.color = new Color(c.r, c.g, c.b, .0f); }
private IEnumerator addParen(AddParenRule rule, LayoutTracker TopSymbol) { var parent = AccessTransfrom(TopSymbol.transform, rule.path); var lt = Instantiate(parenSymbol, parent); lt.root = skeletonRoot; List <Transform> children = new List <Transform>(); for (int i = 0; i < rule.size; i++) { children.Add(parent.GetChild(i)); } lt.transform.SetAsFirstSibling(); foreach (Transform transform in children) { transform.SetParent(lt.transform, true); } foreach (Transform child in skeletonRoot) { Destroy(child.gameObject); } CreateSkeleton(rule.oldTerm, skeletonRoot); yield return(new WaitUntil(() => !lt.Moving())); }
private void Start() { currentLayout = manager.Initialize(Term.Node(new List <Term>())).GetComponentInChildren <LayoutTracker>(); resetParensAlpha(currentLayout); Destroy(currentLayout.GetComponent <DraggableSpell>()); }
public BackwardTermData(Term newTerm, Func <LayoutTracker> lt, Combinator c, List <int> path, LayoutTracker topSymbol) { this.newTerm = newTerm; this.lt = lt; C = c; this.path = path; TopSymbol = topSymbol; }
public BackwardParenData(List <int> path, int size, Func <LayoutTracker> paren, LayoutTracker topSymbol, Term newTerm) { this.path = path; this.size = size; this.paren = paren; TopSymbol = topSymbol; this.newTerm = newTerm; }
public LayoutTracker RemoveAtAndReturn(List <int> path, LayoutTracker root) { var index = path[path.Count - 1]; path = path.Take(path.Count - 1).ToList(); var new_term = currentTerm.ApplyAt(parenTerm => parenTerm.Match(l => { l = l.ToList(); var RemovedTerm = l[index]; l.RemoveAt(index); RemovedTerm.Match(children => { children.Reverse(); foreach (Term child in children) { l.Insert(index, child); } }, _ => { /* already removed */ }); return(Term.Node(l)); } , x => throw new Exception("Depth Exception")), path); foreach (Transform t in skeletonRoot) { if (Application.isPlaying) { Destroy(t.gameObject); } } var Paren = AccessTransfrom(root.transform, path); var Removed = Paren.GetChild(index); if (0 < Removed.childCount) { backwardUndoStack = new Stack <Sum <BackwardTermData, BackwardParenData> >(); //forwardUndoStack.Push(new ForwardData(Sum<ElimRule, AddParenRule>.Inl(new ParenElim(path)), root)); forwardUndoStack.Push(new ForwardData(Sum <ElimRule, AddParenRule> .Inr(new AddParenRule(path, Removed.childCount, currentTerm)), root)); } CreateSkeleton(new_term, skeletonRoot); //sets new term List <Transform> ts = new List <Transform>(); foreach (Transform t in Removed.transform) { ts.Add(t); } ts.Reverse(); foreach (Transform t in ts) { t.SetParent(Paren); t.SetSiblingIndex(index); } return(Removed.GetComponent <LayoutTracker>()); }
// Push a new term onto the undo stack public void pushTerm(Term term) { stack.Push(term); if (currentLayoutTracker) { Destroy(currentLayoutTracker.gameObject); } currentLayoutTracker = symbolManager.Initialize(term); }
public PreviewBackCombinatorInfo(SpawnTarget spawnTarget, LayoutTracker paren, List <int> path, Action place, Action highlight, Action unHighlight) { this.highlight = highlight; this.unHighlight = unHighlight; this.spawnTarget = spawnTarget; this.paren = paren; this.path = path; this.place = place; }
public void reset() { if (currentLayout) { Destroy(currentLayout.gameObject); } currentLayout = manager.Initialize(Term.Node(new List <Term>())); resetParensAlpha(currentLayout); }
public void CreateTerm(Term t) { if (currentLayout && currentLayout.gameObject) { Destroy(currentLayout.gameObject); } currentLayout = manager.Initialize(t); resetParensAlpha(currentLayout); }
Task TrackerIconTapped() { if (Setting.Instance is ITrackable tra) { LayoutTracker.StartTracking(tra); Nav.Reload().RunInParallel(); } return(Task.CompletedTask); }
public void OnPointerClick(PointerEventData eventData) { LayoutTracker root = this; for (int i = 0; i < index.Count - 1; i++) { root = root.transform.parent.GetComponent <LayoutTracker>(); } GetComponentInParent <SymbolManager>().HandleClick(index.Skip(1).ToList(), root); }
public void Cast() { oldterm = proposal.readTerm(); evalmode.val = true; onApply.Invoke(); effectAudioEvent.Invoke(7); //Cast Spell Sound List <Term> args = Enumerable.Range(0, arity) .Select(i => Term.Leaf(Sum <Combinator, Variable> .Inr((Variable)i))).ToList(); proposal.Append(args); LayoutTracker arg_paren = variable_symbols_here.GetComponentInChildren <LayoutTracker>(); List <Transform> ts = new List <Transform>(); for (int i = 0; i < arg_paren.transform.childCount; i++) { ts.Add(arg_paren.transform.GetChild(i)); } foreach (Transform variable in ts) { variable.GetComponent <LayoutTracker>().root = proposal.skeletonRoot; variable.SetParent(proposal.GetComponentInChildren <LayoutTracker>().transform, true); } term = proposal.readTerm(); button.onClick.RemoveListener(Cast); button.onClick.AddListener(Step); button.GetComponent <Image>().sprite = stepSymbol; SkipButton.gameObject.SetActive(true); SkipBackButton.gameObject.SetActive(true); StepBackButton.gameObject.SetActive(true); StopButton.gameObject.SetActive(true); refreshButtons(); LayoutRebuilder.MarkLayoutForRebuild(transform.parent.GetComponent <RectTransform>()); if (target.goal.Equal(term)) { Success.Invoke(); } Debug.Log(arg_paren); Destroy(arg_paren); variable_symbols_here.gameObject.SetActive(false); foreach (var canvas in FindObjectsOfType <Canvas>()) { LayoutRebuilder.MarkLayoutForRebuild(canvas.GetComponent <RectTransform>()); } }
public IEnumerator _BackApplyParens(List <int> path, int size, LayoutTracker paren, LayoutTracker TopSymbol, Term newTerm) { forwardUndoStack.Push(new ForwardData(Sum <ElimRule, AddParenRule> .Inl(new ParenElim(path)), TopSymbol)); var target = AccessTransfrom(TopSymbol.transform, path); List <Transform> temp = new List <Transform>(); for (int i = 0; i < size; i++) { temp.Add(target.GetChild(i)); } paren.transform.parent = target; //this is the problem line. SetParent(target,true) doesn't work and is oddly less effective, lateupdate? paren.transform.SetAsFirstSibling(); foreach (var t in temp) { t.SetParent(paren.transform, true); } foreach (Transform t in skeletonRoot) { Destroy(t.gameObject); } CreateSkeleton(newTerm, skeletonRoot); yield return(new WaitUntil(() => { bool moving = false; IterateTransform(TopSymbol.transform, t => { if (t.GetComponent <LayoutTracker>()) { moving |= t.GetComponent <LayoutTracker>().Moving(); } }); return !moving; })); }
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 ))); } }
// After the level has loaded, populate the skeleton using the symbol manager private void onLevelWasLoaded(int arity) { List <Term> variables = new List <Term>(); for (int i = 0; i < arity; i++) { variables.Add(Term.Leaf(Sum <Combinator, Lambda.Variable> .Inr((Lambda.Variable)i))); } if (oldVariables) { Destroy(oldVariables.gameObject); } oldVariables = symbolManager.Initialize(Term.Node(variables)); // Set the alpha of the oldVariables parens (top level parens) to 0 Image image = oldVariables.GetComponent <Image>(); Color c = image.color; image.color = new Color(c.r, c.g, c.b, 0); }
public static IControl Host(Func <IPopover, IControl> content) { return(LayoutTracker.Create(tracker => { var hostFrame = new ReplaySubject <Rectangle <IObservable <Points> > >(1); var host = new Implementation { LayoutTracker = tracker, Popovers = new BehaviorSubject <IImmutableList <IControl> >(ImmutableList <IControl> .Empty), HostFrame = hostFrame }; return content(host) .WithNativeOverlay(host.Popovers.Layer()) .WithFrame( frame => { hostFrame.OnNext(frame); return frame; }); })); }
private LayoutTracker CreateSymbols(Term term, Transform parent, List <int> path, int index) { return(term.Match <LayoutTracker>(l => { LayoutTracker symbol = Instantiate(parenSymbol, parent); symbol.root = skeletonRoot; symbol.index = path.Append(index).ToList(); LayoutRebuilder.ForceRebuildLayoutImmediate(parent.GetComponent <RectTransform>()); Canvas.ForceUpdateCanvases(); for (var i = 0; i < l.Count; i++) { CreateSymbols(l[i], symbol.transform, path.Append(index).ToList(), i); } return symbol; }, v => { var symbol = Instantiate(GetSymbol(v), parent); symbol.index = path.Append(index).ToList(); symbol.root = skeletonRoot; return symbol; })); }
public void addParens(List <int> path, int size, LayoutTracker paren, Shrub <Sum <Combinator, Variable> > newTerm) { StartCoroutine(smt.GetComponent <SymbolManager>().BackApplyParens(path, size, paren, smt.currentLayout, newTerm)); }
public void unApply(Shrub <Sum <Combinator, Variable> > newTerm, LayoutTracker lt, Combinator C, List <int> path) { StartCoroutine(smt.GetComponent <SymbolManager>().UnTransition(newTerm, lt, C, path, smt.currentLayout)); goal = newTerm; CheckSuccess(); }
public void HandleClick(SymbolManager manager, Shrub <Sum <Combinator, Variable> > term, List <int> path, LayoutTracker root) { print("Click happened"); }
public IEnumerator _UnTransition(Term newTerm, LayoutTracker lt, Combinator C, List <int> path, LayoutTracker TopSymbol) { forwardUndoStack.Push(new ForwardData(Sum <ElimRule, AddParenRule> .Inl(new CombinatorElim(C, path)), TopSymbol)); /* * REMEMBER, you've already "typechecked" this operation, you can assume that everything fits * Get transform at path * Grab transforms at the first occurence of each debruijn index * Delete everything else * spawn metavariables * order everything appropriately */ Transform target = AccessTransfrom(TopSymbol.transform, path); (var debruijn, var arity) = Util.ParseCombinator(C) .Match( pi => pi, u => throw new Exception(u.ToString()) ); debruijn.Match(d => { d = d.ToList(); for (int i = d.Count; i < target.childCount; i++) { d.Add(Shrub <int> .Leaf(arity)); arity++; } debruijn = Shrub <int> .Node(d); }, x => { var d = new List <Shrub <int> >(); d.Add(Shrub <int> .Leaf(x)); for (int i = d.Count; i < target.childCount; i++) { d.Add(Shrub <int> .Leaf(arity)); arity++; } debruijn = Shrub <int> .Node(d); }); Transform[] children = new Transform[arity]; debruijn.IterateI(new List <int>(), (i, p) => { children[i] = AccessTransfrom(target, p, t => t, () => null); }); var canvas = GetComponentInParent <Canvas>(); foreach (var child in children) { child?.SetParent(canvas.transform, true); } foreach (Transform t in target) { Destroy(t.gameObject); } lt.LockDown(.1f); lt.transform.SetParent(target, true); foreach (var child in children) { if (!child) { var meta = Instantiate(GetSymbol(Sum <Combinator, Variable> .Inr((Variable)(-1))), target); meta.root = skeletonRoot; } else { child.SetParent(target, true); } } foreach (Transform t in skeletonRoot) { Destroy(t.gameObject); } CreateSkeleton(newTerm, skeletonRoot); yield return(new WaitUntil(() => { bool moving = false; IterateTransform(TopSymbol.transform, t => { if (t.GetComponent <LayoutTracker>()) { moving |= t.GetComponent <LayoutTracker>().Moving(); } }); return !moving; })); }
public IEnumerator UnTransition(Term newTerm, LayoutTracker lt, Combinator C, List <int> path, LayoutTracker TopSymbol) { backwardUndoStack = new Stack <Sum <BackwardTermData, BackwardParenData> >(); yield return(_UnTransition(newTerm, lt, C, path, TopSymbol)); }
public IEnumerator BackApplyParens(List <int> path, int size, LayoutTracker paren, LayoutTracker TopSymbol, Term newTerm) { backwardUndoStack = new Stack <Sum <BackwardTermData, BackwardParenData> >(); yield return(_BackApplyParens(path, size, paren, TopSymbol, newTerm)); }
public ForwardData(Sum <ElimRule, AddParenRule> rule, LayoutTracker topSymbol) { this.rule = rule; TopSymbol = topSymbol; }
public void CreateTerm() { currentLayout = CreateTermHelper().Item2; }
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; })); }