private static int ScatterSort(ObjectCollectionNode circle1, ObjectCollectionNode circle2) { float distance1 = (circle1.Transform.localPosition).sqrMagnitude; float distance2 = (circle2.Transform.localPosition).sqrMagnitude; return(distance1.CompareTo(distance2)); }
/// <summary> /// Update the facing of a node given the nodes new position for facing origin with node and orientation type /// </summary> protected void UpdateNodeFacing(ObjectCollectionNode node) { Vector3 centerAxis; Vector3 pointOnAxisNearestNode; switch (OrientType) { case OrientationType.FaceOrigin: node.Transform.rotation = Quaternion.LookRotation(node.Transform.position - transform.position, transform.up); break; case OrientationType.FaceOriginReversed: node.Transform.rotation = Quaternion.LookRotation(transform.position - node.Transform.position, transform.up); break; case OrientationType.FaceCenterAxis: centerAxis = Vector3.Project(node.Transform.position - transform.position, transform.up); pointOnAxisNearestNode = transform.position + centerAxis; node.Transform.rotation = Quaternion.LookRotation(node.Transform.position - pointOnAxisNearestNode, transform.up); break; case OrientationType.FaceCenterAxisReversed: centerAxis = Vector3.Project(node.Transform.position - transform.position, transform.up); pointOnAxisNearestNode = transform.position + centerAxis; node.Transform.rotation = Quaternion.LookRotation(pointOnAxisNearestNode - node.Transform.position, transform.up); break; case OrientationType.FaceParentFoward: node.Transform.forward = transform.rotation * Vector3.forward; break; case OrientationType.FaceParentForwardReversed: node.Transform.forward = transform.rotation * Vector3.back; break; case OrientationType.FaceParentUp: node.Transform.forward = transform.rotation * Vector3.up; break; case OrientationType.FaceParentDown: node.Transform.forward = transform.rotation * Vector3.down; break; case OrientationType.None: break; default: Debug.LogWarning("OrientationType out of range"); break; } }
/// <summary> /// Overriding base function for laying out all the children when UpdateCollection is called. /// </summary> protected override void LayoutChildren() { float startOffsetX; float startOffsetY; Vector3[] nodeGrid = new Vector3[NodeList.Count]; Vector3 newPos; // Now lets lay out the grid Columns = Mathf.CeilToInt((float)NodeList.Count / Rows); startOffsetX = (Columns * 0.5f) * CellWidth; startOffsetY = (Rows * 0.5f) * CellHeight; HalfCell = new Vector2(CellWidth * 0.5f, CellHeight * 0.5f); // First start with a grid then project onto surface ResolveGridLayout(nodeGrid, startOffsetX, startOffsetY, Layout); // Get randomized planar mapping // Calculate radius of each node while we're here // Then use the packer function to shift them into place for (int i = 0; i < NodeList.Count; i++) { ObjectCollectionNode node = NodeList[i]; newPos = VectorExtensions.ScatterMapping(nodeGrid[i], Radius); Collider nodeCollider = NodeList[i].Transform.GetComponentInChildren <Collider>(); if (nodeCollider != null) { // Make the radius the largest of the object's dimensions to avoid overlap Bounds bounds = nodeCollider.bounds; node.Radius = Mathf.Max(Mathf.Max(bounds.size.x, bounds.size.y), bounds.size.z) * 0.5f; } else { // Make the radius a default value node.Radius = 1f; } node.Transform.localPosition = newPos; UpdateNodeFacing(node); NodeList[i] = node; } // Iterate [x] times for (int i = 0; i < 100; i++) { IterateScatterPacking(NodeList, Radius); } }
/// <summary> /// Overriding base function for laying out all the children when UpdateCollection is called. /// </summary> protected override void LayoutChildren() { var nodeGrid = new Vector3[NodeList.Count]; Vector3 newPos; // Now lets lay out the grid if (Layout == LayoutOrder.RowThenColumn) { columns = Mathf.CeilToInt((float)NodeList.Count / rows); } else if (Layout == LayoutOrder.ColumnThenRow) { rows = Mathf.CeilToInt((float)NodeList.Count / columns); } HalfCell = new Vector2(CellWidth * 0.5f, CellHeight * 0.5f); // First start with a grid then project onto surface ResolveGridLayout(nodeGrid, layout); switch (SurfaceType) { case ObjectOrientationSurfaceType.Plane: for (int i = 0; i < NodeList.Count; i++) { ObjectCollectionNode node = NodeList[i]; newPos = nodeGrid[i]; newPos.z = distance; node.Transform.localPosition = newPos; UpdateNodeFacing(node); NodeList[i] = node; } break; case ObjectOrientationSurfaceType.Cylinder: for (int i = 0; i < NodeList.Count; i++) { ObjectCollectionNode node = NodeList[i]; newPos = VectorExtensions.CylindricalMapping(nodeGrid[i], radius); node.Transform.localPosition = newPos; UpdateNodeFacing(node); NodeList[i] = node; } break; case ObjectOrientationSurfaceType.Sphere: for (int i = 0; i < NodeList.Count; i++) { ObjectCollectionNode node = NodeList[i]; newPos = VectorExtensions.SphericalMapping(nodeGrid[i], radius); node.Transform.localPosition = newPos; UpdateNodeFacing(node); NodeList[i] = node; } break; case ObjectOrientationSurfaceType.Radial: int curColumn = 0; int curRow = 1; for (int i = 0; i < NodeList.Count; i++) { ObjectCollectionNode node = NodeList[i]; newPos = VectorExtensions.RadialMapping(nodeGrid[i], radialRange, radius, curRow, rows, curColumn, Columns); if (curColumn == (Columns - 1)) { curColumn = 0; ++curRow; } else { ++curColumn; } node.Transform.localPosition = newPos; UpdateNodeFacing(node); NodeList[i] = node; } break; } }