// ----------------------- protected Vector2 GetControlOffset() { if (this.canvas == null) { return(Vector2.zero); } List <TouchControl> controlList = this.panel.rig.GetTouchControls(); //Rect canvasRect = ((RectTransform)this.canvas.transform).rect; Rect panelRect = ((RectTransform)this.panel.transform).rect; float controlRad = this.GetControlSize() / 2.0f; float separation = Mathf.Min(panelRect.width, panelRect.height) * 0.01f; Vector2 anchorPos = Vector2.one * (controlRad + separation); Bounds worldBounds = CFUtils.GetWorldAABB(this.canvas.transform.localToWorldMatrix, BottomLeftToAnchorRelativeLocal(anchorPos), new Vector3(controlRad * 2, controlRad * 2, 0)); float worldControlRad = Mathf.Max(worldBounds.size.x, worldBounds.size.y) * 0.5f; Vector2 bestPos = anchorPos; float bestDist = 100; // closest distance to other controls bool bestPosFound = false; int ringCount = Mathf.Max(1, Mathf.CeilToInt((panelRect.width - separation) / ((controlRad * 2.0f) + separation)), //Factor)), Mathf.CeilToInt((panelRect.height - separation) / ((controlRad * 2.0f) + separation))); //Factor))); for (int ri = 0; ri < ringCount; ++ri) { float ringRad = separation + ((float)ri * ((controlRad * 2.0f) + separation)); //Factor); float controlArcAngle = GetArcAngle(ringRad, controlRad) * Mathf.Rad2Deg; int stepCount = (ringRad < 0.0001f) ? 1 : Mathf.Max(1, Mathf.CeilToInt(90 / controlArcAngle)); //float angleInc = controlArcAngle; //float angleOfs = ((90 - ((float)stepCount * angleInc)) * 0.5f) + (angleInc * 0.5f); if (stepCount <= 1) { // angleInc =0; // angleOfs = 0; } for (int si = 0; si < stepCount; ++si) { //float orbitAngle = (angleOfs + ((float)si * angleInc)) ; float orbitAngle = (stepCount < 2) ? 45 : (((float)(si) + 0) * (90.0f / (float)(stepCount - 1))); Vector2 pos = anchorPos + ((new Vector2(Mathf.Cos(orbitAngle * Mathf.Deg2Rad), Mathf.Sin(orbitAngle * Mathf.Deg2Rad))) * ringRad); //* separationFactor; if ((pos.x > panelRect.width) || (pos.y > panelRect.height)) { continue; } Vector2 worldPos = this.BottomLeftToAnchorRelativeWorldPos(pos); // this.canvas.transform.localToWorldMatrix.MultiplyPoint3x4((Vector3)pos); if (controlList.Count == 0) { break; } bool controlTested = false; float closestControlDist = -100000; Vector2 closestControlPos = Vector2.zero; for (int ci = 0; ci < controlList.Count; ++ci) { TouchControl c = controlList[ci]; if ((c is DynamicRegion) || CFUtils.IsStretchyRectTransform(c.transform)) { continue; } Bounds controlBounds = c.GetWorldSpaceAABB(); Vector2 testControlCen = controlBounds.center; Vector2 testControlSize = controlBounds.size; float testControlRad = Mathf.Max(testControlSize.x, testControlSize.y) / 2.0f; float curDist = (testControlCen - worldPos).magnitude - (testControlRad); if (!controlTested || ((curDist < closestControlDist))) { controlTested = true; closestControlDist = curDist; closestControlPos = pos; } } if (!controlTested) { } else { if (closestControlDist >= worldControlRad) { return(this.BottomLeftToAnchorRelativePos(closestControlPos)); } if (closestControlDist > 0) //-(worldControlRad * 0.5f)) { return(this.BottomLeftToAnchorRelativePos(closestControlPos)); } if (!bestPosFound || (closestControlDist > bestDist)) { bestPosFound = true; bestDist = closestControlDist; bestPos = closestControlPos; } } } } // If the control is almost fully covered by other controls, place it at default position... if (bestDist < -(worldControlRad * 0.9f)) { bestPos = anchorPos; } else { //Debug.Log("GetOffs : returning best IMPERFECTn pos : dist : " + bestDist + " pos: " + bestPos +" rad: " + controlRad + " worldRad: " + worldControlRad + " ctrlNear: " + ((bestControlNear==null)? "NULL" : bestControlNear.name) + "ctrlRad:" + bestControlRad); } return(this.BottomLeftToAnchorRelativePos(bestPos)); }