Ejemplo n.º 1
0
    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;
        }));
    }
Ejemplo n.º 2
0
    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;
        }));
    }