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!"); } } }
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; }