public void SetEdge(int d, UIRail rail) { switch (d) { case 0: Left = rail; break; case 1: Top = rail; break; case 2: Right = rail; break; case 3: Bottom = rail; break; } }
public ConstraintChain(List<UIConstraint> constraints) { Constraints = constraints; Start = Constraints[0].Left; if (Constraints.Count >= 2) Start = Constraints[1].HasEdge(Constraints[0].Left) ? Constraints[0].Right : Constraints[0].Left; MinCollapseId = int.MaxValue; MaxCollapseId = int.MinValue; End = Start; for (int c = 0; c < Constraints.Count; ++c) { MinCollapseId = Mathf.Min(MinCollapseId, Constraints[c].CollapseId); MaxCollapseId = Mathf.Max(MaxCollapseId, Constraints[c].CollapseId); End = Constraints[c].Other(End); } }
public UIRail Other(UIRail rail) { if (Left == rail) return Right; if (Right == rail) return Left; return null; }
public bool HasEdge(UIRail rail) { return Left == rail || Right == rail; }
private void Arrange(UIRail left, UIRail right) { GenerateConstraintChains(); bool[] offMask = new bool[100]; //var minColId = activeChains.SelectMany(c => c.Constraints).Min(c => c.CollapseId); //var maxColId = activeChains.SelectMany(c => c.Constraints).Max(c => c.CollapseId); int maxColId = 2, minColId = -2; for (int i = maxColId; i >= minColId; --i) { for (int r = 0; r < rails.Count; ++r) { var rail = rails[r]; if (rail._chains.Count == 0 || !float.IsNaN(rail._value)) continue; var activeChains = rail._chains; // If `i` collapse id would result in no overlap, continue down (include more constraints) if (i > minColId) { float minLimit, maxLimit; GetLimitRange(rail, i, out minLimit, out maxLimit); //Debug.Log(i + ": " + minLimit + " -- " + maxLimit); if (maxLimit >= minLimit) { // If point is fixed (and valid) with this collapseId // force the rail position if (minLimit == maxLimit) { rail._value = (minLimit + maxLimit) / 2; //if (rail.name == "M2") { //Debug.Log(rail.name + " @" + i); //} } continue; } } for (int c1 = 0; c1 < activeChains.Count; ++c1) offMask[c1] = false; var value = float.NaN; for (int t = 0; t < 10; ++t) { float sumValue = 0; float valueTotal = 0; float divisor = 0; // Need to remove constraints that negatively impact value // (ie. constraints that pull it toward its own limit) for (int c1 = 0; c1 < activeChains.Count; ++c1) { var chain = activeChains[c1]; if (offMask[c1]) continue; valueTotal += chain.GetLength(i); } for (int c1 = 0; c1 < activeChains.Count; ++c1) { var chain = activeChains[c1]; if (offMask[c1]) continue; //Debug.Log(chain.Constraints[0].Constraint.name + ": " + chain.GetEndValue(i) + " -- " + chain.LeftCollapseId + " - " + chain.RightCollapseId); var amount = (valueTotal - chain.GetLength(i) + 0.001f); sumValue += chain.GetEndValue(i) * amount; divisor += amount; } value = sumValue / divisor; //if (rail.name == "M2") { //Debug.Log(rail.name + "=" + value + " @" + i); //} bool changed = false; for (int c1 = 0; c1 < activeChains.Count; ++c1) { var chain = activeChains[c1]; if (offMask[c1]) continue; float minLimit, maxLimit; chain.GetLimits(i, out minLimit, out maxLimit); if (value > minLimit && value < maxLimit) { offMask[c1] = true; changed = true; } } if (!changed) break; } { float minLimit, maxLimit; GetLimitRange(rail, i + 1, out minLimit, out maxLimit); if (maxLimit < minLimit) Debug.LogError("Limit range exception!"); value = Mathf.Clamp(value, minLimit, maxLimit); } rail._value = value; } } }
void GetLimitRange(UIRail rail, int collapseId, out float minLimit, out float maxLimit) { var chains = rail._chains; minLimit = float.MinValue; maxLimit = float.MaxValue; for (int c1 = 0; c1 < chains.Count; ++c1) { var chain = chains[c1]; float cMinLimit, cMaxLimit; chain.GetLimits(collapseId, out cMinLimit, out cMaxLimit); minLimit = Mathf.Max(minLimit, cMinLimit); maxLimit = Mathf.Min(maxLimit, cMaxLimit); } /*if (rail.name == "M2") { Debug.Log("@" + collapseId + " " + minLimit + " -- " + maxLimit + " with " + chains.Count + " C:" + chains.Select(c => c.ToString()).Aggregate((c1, c2) => c1 + ", " + c2)); }*/ }
public UIRail NewRail(string name, UIRail.Directions dir) { var rail = new GameObject().AddComponent<UIRail>(); rail.name = name; rail.transform.parent = transform; rail.Direction = dir; return rail; }
public UIConstraint NewConstraint(UIRail left, UIRail right, float width, int collapseId) { var constraint = new GameObject().AddComponent<UIConstraint>(); constraint.Left = left; constraint.Right = right; constraint.Width = width; constraint.CollapseId = collapseId; constraint.name = "_C" + left.name + "-" + right.name; constraint.transform.parent = transform; return constraint; }
public UIRail Other(UIRail rail) { if (Start == rail) return End; if (End == rail) return Start; return null; }
void Start() { UI = GetComponent <UIRail>(); }
public InfluenceChain(UIRail rail) { Rail = rail; }