예제 #1
0
    private void GenerateConstraintChains()
    {
        rails.Clear();
        for (int l = 0; l < HConstraints.Length; ++l) {
            var constraint = HConstraints[l];
            if (!rails.Contains(constraint.Left)) rails.Add(constraint.Left);
            if (!rails.Contains(constraint.Right)) rails.Add(constraint.Right);
        }
        for (int e = 0; e < Edges.Length; ++e) {
            var edge = Edges[e];
            if (!rails.Contains(edge)) rails.Add(edge);
        }
        for (int r = 0; r < rails.Count; ++r) {
            rails[r]._chains.Clear();
        }
        for (int t = 0; t < 10; ++t) {
            bool changed = false;
            for (int c = 0; c < HConstraints.Length; ++c) {
                var constraint = HConstraints[c];
                if (constraint._CanFlex) {
                    for (int d = 0; d < 2; ++d) {
                        var rail = d == 0 ? constraint.Left : constraint.Right;
                        var destR = constraint.Other(rail);
                        if (!float.IsNaN(destR._value)) continue;
                        // Prevent constraint chains from looping back on themselves
                        // Ignore constraints that arent anchored to fixed
                        // No such chain can be created?!
                        // Only one chain per source? So two pathways always uses the most forceful one?
                        // If two sources, then obviously itll include both sources
                        // hmmm

                        // Propagate from rail to other

                        if (float.IsNaN(rail._value)) {
                            // If rail is completely unknown, ignore for now
                            if (rail._chains.Count == 0) continue;

                            // NOTE: Not possible for a current chain to be the same
                            // as the new chain but longer
                            for (int r = 0; r < rail._chains.Count; ++r) {
                                var rchain = rail._chains[r];

                                bool hasChain = false;
                                // If the current constraint chain already passes the rail `destR`
                                for (int rc = 0; rc < rchain.Constraints.Count; ++rc) {
                                    if (rchain.Constraints[rc].Constraint.HasEdge(destR)) hasChain = true;
                                }
                                if (!hasChain) {
                                    // Check if `other` has any chains that are the same as the one we're about to add
                                    for (int o = 0; o < destR._chains.Count; ++o) {
                                        var dchain = destR._chains[o];
                                        if (dchain.Rail == rchain.Rail &&
                                            dchain.Constraints.Count == rchain.Constraints.Count + 1 &&
                                            dchain.OverlapLength(rchain) == rchain.Constraints.Count &&
                                            dchain.Constraints[rchain.Constraints.Count].Constraint == constraint) {
                                            hasChain = true;
                                            break;
                                        }
                                    }
                                }
                                // If a similar chain was not found, add it
                                if (!hasChain) {
                                    var newChain = new InfluenceChain(rchain.Rail);
                                    for (int rc = 0; rc < rchain.Constraints.Count; ++rc)
                                        newChain.Constraints.Add(rchain.Constraints[rc]);
                                    newChain.Constraints.Add(new InfluenceValue(constraint, constraint.Right == rail));
                                    destR._chains.Add(newChain);
                                    changed = true;
                                }
                            }
                        } else {
                            bool hasValue = false;
                            for (int o = 0; o < destR._chains.Count; ++o) {
                                var dchain = destR._chains[o];
                                for (int cc = 0; cc < dchain.Constraints.Count; ++cc) {
                                    if (dchain.Constraints[cc].Constraint == constraint) { hasValue = true; break; }
                                }
                            }
                            if (!hasValue) {
                                var newChain = new InfluenceChain(rail);
                                newChain.Constraints.Add(new InfluenceValue(constraint, constraint.Right == rail));
                                destR._chains.Add(newChain);
                                changed = true;
                            }
                        }
                    }
                }
            }
            if (!changed) break;
            if (t == 9) {
                Debug.LogError("Spun out!");
            }
        }
    }
예제 #2
0
 public int OverlapLength(InfluenceChain other)
 {
     int len = Mathf.Min(Constraints.Count, other.Constraints.Count);
     for (int c = 0; c < len; ++c) {
         if (Constraints[c].Constraint != other.Constraints[c].Constraint) return c;
     }
     return len;
 }