public static void ForEachConnection(System.Action <IStrokeConnection, Vector3> Event, StrokeCategory Category, float Distance, Vector3 CenterPosition, LayerMask Layers)
        {
            // check front,back,left,right
            IStrokeConnection TopPiece    = CheckForConnection(CenterPosition, Distance, Category, Vector3.forward, ConnectionDirection.Front, Layers, true);
            IStrokeConnection BottomPiece = CheckForConnection(CenterPosition, Distance, Category, -Vector3.forward, ConnectionDirection.Back, Layers, true);
            IStrokeConnection RightPiece  = CheckForConnection(CenterPosition, Distance, Category, Vector3.right, ConnectionDirection.Right, Layers, true);
            IStrokeConnection LeftPiece   = CheckForConnection(CenterPosition, Distance, Category, -Vector3.right, ConnectionDirection.Left, Layers, true);

            if (TopPiece != null)
            {
                Event.Invoke(TopPiece, Vector3.forward);
            }
            if (BottomPiece != null)
            {
                Event.Invoke(BottomPiece, -Vector3.forward);
            }
            if (RightPiece != null)
            {
                Event.Invoke(RightPiece, Vector3.right);
            }
            if (LeftPiece != null)
            {
                Event.Invoke(LeftPiece, -Vector3.right);
            }
        }
 public static IStrokeConnection CheckForConnection(Vector3 CenterPosition, float Distance, StrokeCategory Category, Vector3 WorldDirection, ConnectionDirection WorldConnectionDirection, LayerMask Mask, bool ShouldDebug = false, float DebugTime = 1f)
 {
     if (ShouldDebug)
     {
         Debug.DrawRay(CenterPosition, WorldDirection * Distance, Color.red, DebugTime);
     }                                       // check if should debug
     RaycastHit[] CastResults = Physics.RaycastAll(CenterPosition, WorldDirection, Distance, Mask);
     if (CastResults.Length > 0)             // check for object
     {
         for (int i = 0; i < CastResults.Length; i++)
         {
             IStrokeConnection Piece = CastResults[i].collider.transform.GetComponent <IStrokeConnection>(); // get stroke piece component of object
             if (Piece != null && Piece.StrokeCategory == Category)                                          // if is a stroke piece and of the same category
             // Check if has connection
             {
                 ConnectionDirection   InverseWorldDirection = VectorToDirection(-WorldDirection); // calculate inverse direction
                 ConnectionDirection[] WorldPieceConnections = Piece.WorldConnectionDirections;    // get world connection directions of piece
                 for (int x = 0; x < WorldPieceConnections.Length; x++)                            // check for connection match
                 {
                     if (WorldPieceConnections [x] == InverseWorldDirection)                       // found a matching connection
                     {
                         return(Piece);                                                            // return piece
                     }
                 }
             }
         }
     }
     return(null);
 }
        public static void GetStrokeStateInformation(Vector3 CenterPosition, float Distance, ConnectionDirection[] Connections, Vector3[] Directions, ModularStrokeSetData StrokeSet, System.Action <bool, StrokeType, int> Result)
        {
            if (Directions.Length > 0)                          // check if has any directions
            {
                float TotalAngles = 0f;                         // calculate total connection angles
                for (int i = 0; i < Directions.Length; i++)     // loop through all directions
                {
                    for (int x = 0; x < Directions.Length; x++) // loop through all directions
                    {
                        if (x != i)
                        {
                            TotalAngles += Vector3.Angle(Directions [i], Directions [x]);
                        }
                    }
                }                                                                                     // calculate angle and add to total angles

                StrokeType        Type     = (StrokeType)(int)(TotalAngles / Directions.Length);      // new stroke type
                IStrokeConnection SetPiece = StrokeSet.FindStrokePieceComponent(Type);

                if (SetPiece != null)
                {
                    int RotationY = CalculateMatchAngle(Connections, SetPiece.ConnectionDirections.ToArray());                     // calculate the angle to match
                    Result.Invoke(true, Type, RotationY);
                    return;
                }
            }
            Result.Invoke(false, StrokeType.Straight, 0);
        }
 public static void RemoveSelfFromConnections(this IStrokeConnection Self)
 {
     IStrokeConnection[] CurrentlyConnected = Self.CurrentlyConnected;
     for (int i = 0; i < CurrentlyConnected.Length; i++)
     {
         CurrentlyConnected [i].OnSurroundingRemoved(Self);
     }
 }
        public static HashSet <IStrokeConnection> UpdateCurrentlyConnected(this IStrokeConnection Self, HashSet <IStrokeConnection> CurrentlyConnected, float CheckDistance, Vector3 CenterPosition, LayerMask Layers)
        {
            HashSet <IStrokeConnection> TempConnections = new HashSet <IStrokeConnection> ();

            ModularPieceExtensions.ForEachConnection((IStrokeConnection Connection, Vector3 Pos) => {
                TempConnections.Add(Connection);
                if (!CurrentlyConnected.Contains(Connection))                 // new connection wasnt in last connections meaning its added
                {
                    Connection.OnSurroundingAdded(Self);
                }
            }, Self.StrokeCategory, CheckDistance, CenterPosition, Layers);

            foreach (IStrokeConnection Connection in CurrentlyConnected)
            {
                if (!TempConnections.Contains(Connection))                    // old connection is not in the new connections anymore meaning its gone
                {
                    Connection.OnSurroundingRemoved(Self);
                }
            }

            return(TempConnections);            // set temp connections
        }
 public void OnSurroundingAdded(IStrokeConnection Sender)
 {
     _CurrentConnections.Add(Sender);
     OnChangedEvent();
 }
 public void OnSurroundingRemoved(IStrokeConnection Sender)
 {
     _CurrentConnections.Remove(Sender);
     OnChangedEvent();
 }