Exemple #1
0
        /// <summary>
        /// Creates a deep copy of this class
        /// </summary>
        /// <returns>Returns a deep copy of this class</returns>
        public SPieceInfo MakeCopy()
        {
            SPieceInfo Temp = new SPieceInfo(_ID);

            foreach (SJointInfo item in _Joints)
            {
                Temp.AddJoint(item);
            }

            return(Temp);
        }
        /// <summary>
        /// Generate puzzle pieces from image.
        /// </summary>
        /// <param name="NoOfPiecesInRow">Total no of pieces in row of puzzle / total columns</param>
        /// <param name="NoOfPiecesInCol">Total no of pieces in Col of puzzle / total rows</param>
        /// <param name="Image">Main image for puzzle</param>
        /// <param name="JointMaskImage">Mask images for joints to be used to create joints for pieces in this puzzle</param>
        /// <param name="CreatedImageMask">Unknown</param>
        /// <returns>Returns generated pieces metadata</returns>
        private SPieceInfo[,] GenerateJigsawPieces(Texture2D Image, Texture2D[] JointMaskImage, out Texture2D CreatedImageMask, int NoOfPiecesInRow, int NoOfPiecesInCol)
        {

#region "Argument Error Checking"

            if (NoOfPiecesInRow < 2)
            {
                throw new System.ArgumentOutOfRangeException("NoOfPiecesInRow", "Argument should be greater then 1");
            }
            else if (NoOfPiecesInCol < 2)
            {
                throw new System.ArgumentOutOfRangeException("NoOfPiecesInCol", "Argument should be greater then 1");
            }
            else if (Image == null)
            {
                throw new System.ArgumentNullException("No texture2d assigned to this class");
            }

#endregion

            

            _noOfPiecesInRow = NoOfPiecesInRow;
            _noOfPiecesInCol = NoOfPiecesInCol;

            _origionalImage = Image;

            Color[][] _PuzzleImageTopJointMask = HelperMethods.Texture2DToColorArr(Image);
            Color[][] _PuzzleImageBotJointMask = HelperMethods.Texture2DToColorArr(Image);
            Color[][] _PuzzleImageLeftJointMask = HelperMethods.Texture2DToColorArr(Image);
            Color[][] _PuzzleImageRightJointMask = HelperMethods.Texture2DToColorArr(Image);
            Color[][] _PuzzleImage = HelperMethods.Texture2DToColorArr(Image);


            SPieceInfo[,] PiecesInformation = null;


            PiecesInformation = DrawCustomPieceJointsMask(ref _PuzzleImageTopJointMask, ref _PuzzleImageBotJointMask,
                    ref _PuzzleImageLeftJointMask, ref _PuzzleImageRightJointMask,
                    JointMaskImage,  out _pieceWidthWithoutJoint,
                    out _pieceHeightWithoutJoint,Image.width, Image.height, NoOfPiecesInCol, NoOfPiecesInRow);
            


            CreatedImageMask = HelperMethods.ColorArrToTexture2D(_PuzzleImageTopJointMask);

            //Create mask image for each side joints
            JointsMaskToJointsImage(ref _PuzzleImage, ref _PuzzleImageTopJointMask,ref  _PuzzleImageBotJointMask,
                ref _PuzzleImageLeftJointMask, ref _PuzzleImageRightJointMask,
                PieceWidthWithoutJoint, PieceHeightWithoutJoint, Image.width, Image.height);

            _topJointsMaskImage = HelperMethods.ColorArrToTexture2D(_PuzzleImageTopJointMask);
            _botJointsMaskImage = HelperMethods.ColorArrToTexture2D(_PuzzleImageBotJointMask);
            _leftJointsMaskImage = HelperMethods.ColorArrToTexture2D(_PuzzleImageLeftJointMask);
            _rightJointsMaskImage = HelperMethods.ColorArrToTexture2D(_PuzzleImageRightJointMask);

            _image = HelperMethods.ColorArrToTexture2D(_PuzzleImage);
            

            //Return data for puzzle pieces
            SPieceInfo[,] ResultData = new SPieceInfo[NoOfPiecesInCol, NoOfPiecesInRow];
            for (int i = 0; i < NoOfPiecesInCol; i++)
                for (int j = 0; j < NoOfPiecesInRow; j++)
                    ResultData[i, j] = PiecesInformation[i, j];

            return ResultData;

        }
 public SPieceMetaData(SPieceInfo MetaData, Texture2D Image)
 {
     PieceMetaData = MetaData;
     PieceImage = Image;
 }
        private SPieceInfo[,] DrawCustomPieceJointsMask(ref Color[][] Image, Texture2D[] JointMaskImage,
                out int PieceWidthWithoutJoint, out int PieceHeightWithoutJoint, int PuzzleImgWidth, int PuzzleImgHeight, int Rows = 5, int Cols = 5)
        {

            //Create direction wise mask images
            Texture2D[] LeftJointMask = new Texture2D[JointMaskImage.Length];
            int[] LeftJointMaskWidth = new int[JointMaskImage.Length];
            int[] LeftJointMaskHeight = new int[JointMaskImage.Length];

            Texture2D[] RightJointMask = new Texture2D[JointMaskImage.Length];
            int[] RightJointMaskWidth = new int[JointMaskImage.Length];
            int[] RightJointMaskHeight = new int[JointMaskImage.Length];

            Texture2D[] TopJointMask = new Texture2D[JointMaskImage.Length];
            int[] TopJointMaskWidth = new int[JointMaskImage.Length];
            int[] TopJointMaskHeight = new int[JointMaskImage.Length];

            Texture2D[] BottomJointMask = new Texture2D[JointMaskImage.Length];
            int[] BottomJointMaskWidth = new int[JointMaskImage.Length];
            int[] BottomJointMaskHeight = new int[JointMaskImage.Length];


            SPieceInfo[,] ResultPiecesData = new SPieceInfo[Rows, Cols];

            //Initialize pieces data
            for (int i = 0; i < Rows; i++)
                for (int j = 0; j < Cols; j++)
                    ResultPiecesData[i, j] = new SPieceInfo((i * Cols) + j);
            
            int PieceHeight = PuzzleImgHeight / Rows;
            int PieceWidth = PuzzleImgWidth / Cols;

            PieceWidthWithoutJoint = PieceWidth;
            PieceHeightWithoutJoint = PieceHeight;



            for (int ArrayTav = 0; ArrayTav < JointMaskImage.Length; ArrayTav++)
            {
                LeftJointMask[ArrayTav] = JointMaskImage[ArrayTav];
                RightJointMask[ArrayTav] = rotateImage(JointMaskImage[ArrayTav], 180);
                TopJointMask[ArrayTav] = rotateImage(JointMaskImage[ArrayTav], 270);
                BottomJointMask[ArrayTav] = rotateImage(JointMaskImage[ArrayTav], 90);

#region "Resize Joint mask images for drawing inside mask image And calculate joints width and height"

                //Resize Joint mask images for drawing inside mask image
                //  Image will be resized according to piece width
                int MaskImageWidth = (int)(PieceWidth * 0.3f);
                int MaskImageHeight = (int)((float)MaskImageWidth / ((float)JointMaskImage[ArrayTav].width / (float)JointMaskImage[ArrayTav].height));

                LeftJointMask[ArrayTav] = resizeImage(LeftJointMask[ArrayTav], MaskImageWidth, MaskImageHeight);
                RightJointMask[ArrayTav] = resizeImage(RightJointMask[ArrayTav], MaskImageWidth, MaskImageHeight);
                TopJointMask[ArrayTav] = resizeImage(TopJointMask[ArrayTav], MaskImageWidth, MaskImageHeight);
                BottomJointMask[ArrayTav] = resizeImage(BottomJointMask[ArrayTav], MaskImageWidth, MaskImageHeight);

                
                //Calculate joints width and heights
                CalculateCustomJointDimensions(LeftJointMask[ArrayTav], out LeftJointMaskWidth[ArrayTav], out LeftJointMaskHeight[ArrayTav]);
                
                RightJointMaskWidth[ArrayTav] = LeftJointMaskWidth[ArrayTav];
                RightJointMaskHeight[ArrayTav] = LeftJointMaskHeight[ArrayTav];

                TopJointMaskWidth[ArrayTav] = LeftJointMaskHeight[ArrayTav];
                TopJointMaskHeight[ArrayTav] = LeftJointMaskWidth[ArrayTav];

                BottomJointMaskWidth[ArrayTav] = LeftJointMaskHeight[ArrayTav];
                BottomJointMaskHeight[ArrayTav] = LeftJointMaskWidth[ArrayTav];
                
                
                /*
                //Save these image
                saveTexture2D(LeftJointMask[ArrayTav], "c:\\Images\\LeftJoint.png");
                saveTexture2D(RightJointMask[ArrayTav], "c:\\Images\\RightJointMask.png");
                saveTexture2D(TopJointMask[ArrayTav], "c:\\Images\\TopJointMask.png");
                saveTexture2D(BottomJointMask[ArrayTav], "c:\\Images\\BottomJointMask.png");
                */

#endregion

            }




#region "Argument Error Checking"

            //Joint mask image width and height should be same
            //Joint mask image should have only black and white pixels inside it

            if (JointMaskImage[0].width != JointMaskImage[0].height)
            {
                Debug.LogError("JointMaskImage width and height should be same");
                return null;
            }
            else
            {
                bool ErrorFound = false;  //If Non-Black or Non-White pixel found

                //Check for pixel colors in joint mask image
                for (int rowtrav = 0; rowtrav < JointMaskImage[0].height && !ErrorFound; rowtrav++)
                {
                    for (int coltrav = 0; coltrav < JointMaskImage[0].width && !ErrorFound; coltrav++)
                    {
                        Color PixelColor = JointMaskImage[0].GetPixel(coltrav, rowtrav);

                        if (PixelColor != Color.white || PixelColor != Color.black)
                        {
                            ErrorFound = true;

                            //Debug.LogError("Only white and black pixels are allowed in JointMaskImage");

                            //return null;
                        }
                    }
                }


            }

#endregion

            Color[][] CreatedMaskImage = new Color[PuzzleImgWidth][];
            
            //Clear Instantiated mask image
            for (int i = 0; i < PuzzleImgWidth; i++)
            {
                CreatedMaskImage[i] = new Color[PuzzleImgHeight];
                for (int j = 0; j < PuzzleImgHeight; j++)
                {
                    CreatedMaskImage[i][j] = Color.white;
                }
            }


#region "Color Pieces Alternatively And Generate random joint info And Draw joints"

            bool AlternatePiece = true;

            //if (ColorPieces)
            {
                Random.seed = System.DateTime.Now.Second;

                for (int RowTrav = 0; RowTrav < Rows; RowTrav++)
                {

                    for (int ColTrav = 0; ColTrav < Cols; ColTrav++)
                    {
                        int PieceX = ColTrav * PieceWidth;
                        int PieceY = RowTrav * PieceHeight;
                        Color PieceColor = AlternatePiece ? Color.green : Color.red;

                        for (int InternalRowTrav = PieceY; InternalRowTrav < PieceY + PieceHeight; InternalRowTrav++)
                            for (int InternalColTrav = PieceX; InternalColTrav < PieceX + PieceWidth; InternalColTrav++)
                                if (CreatedMaskImage[InternalColTrav][InternalRowTrav] == Color.white)
                                    CreatedMaskImage[InternalColTrav][InternalRowTrav] = PieceColor;


#region "Generate Random joint info and Draw Joints From Mask Image"


#region "Draw right joints according to piece joint information"

                        if (ColTrav < Cols - 1)
                        {
                            int SelectedRandomJoint = Random.Range(1, JointMaskImage.Length) - 1;

                            //Create random joint information
                            int RndVal = (int)(Random.Range(1f, 18f) >= 10 ? 1 : 0);
                            ResultPiecesData[RowTrav, ColTrav].AddJoint(new SJointInfo((EJointType)RndVal, EJointPosition.Right, 
                                            RightJointMaskWidth[SelectedRandomJoint], RightJointMaskHeight[SelectedRandomJoint]));


                            int JointX = PieceX + PieceWidth - 5;
                            int JointY = PieceY + (PieceHeight / 2) - (RightJointMask[SelectedRandomJoint].height / 2);

                            bool Result = false;
                            SJointInfo RightJointInfo = ResultPiecesData[RowTrav, ColTrav].GetJoint(EJointPosition.Right, out Result);

                            if (!Result)
                            {
                                Debug.LogError("Logical error in draw joints from mask image Right Joints");
                            }
                            else
                            {
                                if ( RightJointInfo.JointType == EJointType.Male )
                                    drawJoint(ref CreatedMaskImage, RightJointMask[SelectedRandomJoint], PieceColor, JointX, JointY);
                            }

                        }
#endregion

#region"Draw left joints according to piece joint information"

                        if (ColTrav > 0)
                        {
                            int SelectedRandomJoint = Random.Range(1, JointMaskImage.Length) - 1;

                            //Create random joint information
                            bool Result = false;

                            SJointInfo PreviousRightJoint = ResultPiecesData[RowTrav, ColTrav - 1].GetJoint(EJointPosition.Right, out Result);

                            if (Result == false)
                            {
                                Debug.LogError("Logical error in joints information left joint");
                            }
                            else
                            {
                                SJointInfo CalcLeftJoint = new SJointInfo(PreviousRightJoint.JointType == EJointType.Female ?
                                            EJointType.Male : EJointType.Female, EJointPosition.Left, 
                                            LeftJointMaskWidth[SelectedRandomJoint], LeftJointMaskHeight[SelectedRandomJoint]);
                                ResultPiecesData[RowTrav , ColTrav].AddJoint(CalcLeftJoint);
                            }


                            int JointX = PieceX - LeftJointMask[SelectedRandomJoint].width + 5;
                            int JointY = PieceY + (PieceHeight / 2) - (LeftJointMask[SelectedRandomJoint].height / 2);

                            Result = false;
                            SJointInfo LeftJointInfo = ResultPiecesData[RowTrav, ColTrav].GetJoint(EJointPosition.Left, out Result);

                            if (!Result)
                            {
                                Debug.LogError("Logical error in draw joints from mask image Left Joints");
                            }
                            else
                            {
                                if (LeftJointInfo.JointType == EJointType.Male)
                                    drawJoint(ref CreatedMaskImage, LeftJointMask[SelectedRandomJoint], PieceColor, JointX, JointY);
                            }
                        }

#endregion

#region"Draw Top joints according to piece joint information"
                        
                        if (RowTrav < Rows - 1)
                        {
                            int SelectedRandomJoint = Random.Range(1, JointMaskImage.Length) - 1;

                            //Create random joint information
                            int RndVal = (int)(Random.Range(1f, 17f) >= 10 ? 1 : 0);
                            ResultPiecesData[RowTrav, ColTrav].AddJoint(new SJointInfo((EJointType)RndVal, EJointPosition.Top,
                                            TopJointMaskWidth[SelectedRandomJoint], TopJointMaskHeight[SelectedRandomJoint] ));

                            int JointX = PieceX + (PieceWidth / 2) - (TopJointMask[SelectedRandomJoint].width / 2);
                            int JointY = PieceY + PieceHeight - 5;

                            bool Result = false;
                            SJointInfo TopJointInfo = ResultPiecesData[RowTrav, ColTrav].GetJoint(EJointPosition.Top, out Result);

                            if (!Result)
                            {
                                Debug.LogError("Logical error in draw joints from mask image Top Joints");
                            }
                            else
                            {
                                if (TopJointInfo.JointType == EJointType.Male)
                                    drawJoint(ref CreatedMaskImage, TopJointMask[SelectedRandomJoint], PieceColor, JointX, JointY);
                            }

                        }
                        
#endregion

#region"Draw Bottom joints according to piece joint information"

                        if (RowTrav > 0)
                        {
                            int SelectedRandomJoint = Random.Range(1, JointMaskImage.Length) - 1;

                            //Create random joint information
                            bool Result = false;

                            SJointInfo PreviousPieceTopJoint = ResultPiecesData[RowTrav - 1, ColTrav].GetJoint(EJointPosition.Top, out Result);

                            if (Result == false)
                            {
                                Debug.LogError("Logical error in joints information Bottom joint");
                            }
                            else
                            {
                                SJointInfo CalcBottomJoint = new SJointInfo(PreviousPieceTopJoint.JointType == EJointType.Female ?
                                            EJointType.Male : EJointType.Female, EJointPosition.Bottom,
                                            BottomJointMaskWidth[SelectedRandomJoint], BottomJointMaskHeight[SelectedRandomJoint] );

                                ResultPiecesData[RowTrav, ColTrav].AddJoint(CalcBottomJoint);
                            }


                            int JointX = PieceX + (PieceWidth / 2) - (BottomJointMask[SelectedRandomJoint].width / 2);
                            int JointY = PieceY - BottomJointMask[SelectedRandomJoint].height;

                            Result = false;
                            SJointInfo BottomJointInfo = ResultPiecesData[RowTrav, ColTrav].GetJoint(EJointPosition.Bottom, out Result);

                            if (!Result)
                            {
                                Debug.LogError("Logical error in draw joints from mask image Top Joints");
                            }
                            else
                            {
                                if (BottomJointInfo.JointType == EJointType.Male)
                                    drawJoint(ref CreatedMaskImage, BottomJointMask[SelectedRandomJoint], PieceColor, JointX, JointY);
                            }

                        }

#endregion


#endregion


                        AlternatePiece = !AlternatePiece;
                    }

                    if (Cols % 2 == 0)
                        AlternatePiece = !AlternatePiece;
                }


            }

#endregion

            //Store mask image for testing purposes
            //System.IO.File.WriteAllBytes("c:\\Images\\MaskImage.png", CreatedMaskImage.EncodeToPNG());

            Image = CreatedMaskImage;

            
            return ResultPiecesData;
        }
        /// <summary>
        /// Load data from stream of file for puzzle maker.
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        private bool LoadStreamData(System.IO.Stream stream)
        {
            System.IO.BinaryReader bReader = null;

            try
            {
                using (bReader = new System.IO.BinaryReader(stream))
                {
                    //Get secret number to check file intigrity
                    int secretNumber = bReader.ReadInt32();
                    if (secretNumber != 6640330)
                    {
                        bReader.Close();
                        Debug.LogError("Error reading file. Make sure this file is created with puzzle maker`s current version");
                        return false;
                    }

                    //Get basic variables data
                    _NoOfPiecesInRow = bReader.ReadInt32();
                    _NoOfPiecesInCol = bReader.ReadInt32();

                    _PieceWidthWithoutJoint = bReader.ReadInt32();
                    _PieceHeightWithoutJoint = bReader.ReadInt32();

                    ColorPieces = bReader.ReadBoolean();


#region "Retrieve basic images"


                    int lengthImageEncoded = bReader.ReadInt32();
                    byte[] imageEncoded = bReader.ReadBytes(lengthImageEncoded);
                    _Image = new Texture2D(100, 100);
                    _Image.LoadImage(imageEncoded);


                    int lengthBackgroundImageEncoded = bReader.ReadInt32();
                    byte[] createdBackgroundImageEncoded = bReader.ReadBytes(lengthBackgroundImageEncoded);
                    _CreatedBackgroundImage = new Texture2D(100, 100);
                    _CreatedBackgroundImage.LoadImage(createdBackgroundImageEncoded);

#endregion


#region "Retrieve joint mask array"

                    int lengthJointMaskArr = bReader.ReadInt32();
                    _JointMask = new Texture2D[lengthJointMaskArr];
                    for (int i = 0; i < lengthJointMaskArr; i++)
                    {
                        int TempLength = bReader.ReadInt32();

                        _JointMask[i] = new Texture2D(100, 100);
                        byte[] TempMaskArr = bReader.ReadBytes(TempLength);
                        _JointMask[i].LoadImage(TempMaskArr);
                    }

#endregion


#region "Retreive Pieces Metadata"

                    _CreatedImagePiecesData = new SPieceMetaData[_NoOfPiecesInCol, _NoOfPiecesInRow];

                    for (int RowTrav = 0; RowTrav < _NoOfPiecesInCol; RowTrav++)
                    {
                        for (int ColTrav = 0; ColTrav < _NoOfPiecesInRow; ColTrav++)
                        {
                            int pieceID = bReader.ReadInt32();

                            //Get joints info
                            int JointInfoLength = bReader.ReadInt32();
                            SPieceInfo TempSPieceInfo = new SPieceInfo(pieceID);

                            for (int i = 0; i < JointInfoLength; i++)
                            {
                                int jointType = bReader.ReadInt32();
                                int jointWidth = bReader.ReadInt32();
                                int jointHeight = bReader.ReadInt32();
                                int jointPosition = bReader.ReadInt32();


                                TempSPieceInfo.AddJoint(new SJointInfo((EJointType)jointType, (EJointPosition)jointPosition,
                                                        jointWidth, jointHeight));
                            }

                            //Get this piece image
                            int pieceImgArrLength = bReader.ReadInt32();
                            byte[] pieceTempArr = bReader.ReadBytes(pieceImgArrLength);
                            Texture2D pieceTempImage = new Texture2D(100, 100);
                            pieceTempImage.LoadImage(pieceTempArr);
                            pieceTempImage.wrapMode = TextureWrapMode.Clamp;

                            //Insert this piece data in list
                            _CreatedImagePiecesData[RowTrav, ColTrav] = new SPieceMetaData(TempSPieceInfo, pieceTempImage);

                        }
                    }

#endregion

                    bReader.Close();

                }
            }
            catch (System.Exception ex)
            {
                throw new System.Exception("Exception in load data 2: " + ex.Message);
                //Debug.LogError("Puzzle Maker LoadData Method: " + ex.Message);
            }

            return true;
        }
    /// <summary>
    /// Called when piece is colliding from its bottom side
    /// </summary>
    /// <param name="CollidingPieceId">Id of piece colliding with</param>
    /// <param name="ColP">Instance of piece colliding with</param>
    /// <param name="ColPPieceData">Metadata of piece colliding with</param>
    /// <param name="ColObjController">JPPieceController instance of piece colliding with</param>
    void OnBottomCollision(int CollidingPieceId, GameObject ColP, SPieceInfo ColPPieceData, JPPieceController ColObjController)
    {
        
        //Check if this is child of current holding piece then apply collision logic
        bool IsChildOfHoldingPiece = false;

        JPPieceController[] ChildrenControllers = transform.GetComponentsInChildren<JPPieceController>();
        foreach (JPPieceController item in ChildrenControllers)
        {
            if (ThisPieceData.ID == item.ThisPieceData.ID)
            {
                IsChildOfHoldingPiece = true;
                break;
            }
        }


        if (ThisPieceData.ID == JpPuzzleControllerInstance.HoldingPieceID() || IsChildOfHoldingPiece)
        {

            //Get colliding piece position in grid
            int CPElementRow = 0;
            int CPElementCol = 0;
            PPPuzzleController.ArrayPosToRC(CollidingPieceId, JpPuzzleControllerInstance.PiecesInCol,
                            JpPuzzleControllerInstance.PiecesInRow, out CPElementRow, out CPElementCol);


            //Get this piece position in grid
            int PElementRow = 0;
            int PElementCol = 0;
            PPPuzzleController.ArrayPosToRC(ThisPieceData.ID, JpPuzzleControllerInstance.PiecesInCol,
                            JpPuzzleControllerInstance.PiecesInRow, out PElementRow, out PElementCol);


            if (ThisPieceData.ID > CollidingPieceId && PElementCol == CPElementCol && PElementRow == CPElementRow + 1)
            {
                //If is child of holding piece make it parent
                //Make this piece parent of all
                Transform Temp = transform.root;
                transform.parent = null;
                Temp.parent = transform;


                JpPuzzleControllerInstance.UnholdPiece();

                transform.position = new Vector3(ColP.transform.position.x,
                    ColP.transform.position.y + JpPuzzleControllerInstance.PieceHeightInWorld, ColP.transform.position.z);

                ColP.transform.root.parent = transform;

                OnPieceJoined();

                CheckForPuzzleComplete(transform);
            }

        }

    }
    /// <summary>
    /// Called when piece is colliding from its left side
    /// </summary>
    /// <param name="CollidingPieceId">Id of piece colliding with</param>
    /// <param name="ColP">Instance of piece colliding with</param>
    /// <param name="ColPPieceData">Metadata of piece colliding with</param>
    /// <param name="ColObjController">JPPieceController instance of piece colliding with</param>
    void OnLeftCollision(int CollidingPieceId, GameObject ColP, SPieceInfo ColPPieceData, JPPieceController ColObjController)
    {
        
        //Check if this is child of current holding piece then apply collision logic
        bool IsChildOfHoldingPiece = false;

        JPPieceController[] ChildrenControllers = transform.GetComponentsInChildren<JPPieceController>();
        foreach (JPPieceController item in ChildrenControllers)
        {
            if (ThisPieceData.ID == item.ThisPieceData.ID)
            {
                IsChildOfHoldingPiece = true;
                break;
            }
        }


        if (ThisPieceData.ID == JpPuzzleControllerInstance.HoldingPieceID() || IsChildOfHoldingPiece)
        {

            if (ThisPieceData.ID == CollidingPieceId + 1)
            {
                //If is child of holding piece make it parent
                //Make this piece parent of all
                Transform Temp = transform.root;
                transform.parent = null;
                Temp.parent = transform;


                JpPuzzleControllerInstance.UnholdPiece();

                transform.position = new Vector3(ColP.transform.position.x + JpPuzzleControllerInstance.PieceWidthInWorld,
                    ColP.transform.position.y, ColP.transform.position.z);

                ColP.transform.root.parent = transform;

                OnPieceJoined();

                CheckForPuzzleComplete(transform);
            }
        }
        
    }
    void OnBottomCollision(int CollidingPieceId, GameObject ColP, SPieceInfo ColPPieceData, JPPieceController ColObjController)
    {
        //Check if this is child of current holding piece then apply collision logic
        bool IsChildOfHoldingPiece = false;

        JPPieceController[] ChildrenControllers = transform.GetComponentsInChildren<JPPieceController>();
        foreach (JPPieceController item in ChildrenControllers)
        {
            if (ThisPieceData.ID == item.ThisPieceData.ID)
            {
                IsChildOfHoldingPiece = true;
                break;
            }
        }


        if (ThisPieceData.ID == JpPuzzleControllerInstance.HoldingPieceID() || IsChildOfHoldingPiece)
        {

            //Get colliding piece position in grid
            int CPElementRow = 0;
            int CPElementCol = 0;
            PPPuzzleController.ArrayPosToRC(CollidingPieceId, JpPuzzleControllerInstance.PiecesInCol,
                            JpPuzzleControllerInstance.PiecesInRow, out CPElementRow, out CPElementCol);


            //Get this piece position in grid
            int PElementRow = 0;
            int PElementCol = 0;
            PPPuzzleController.ArrayPosToRC(ThisPieceData.ID, JpPuzzleControllerInstance.PiecesInCol,
                            JpPuzzleControllerInstance.PiecesInRow, out PElementRow, out PElementCol);


            if (ThisPieceData.ID > CollidingPieceId && PElementCol == CPElementCol && PElementRow == CPElementRow + 1)
            {
                //If is child of holding piece make it parent
                //Make this piece parent of all
                Transform Temp = transform.root;
                transform.parent = null;
                Temp.parent = transform;


                JpPuzzleControllerInstance.UnholdPiece();

                Vector3 CalculatedPos = new Vector3();


                float LeftJointWorldScale = 0;
                float RightJointWorldScale = 0;
                float TopJointWorldScale = 0;
                float BotJointWorldScale = 0;

                float ColPLeftJointWorldScale = 0;
                float ColPRightJointWorldScale = 0;
                float ColPTopJointWorldScale = 0;
                float ColPBotJointWorldScale = 0;


                //Calculate required data
                CalculateDataForCollisionPlacement(ColPPieceData, out ColPLeftJointWorldScale, out ColPRightJointWorldScale,
                                        out ColPTopJointWorldScale, out ColPBotJointWorldScale);
                CalculateDataForCollisionPlacement(ThisPieceData, out LeftJointWorldScale, out RightJointWorldScale,
                                        out TopJointWorldScale, out BotJointWorldScale);


                //Calculate X
                CalculatedPos.x = ColP.transform.position.x - (ColPRightJointWorldScale / 2) + (ColPLeftJointWorldScale / 2) +
                                            (RightJointWorldScale / 2) - (LeftJointWorldScale / 2);

                //Calculate Y
                float CalcYWJ = ColP.transform.position.y + JpPuzzleControllerInstance.PieceHeightInWorld;
                CalculatedPos.y = CalcYWJ + (TopJointWorldScale / 2) - (BotJointWorldScale / 2)
                                                        - (ColPTopJointWorldScale / 2) + (ColPBotJointWorldScale / 2);


                CalculatedPos.z = transform.position.z;

                transform.position = CalculatedPos;

                ColP.transform.root.parent = transform;

                OnPieceJoined();

                CheckForPuzzleComplete(transform);
            }

        }
        
    }
Exemple #9
0
 public SPieceMetaData(SPieceInfo MetaData, Texture2D Image)
 {
     PieceMetaData = MetaData;
     PieceImage    = Image;
 }
        /// <summary>
        /// Loads puzzle data from file stream of .pm file
        /// </summary>
        /// <param name="stream">Stream to load data from</param>
        /// <returns>Returns true if data loading is successfull false otherwise</returns>
        private bool LoadStreamData(System.IO.Stream stream)
        {
            System.IO.BinaryReader bReader = null;

            try
            {
                using (bReader = new System.IO.BinaryReader(stream))
                {
                    //Get secret number to check file intigrity
                    int secretNumber = bReader.ReadInt32();
                    if (secretNumber != _secretVersionNo)
                    {
                        bReader.Close();
                        Debug.LogError("Error reading file. Make sure this file is created with puzzle maker`s current version");
                        return(false);
                    }

                    //Get basic variables data
                    _noOfPiecesInRow = bReader.ReadInt32();
                    _noOfPiecesInCol = bReader.ReadInt32();

                    _pieceWidthWithoutJoint  = bReader.ReadInt32();
                    _pieceHeightWithoutJoint = bReader.ReadInt32();


                    //Origional puzzle image
                    int    lengthImageEncoded = bReader.ReadInt32();
                    byte[] imageEncoded       = bReader.ReadBytes(lengthImageEncoded);
                    _origionalImage = new Texture2D(100, 100);
                    _origionalImage.LoadImage(imageEncoded);


                    //Puzzle image with joints
                    lengthImageEncoded = bReader.ReadInt32();
                    imageEncoded       = bReader.ReadBytes(lengthImageEncoded);
                    _image             = new Texture2D(100, 100);
                    _image.LoadImage(imageEncoded);

                    //Created background image
                    lengthImageEncoded      = bReader.ReadInt32();
                    imageEncoded            = bReader.ReadBytes(lengthImageEncoded);
                    _createdBackgroundImage = new Texture2D(100, 100);
                    _createdBackgroundImage.LoadImage(imageEncoded);

                    //Top joint mask image
                    lengthImageEncoded  = bReader.ReadInt32();
                    imageEncoded        = bReader.ReadBytes(lengthImageEncoded);
                    _topJointsMaskImage = new Texture2D(100, 100);
                    _topJointsMaskImage.LoadImage(imageEncoded);

                    //Bottom joint mask image
                    lengthImageEncoded  = bReader.ReadInt32();
                    imageEncoded        = bReader.ReadBytes(lengthImageEncoded);
                    _botJointsMaskImage = new Texture2D(100, 100);
                    _botJointsMaskImage.LoadImage(imageEncoded);

                    //Left joint mask image
                    lengthImageEncoded   = bReader.ReadInt32();
                    imageEncoded         = bReader.ReadBytes(lengthImageEncoded);
                    _leftJointsMaskImage = new Texture2D(100, 100);
                    _leftJointsMaskImage.LoadImage(imageEncoded);

                    //Right joint mask iamge
                    lengthImageEncoded    = bReader.ReadInt32();
                    imageEncoded          = bReader.ReadBytes(lengthImageEncoded);
                    _rightJointsMaskImage = new Texture2D(100, 100);
                    _rightJointsMaskImage.LoadImage(imageEncoded);


                    //Load joint mask array
                    int lengthJointMaskArr = bReader.ReadInt32();
                    _jointMask = new Texture2D[lengthJointMaskArr];
                    for (int i = 0; i < lengthJointMaskArr; i++)
                    {
                        int TempLength = bReader.ReadInt32();

                        _jointMask[i] = new Texture2D(100, 100);
                        imageEncoded  = bReader.ReadBytes(TempLength);
                        _jointMask[i].LoadImage(imageEncoded);
                    }


                    #region "Retreive Pieces Metadata"

                    _CreatedPiecesData = new SPieceInfo[_noOfPiecesInCol, _noOfPiecesInRow];

                    for (int RowTrav = 0; RowTrav < _noOfPiecesInCol; RowTrav++)
                    {
                        for (int ColTrav = 0; ColTrav < _noOfPiecesInRow; ColTrav++)
                        {
                            int pieceID = bReader.ReadInt32();

                            //Get joints info
                            int        JointInfoLength = bReader.ReadInt32();
                            SPieceInfo TempSPieceInfo  = new SPieceInfo(pieceID);

                            for (int i = 0; i < JointInfoLength; i++)
                            {
                                int jointType     = bReader.ReadInt32();
                                int jointWidth    = bReader.ReadInt32();
                                int jointHeight   = bReader.ReadInt32();
                                int jointPosition = bReader.ReadInt32();


                                TempSPieceInfo.AddJoint(new SJointInfo((EJointType)jointType, (EJointPosition)jointPosition,
                                                                       jointWidth, jointHeight));
                            }


                            //Insert this piece data in list
                            _CreatedPiecesData[RowTrav, ColTrav] = TempSPieceInfo;
                        }
                    }

                    #endregion

                    bReader.Close();
                }
            }
            catch (System.Exception ex)
            {
                throw new System.Exception("Exception in load data 2: " + ex.Message);
            }

            return(true);
        }
        /// <summary>
        /// Draws joint mask image for each side of joints for every piece which is used to later
        /// generate puzzle image for pieces
        /// </summary>
        /// <param name="TopJointMaskImage">Output mask image for top joints</param>
        /// <param name="BotJointMaskImage">Output mask image for bottom joints</param>
        /// <param name="LeftJointMaskImage">Output mask image for left joints</param>
        /// <param name="RightJointMaskImage">Output mask image for right joints</param>
        /// <param name="JointMaskImages">User provided joint mask images to be used</param>
        /// <param name="PieceHeightWithoutJoint">Output piece image height</param>
        /// <param name="PieceWidthWithoutJoint">Output piece image width</param>
        /// <param name="PuzzleImgHeight">Height of user provided puzzle image</param>
        /// <param name="PuzzleImgWidth">Width of user provided puzzle image</param>
        /// <param name="Cols">Total columns in puzzle</param>
        /// <param name="Rows">Total rows in puzzle</param>
        /// <returns>Returns created pieces metadata created during masks creation</returns>
        private SPieceInfo[,] DrawCustomPieceJointsMask(ref Color[][] TopJointMaskImage, ref Color[][] BotJointMaskImage,
                                                        ref Color[][] LeftJointMaskImage, ref Color[][] RightJointMaskImage, Texture2D[] JointMaskImages,
                                                        out int PieceWidthWithoutJoint, out int PieceHeightWithoutJoint, int PuzzleImgWidth, int PuzzleImgHeight, int Rows = 5, int Cols = 5)
        {
            int[] JointMaskWidth  = new int[JointMaskImages.Length];
            int[] JointMaskHeight = new int[JointMaskImages.Length];

            //Create direction wise mask images
            Texture2D[] LeftJointMask   = new Texture2D[JointMaskImages.Length];
            Texture2D[] RightJointMask  = new Texture2D[JointMaskImages.Length];
            Texture2D[] TopJointMask    = new Texture2D[JointMaskImages.Length];
            Texture2D[] BottomJointMask = new Texture2D[JointMaskImages.Length];

            SPieceInfo[,] ResultPiecesData = new SPieceInfo[Rows, Cols];


            //Initialize pieces data
            for (int i = 0; i < Rows; i++)
            {
                for (int j = 0; j < Cols; j++)
                {
                    ResultPiecesData[i, j] = new SPieceInfo((i * Cols) + j);
                }
            }

            int PieceHeight = PuzzleImgHeight / Rows;
            int PieceWidth  = PuzzleImgWidth / Cols;

            PieceWidthWithoutJoint  = PieceWidth;
            PieceHeightWithoutJoint = PieceHeight;



            for (int ArrayTav = 0; ArrayTav < JointMaskImages.Length; ArrayTav++)
            {
                LeftJointMask[ArrayTav]   = JointMaskImages[ArrayTav];
                BottomJointMask[ArrayTav] = HelperMethods.rotateImage(JointMaskImages[ArrayTav], 90);
                RightJointMask[ArrayTav]  = HelperMethods.rotateImage(BottomJointMask[ArrayTav], 90);
                TopJointMask[ArrayTav]    = HelperMethods.rotateImage(JointMaskImages[ArrayTav], 270);


                #region "Resize Joint mask images for drawing inside mask image And calculate joints width and height"

                //Resize Joint mask images for drawing inside mask image
                //  Image will be resized according to piece width
                int MaskImageWidth  = (int)(PieceWidth * 0.3f);
                int MaskImageHeight = (int)((float)MaskImageWidth / ((float)JointMaskImages[ArrayTav].width / (float)JointMaskImages[ArrayTav].height));

                LeftJointMask[ArrayTav]   = HelperMethods.resizeImage(LeftJointMask[ArrayTav], MaskImageWidth, MaskImageHeight);
                RightJointMask[ArrayTav]  = HelperMethods.resizeImage(RightJointMask[ArrayTav], MaskImageWidth, MaskImageHeight);
                TopJointMask[ArrayTav]    = HelperMethods.resizeImage(TopJointMask[ArrayTav], MaskImageWidth, MaskImageHeight);
                BottomJointMask[ArrayTav] = HelperMethods.resizeImage(BottomJointMask[ArrayTav], MaskImageWidth, MaskImageHeight);


                //Calculate joints width and heights
                CalculateCustomJointDimensions(LeftJointMask[ArrayTav], out JointMaskWidth[ArrayTav], out JointMaskHeight[ArrayTav]);



                #endregion
            }



            #region "Argument Error Checking"

            //Joint mask image width and height should be same
            //Joint mask image should have only black and white pixels inside it

            if (JointMaskImages[0].width != JointMaskImages[0].height)
            {
                Debug.LogError("JointMaskImage width and height should be same");
                return(null);
            }
            else
            {
                bool ErrorFound = false;  //If Non-Black or Non-White pixel found

                //Check for pixel colors in joint mask image
                for (int rowtrav = 0; rowtrav < JointMaskImages[0].height && !ErrorFound; rowtrav++)
                {
                    for (int coltrav = 0; coltrav < JointMaskImages[0].width && !ErrorFound; coltrav++)
                    {
                        Color PixelColor = JointMaskImages[0].GetPixel(coltrav, rowtrav);

                        if (PixelColor != Color.white || PixelColor != Color.black)
                        {
                            ErrorFound = true;

                            //Debug.LogError("Only white and black pixels are allowed in JointMaskImage");

                            //return null;
                        }
                    }
                }
            }

            #endregion

            TopJointMaskImage   = new Color[PuzzleImgWidth][];
            BotJointMaskImage   = new Color[PuzzleImgWidth][];
            LeftJointMaskImage  = new Color[PuzzleImgWidth][];
            RightJointMaskImage = new Color[PuzzleImgWidth][];

            //Clear Instantiated mask image
            for (int i = 0; i < PuzzleImgWidth; i++)
            {
                TopJointMaskImage[i]   = new Color[PuzzleImgHeight];
                BotJointMaskImage[i]   = new Color[PuzzleImgHeight];
                LeftJointMaskImage[i]  = new Color[PuzzleImgHeight];
                RightJointMaskImage[i] = new Color[PuzzleImgHeight];
            }


            //Generate random joint info And Draw joints

            Random.seed = System.DateTime.Now.Second;
            Color PieceColor = Color.black;


            for (int RowTrav = 0; RowTrav < Rows; RowTrav++)
            {
                for (int ColTrav = 0; ColTrav < Cols; ColTrav++)
                {
                    int PieceX = ColTrav * PieceWidth;
                    int PieceY = RowTrav * PieceHeight;

                    //Generate Random joint info and Draw Joints From Mask Image

                    #region "Draw right joints according to piece joint information"

                    if (ColTrav < Cols - 1)
                    {
                        int SelectedRandomJoint = Random.Range(1, JointMaskImages.Length) - 1;

                        //Create random joint information
                        int RndVal = (int)(Random.Range(1f, 18f) >= 10 ? 1 : 0);
                        ResultPiecesData[RowTrav, ColTrav].AddJoint(new SJointInfo((EJointType)RndVal, EJointPosition.Right,
                                                                                   JointMaskWidth[SelectedRandomJoint], JointMaskHeight[SelectedRandomJoint]));


                        int JointX = PieceX + PieceWidth;
                        int JointY = PieceY + (PieceHeight / 2) - (RightJointMask[SelectedRandomJoint].height / 2);

                        bool       Result         = false;
                        SJointInfo RightJointInfo = ResultPiecesData[RowTrav, ColTrav].GetJoint(EJointPosition.Right, out Result);

                        if (!Result)
                        {
                            Debug.LogError("Logical error in draw joints from mask image Right Joints");
                        }
                        else
                        {
                            if (RightJointInfo.JointType == EJointType.Male)
                            {
                                drawJoint(ref RightJointMaskImage, RightJointMask[SelectedRandomJoint], PieceColor, JointX, JointY);
                            }
                        }
                    }
                    #endregion

                    #region "Draw left joints according to piece joint information"

                    if (ColTrav > 0)
                    {
                        int SelectedRandomJoint = Random.Range(1, JointMaskImages.Length) - 1;

                        //Create random joint information
                        bool Result = false;

                        SJointInfo PreviousRightJoint = ResultPiecesData[RowTrav, ColTrav - 1].GetJoint(EJointPosition.Right, out Result);

                        if (Result == false)
                        {
                            Debug.LogError("Logical error in joints information left joint");
                        }
                        else
                        {
                            SJointInfo CalcLeftJoint = new SJointInfo(PreviousRightJoint.JointType == EJointType.Female ?
                                                                      EJointType.Male : EJointType.Female, EJointPosition.Left,
                                                                      JointMaskWidth[SelectedRandomJoint], JointMaskHeight[SelectedRandomJoint]);
                            ResultPiecesData[RowTrav, ColTrav].AddJoint(CalcLeftJoint);
                        }


                        int JointX = PieceX - LeftJointMask[SelectedRandomJoint].width;
                        int JointY = PieceY + (PieceHeight / 2) - (LeftJointMask[SelectedRandomJoint].height / 2);

                        Result = false;
                        SJointInfo LeftJointInfo = ResultPiecesData[RowTrav, ColTrav].GetJoint(EJointPosition.Left, out Result);

                        if (!Result)
                        {
                            Debug.LogError("Logical error in draw joints from mask image Left Joints");
                        }
                        else
                        {
                            if (LeftJointInfo.JointType == EJointType.Male)
                            {
                                drawJoint(ref LeftJointMaskImage, LeftJointMask[SelectedRandomJoint], PieceColor, JointX, JointY);
                            }
                        }
                    }

                    #endregion

                    #region "Draw Top joints according to piece joint information"

                    if (RowTrav < Rows - 1)
                    {
                        int SelectedRandomJoint = Random.Range(1, JointMaskImages.Length) - 1;

                        //Create random joint information
                        int RndVal = (int)(Random.Range(1f, 17f) >= 10 ? 1 : 0);
                        ResultPiecesData[RowTrav, ColTrav].AddJoint(new SJointInfo((EJointType)RndVal, EJointPosition.Top,
                                                                                   JointMaskWidth[SelectedRandomJoint], JointMaskHeight[SelectedRandomJoint]));

                        int JointX = PieceX + (PieceWidth / 2) - (TopJointMask[SelectedRandomJoint].width / 2);
                        int JointY = PieceY + PieceHeight;

                        bool       Result       = false;
                        SJointInfo TopJointInfo = ResultPiecesData[RowTrav, ColTrav].GetJoint(EJointPosition.Top, out Result);

                        if (!Result)
                        {
                            Debug.LogError("Logical error in draw joints from mask image Top Joints");
                        }
                        else
                        {
                            if (TopJointInfo.JointType == EJointType.Male)
                            {
                                drawJoint(ref TopJointMaskImage, TopJointMask[SelectedRandomJoint], PieceColor, JointX, JointY);
                            }
                        }
                    }

                    #endregion

                    #region "Draw Bottom joints according to piece joint information"

                    if (RowTrav > 0)
                    {
                        int SelectedRandomJoint = Random.Range(1, JointMaskImages.Length) - 1;

                        //Create random joint information
                        bool Result = false;

                        SJointInfo PreviousPieceTopJoint = ResultPiecesData[RowTrav - 1, ColTrav].GetJoint(EJointPosition.Top, out Result);

                        if (Result == false)
                        {
                            Debug.LogError("Logical error in joints information Bottom joint");
                        }
                        else
                        {
                            SJointInfo CalcBottomJoint = new SJointInfo(PreviousPieceTopJoint.JointType == EJointType.Female ?
                                                                        EJointType.Male : EJointType.Female, EJointPosition.Bottom,
                                                                        JointMaskWidth[SelectedRandomJoint], JointMaskHeight[SelectedRandomJoint]);

                            ResultPiecesData[RowTrav, ColTrav].AddJoint(CalcBottomJoint);
                        }


                        int JointX = PieceX + (PieceWidth / 2) - (BottomJointMask[SelectedRandomJoint].width / 2);
                        int JointY = PieceY - BottomJointMask[SelectedRandomJoint].height;

                        Result = false;
                        SJointInfo BottomJointInfo = ResultPiecesData[RowTrav, ColTrav].GetJoint(EJointPosition.Bottom, out Result);

                        if (!Result)
                        {
                            Debug.LogError("Logical error in draw joints from mask image Top Joints");
                        }
                        else
                        {
                            if (BottomJointInfo.JointType == EJointType.Male)
                            {
                                drawJoint(ref BotJointMaskImage, BottomJointMask[SelectedRandomJoint], PieceColor, JointX, JointY);
                            }
                        }
                    }

                    #endregion
                }
            }



            return(ResultPiecesData);
        }
        /// <summary>
        /// Generate puzzle pieces from image.
        /// </summary>
        /// <param name="NoOfPiecesInRow">Total no of pieces in row of puzzle / total columns</param>
        /// <param name="NoOfPiecesInCol">Total no of pieces in Col of puzzle / total rows</param>
        /// <param name="Image">Main image for puzzle</param>
        /// <param name="JointMaskImage">Mask images for joints to be used to create joints for pieces in this puzzle</param>
        /// <param name="CreatedImageMask">Unknown</param>
        /// <returns>Returns generated pieces metadata</returns>
        private SPieceInfo[,] GenerateJigsawPieces(Texture2D Image, Texture2D[] JointMaskImage, out Texture2D CreatedImageMask, int NoOfPiecesInRow, int NoOfPiecesInCol)
        {
            #region "Argument Error Checking"

            if (NoOfPiecesInRow < 2)
            {
                throw new System.ArgumentOutOfRangeException("NoOfPiecesInRow", "Argument should be greater then 1");
            }
            else if (NoOfPiecesInCol < 2)
            {
                throw new System.ArgumentOutOfRangeException("NoOfPiecesInCol", "Argument should be greater then 1");
            }
            else if (Image == null)
            {
                throw new System.ArgumentNullException("No texture2d assigned to this class");
            }

            #endregion



            _noOfPiecesInRow = NoOfPiecesInRow;
            _noOfPiecesInCol = NoOfPiecesInCol;

            _origionalImage = Image;

            Color[][] _PuzzleImageTopJointMask   = HelperMethods.Texture2DToColorArr(Image);
            Color[][] _PuzzleImageBotJointMask   = HelperMethods.Texture2DToColorArr(Image);
            Color[][] _PuzzleImageLeftJointMask  = HelperMethods.Texture2DToColorArr(Image);
            Color[][] _PuzzleImageRightJointMask = HelperMethods.Texture2DToColorArr(Image);
            Color[][] _PuzzleImage = HelperMethods.Texture2DToColorArr(Image);


            SPieceInfo[,] PiecesInformation = null;


            PiecesInformation = DrawCustomPieceJointsMask(ref _PuzzleImageTopJointMask, ref _PuzzleImageBotJointMask,
                                                          ref _PuzzleImageLeftJointMask, ref _PuzzleImageRightJointMask,
                                                          JointMaskImage, out _pieceWidthWithoutJoint,
                                                          out _pieceHeightWithoutJoint, Image.width, Image.height, NoOfPiecesInCol, NoOfPiecesInRow);



            CreatedImageMask = HelperMethods.ColorArrToTexture2D(_PuzzleImageTopJointMask);

            //Create mask image for each side joints
            JointsMaskToJointsImage(ref _PuzzleImage, ref _PuzzleImageTopJointMask, ref _PuzzleImageBotJointMask,
                                    ref _PuzzleImageLeftJointMask, ref _PuzzleImageRightJointMask,
                                    PieceWidthWithoutJoint, PieceHeightWithoutJoint, Image.width, Image.height);

            _topJointsMaskImage   = HelperMethods.ColorArrToTexture2D(_PuzzleImageTopJointMask);
            _botJointsMaskImage   = HelperMethods.ColorArrToTexture2D(_PuzzleImageBotJointMask);
            _leftJointsMaskImage  = HelperMethods.ColorArrToTexture2D(_PuzzleImageLeftJointMask);
            _rightJointsMaskImage = HelperMethods.ColorArrToTexture2D(_PuzzleImageRightJointMask);

            _image = HelperMethods.ColorArrToTexture2D(_PuzzleImage);


            //Return data for puzzle pieces
            SPieceInfo[,] ResultData = new SPieceInfo[NoOfPiecesInCol, NoOfPiecesInRow];
            for (int i = 0; i < NoOfPiecesInCol; i++)
            {
                for (int j = 0; j < NoOfPiecesInRow; j++)
                {
                    ResultData[i, j] = PiecesInformation[i, j];
                }
            }

            return(ResultData);
        }
    /// <summary>
    /// Used to calculate required data for joining of pieces together
    /// </summary>
    void CalculateDataForCollisionPlacement(SPieceInfo PieceData, out float LeftJointWorldScale, out float RightJointWorldScale,
                        out float TopJointWorldScale, out float BottomJointWorldScale)
    {

        bool LeftJointPresent = false;
        bool RightJointPresent = false;
        bool TopJointPresent = false;
        bool BotJointPresent = false;

        SJointInfo TempLeftJointInfo = PieceData.GetJoint(EJointPosition.Left, out LeftJointPresent);
        SJointInfo TempRightJointInfo = PieceData.GetJoint(EJointPosition.Right, out RightJointPresent);
        SJointInfo TempTopJointInfo = PieceData.GetJoint(EJointPosition.Top, out TopJointPresent);
        SJointInfo TempBotJointInfo = PieceData.GetJoint(EJointPosition.Bottom, out BotJointPresent);

        float PMPieceWidthWOJoint = (float)JpPuzzleControllerInstance.PuzzleMakerPieceWidthWithoutJoint;

        LeftJointWorldScale = LeftJointPresent && TempLeftJointInfo.JointType == EJointType.Male ?
            (float)TempLeftJointInfo.JointWidth / PMPieceWidthWOJoint : 0;
        RightJointWorldScale = RightJointPresent && TempRightJointInfo.JointType == EJointType.Male ?
            (float)TempRightJointInfo.JointWidth / PMPieceWidthWOJoint : 0;
        TopJointWorldScale = TopJointPresent && TempTopJointInfo.JointType == EJointType.Male ?
            (float)TempTopJointInfo.JointHeight / PMPieceWidthWOJoint : 0;
        BottomJointWorldScale = BotJointPresent && TempBotJointInfo.JointType == EJointType.Male ?
            (float)TempBotJointInfo.JointHeight / PMPieceWidthWOJoint : 0;

    }
        /// <summary>
        /// Draws joint mask image for each side of joints for every piece which is used to later 
        /// generate puzzle image for pieces
        /// </summary>
        /// <param name="TopJointMaskImage">Output mask image for top joints</param>
        /// <param name="BotJointMaskImage">Output mask image for bottom joints</param>
        /// <param name="LeftJointMaskImage">Output mask image for left joints</param>
        /// <param name="RightJointMaskImage">Output mask image for right joints</param>
        /// <param name="JointMaskImages">User provided joint mask images to be used</param>
        /// <param name="PieceHeightWithoutJoint">Output piece image height</param>
        /// <param name="PieceWidthWithoutJoint">Output piece image width</param>
        /// <param name="PuzzleImgHeight">Height of user provided puzzle image</param>
        /// <param name="PuzzleImgWidth">Width of user provided puzzle image</param>
        /// <param name="Cols">Total columns in puzzle</param>
        /// <param name="Rows">Total rows in puzzle</param>
        /// <returns>Returns created pieces metadata created during masks creation</returns>
        private SPieceInfo[,] DrawCustomPieceJointsMask(ref Color[][] TopJointMaskImage, ref Color[][] BotJointMaskImage,
            ref Color[][] LeftJointMaskImage, ref Color[][] RightJointMaskImage, Texture2D[] JointMaskImages,
                out int PieceWidthWithoutJoint, out int PieceHeightWithoutJoint, int PuzzleImgWidth, int PuzzleImgHeight, int Rows = 5, int Cols = 5)
        {

            int[] JointMaskWidth = new int[JointMaskImages.Length];
            int[] JointMaskHeight = new int[JointMaskImages.Length];

            //Create direction wise mask images
            Texture2D[] LeftJointMask = new Texture2D[JointMaskImages.Length];
            Texture2D[] RightJointMask = new Texture2D[JointMaskImages.Length];
            Texture2D[] TopJointMask = new Texture2D[JointMaskImages.Length];
            Texture2D[] BottomJointMask = new Texture2D[JointMaskImages.Length];

            SPieceInfo[,] ResultPiecesData = new SPieceInfo[Rows, Cols];


            //Initialize pieces data
            for (int i = 0; i < Rows; i++)
                for (int j = 0; j < Cols; j++)
                    ResultPiecesData[i, j] = new SPieceInfo((i * Cols) + j);

            int PieceHeight = PuzzleImgHeight / Rows;
            int PieceWidth = PuzzleImgWidth / Cols;

            PieceWidthWithoutJoint = PieceWidth;
            PieceHeightWithoutJoint = PieceHeight;



            for (int ArrayTav = 0; ArrayTav < JointMaskImages.Length; ArrayTav++)
            {
                LeftJointMask[ArrayTav] = JointMaskImages[ArrayTav];
                BottomJointMask[ArrayTav] = HelperMethods.rotateImage(JointMaskImages[ArrayTav], 90);
                RightJointMask[ArrayTav] = HelperMethods.rotateImage(BottomJointMask[ArrayTav], 90);
                TopJointMask[ArrayTav] = HelperMethods.rotateImage(JointMaskImages[ArrayTav], 270);
                                

                #region "Resize Joint mask images for drawing inside mask image And calculate joints width and height"

                //Resize Joint mask images for drawing inside mask image
                //  Image will be resized according to piece width
                int MaskImageWidth = (int)(PieceWidth * 0.3f);
                int MaskImageHeight = (int)((float)MaskImageWidth / ((float)JointMaskImages[ArrayTav].width / (float)JointMaskImages[ArrayTav].height));

                LeftJointMask[ArrayTav] = HelperMethods.resizeImage(LeftJointMask[ArrayTav], MaskImageWidth, MaskImageHeight);
                RightJointMask[ArrayTav] = HelperMethods.resizeImage(RightJointMask[ArrayTav], MaskImageWidth, MaskImageHeight);
                TopJointMask[ArrayTav] = HelperMethods.resizeImage(TopJointMask[ArrayTav], MaskImageWidth, MaskImageHeight);
                BottomJointMask[ArrayTav] = HelperMethods.resizeImage(BottomJointMask[ArrayTav], MaskImageWidth, MaskImageHeight);


                //Calculate joints width and heights
                CalculateCustomJointDimensions(LeftJointMask[ArrayTav], out JointMaskWidth[ArrayTav], out JointMaskHeight[ArrayTav]);



                #endregion

            }




            #region "Argument Error Checking"

            //Joint mask image width and height should be same
            //Joint mask image should have only black and white pixels inside it

            if (JointMaskImages[0].width != JointMaskImages[0].height)
            {
                Debug.LogError("JointMaskImage width and height should be same");
                return null;
            }
            else
            {
                bool ErrorFound = false;  //If Non-Black or Non-White pixel found

                //Check for pixel colors in joint mask image
                for (int rowtrav = 0; rowtrav < JointMaskImages[0].height && !ErrorFound; rowtrav++)
                {
                    for (int coltrav = 0; coltrav < JointMaskImages[0].width && !ErrorFound; coltrav++)
                    {
                        Color PixelColor = JointMaskImages[0].GetPixel(coltrav, rowtrav);

                        if (PixelColor != Color.white || PixelColor != Color.black)
                        {
                            ErrorFound = true;

                            //Debug.LogError("Only white and black pixels are allowed in JointMaskImage");

                            //return null;
                        }
                    }
                }


            }

            #endregion

            TopJointMaskImage = new Color[PuzzleImgWidth][];
            BotJointMaskImage = new Color[PuzzleImgWidth][];
            LeftJointMaskImage = new Color[PuzzleImgWidth][];
            RightJointMaskImage = new Color[PuzzleImgWidth][];

            //Clear Instantiated mask image
            for (int i = 0; i < PuzzleImgWidth; i++)
            {
                TopJointMaskImage[i] = new Color[PuzzleImgHeight];
                BotJointMaskImage[i] = new Color[PuzzleImgHeight];
                LeftJointMaskImage[i] = new Color[PuzzleImgHeight];
                RightJointMaskImage[i] = new Color[PuzzleImgHeight];
            }


            //Generate random joint info And Draw joints

            Random.seed = System.DateTime.Now.Second;
            Color PieceColor = Color.black;


            for (int RowTrav = 0; RowTrav < Rows; RowTrav++)
            {

                for (int ColTrav = 0; ColTrav < Cols; ColTrav++)
                {
                    int PieceX = ColTrav * PieceWidth;
                    int PieceY = RowTrav * PieceHeight;

                    //Generate Random joint info and Draw Joints From Mask Image

                    #region "Draw right joints according to piece joint information"

                    if (ColTrav < Cols - 1)
                    {
                        int SelectedRandomJoint = Random.Range(1, JointMaskImages.Length) - 1;

                        //Create random joint information
                        int RndVal = (int)(Random.Range(1f, 18f) >= 10 ? 1 : 0);
                        ResultPiecesData[RowTrav, ColTrav].AddJoint(new SJointInfo((EJointType)RndVal, EJointPosition.Right,
                                        JointMaskWidth[SelectedRandomJoint], JointMaskHeight[SelectedRandomJoint]));


                        int JointX = PieceX + PieceWidth;
                        int JointY = PieceY + (PieceHeight / 2) - (RightJointMask[SelectedRandomJoint].height / 2);

                        bool Result = false;
                        SJointInfo RightJointInfo = ResultPiecesData[RowTrav, ColTrav].GetJoint(EJointPosition.Right, out Result);

                        if (!Result)
                        {
                            Debug.LogError("Logical error in draw joints from mask image Right Joints");
                        }
                        else
                        {
                            if (RightJointInfo.JointType == EJointType.Male)
                                drawJoint(ref RightJointMaskImage, RightJointMask[SelectedRandomJoint], PieceColor, JointX, JointY);
                        }

                    }
                    #endregion

                    #region"Draw left joints according to piece joint information"

                    if (ColTrav > 0)
                    {
                        int SelectedRandomJoint = Random.Range(1, JointMaskImages.Length) - 1;

                        //Create random joint information
                        bool Result = false;

                        SJointInfo PreviousRightJoint = ResultPiecesData[RowTrav, ColTrav - 1].GetJoint(EJointPosition.Right, out Result);

                        if (Result == false)
                        {
                            Debug.LogError("Logical error in joints information left joint");
                        }
                        else
                        {
                            SJointInfo CalcLeftJoint = new SJointInfo(PreviousRightJoint.JointType == EJointType.Female ?
                                        EJointType.Male : EJointType.Female, EJointPosition.Left,
                                        JointMaskWidth[SelectedRandomJoint], JointMaskHeight[SelectedRandomJoint]);
                            ResultPiecesData[RowTrav, ColTrav].AddJoint(CalcLeftJoint);
                        }


                        int JointX = PieceX - LeftJointMask[SelectedRandomJoint].width;
                        int JointY = PieceY + (PieceHeight / 2) - (LeftJointMask[SelectedRandomJoint].height / 2);

                        Result = false;
                        SJointInfo LeftJointInfo = ResultPiecesData[RowTrav, ColTrav].GetJoint(EJointPosition.Left, out Result);

                        if (!Result)
                        {
                            Debug.LogError("Logical error in draw joints from mask image Left Joints");
                        }
                        else
                        {
                            if (LeftJointInfo.JointType == EJointType.Male)
                                drawJoint(ref LeftJointMaskImage, LeftJointMask[SelectedRandomJoint], PieceColor, JointX, JointY);
                        }
                    }

                    #endregion

                    #region"Draw Top joints according to piece joint information"

                    if (RowTrav < Rows - 1)
                    {
                        int SelectedRandomJoint = Random.Range(1, JointMaskImages.Length) - 1;

                        //Create random joint information
                        int RndVal = (int)(Random.Range(1f, 17f) >= 10 ? 1 : 0);
                        ResultPiecesData[RowTrav, ColTrav].AddJoint(new SJointInfo((EJointType)RndVal, EJointPosition.Top,
                                        JointMaskWidth[SelectedRandomJoint], JointMaskHeight[SelectedRandomJoint]));

                        int JointX = PieceX + (PieceWidth / 2) - (TopJointMask[SelectedRandomJoint].width / 2);
                        int JointY = PieceY + PieceHeight;

                        bool Result = false;
                        SJointInfo TopJointInfo = ResultPiecesData[RowTrav, ColTrav].GetJoint(EJointPosition.Top, out Result);

                        if (!Result)
                        {
                            Debug.LogError("Logical error in draw joints from mask image Top Joints");
                        }
                        else
                        {
                            if (TopJointInfo.JointType == EJointType.Male)
                                drawJoint(ref TopJointMaskImage, TopJointMask[SelectedRandomJoint], PieceColor, JointX, JointY);
                        }

                    }

                    #endregion

                    #region"Draw Bottom joints according to piece joint information"

                    if (RowTrav > 0)
                    {
                        int SelectedRandomJoint = Random.Range(1, JointMaskImages.Length) - 1;

                        //Create random joint information
                        bool Result = false;

                        SJointInfo PreviousPieceTopJoint = ResultPiecesData[RowTrav - 1, ColTrav].GetJoint(EJointPosition.Top, out Result);

                        if (Result == false)
                        {
                            Debug.LogError("Logical error in joints information Bottom joint");
                        }
                        else
                        {
                            SJointInfo CalcBottomJoint = new SJointInfo(PreviousPieceTopJoint.JointType == EJointType.Female ?
                                        EJointType.Male : EJointType.Female, EJointPosition.Bottom,
                                        JointMaskWidth[SelectedRandomJoint], JointMaskHeight[SelectedRandomJoint]);

                            ResultPiecesData[RowTrav, ColTrav].AddJoint(CalcBottomJoint);
                        }


                        int JointX = PieceX + (PieceWidth / 2) - (BottomJointMask[SelectedRandomJoint].width / 2);
                        int JointY = PieceY - BottomJointMask[SelectedRandomJoint].height;

                        Result = false;
                        SJointInfo BottomJointInfo = ResultPiecesData[RowTrav, ColTrav].GetJoint(EJointPosition.Bottom, out Result);

                        if (!Result)
                        {
                            Debug.LogError("Logical error in draw joints from mask image Top Joints");
                        }
                        else
                        {
                            if (BottomJointInfo.JointType == EJointType.Male)
                                drawJoint(ref BotJointMaskImage, BottomJointMask[SelectedRandomJoint], PieceColor, JointX, JointY);
                        }

                    }

                    #endregion


                }

            }



            return ResultPiecesData;
        }
        /// <summary>
        /// Creates a deep copy of this class
        /// </summary>
        /// <returns>Returns a deep copy of this class</returns>
        public SPieceInfo MakeCopy()
        {
            SPieceInfo Temp = new SPieceInfo(_ID);
            foreach (SJointInfo item in _Joints)
                Temp.AddJoint(item);

            return Temp;
        }
        /// <summary>
        /// Loads puzzle data from file stream of .pm file
        /// </summary>
        /// <param name="stream">Stream to load data from</param>
        /// <returns>Returns true if data loading is successfull false otherwise</returns>
        private bool LoadStreamData(System.IO.Stream stream)
        {
            System.IO.BinaryReader bReader = null;

            try
            {
                using (bReader = new System.IO.BinaryReader(stream))
                {
                    //Get secret number to check file intigrity
                    int secretNumber = bReader.ReadInt32();
                    if (secretNumber != _secretVersionNo)
                    {
                        bReader.Close();
                        Debug.LogError("Error reading file. Make sure this file is created with puzzle maker`s current version");
                        return false;
                    }

                    //Get basic variables data
                    _noOfPiecesInRow = bReader.ReadInt32();
                    _noOfPiecesInCol = bReader.ReadInt32();

                    _pieceWidthWithoutJoint = bReader.ReadInt32();
                    _pieceHeightWithoutJoint = bReader.ReadInt32();


                    //Origional puzzle image
                    int lengthImageEncoded = bReader.ReadInt32();
                    byte[] imageEncoded = bReader.ReadBytes(lengthImageEncoded);
                    _origionalImage = new Texture2D(100, 100);
                    _origionalImage.LoadImage(imageEncoded);


                    //Puzzle image with joints
                    lengthImageEncoded = bReader.ReadInt32();
                    imageEncoded = bReader.ReadBytes(lengthImageEncoded);
                    _image = new Texture2D(100, 100);
                    _image.LoadImage(imageEncoded);

                    //Created background image
                    lengthImageEncoded = bReader.ReadInt32();
                    imageEncoded = bReader.ReadBytes(lengthImageEncoded);
                    _createdBackgroundImage = new Texture2D(100, 100);
                    _createdBackgroundImage.LoadImage(imageEncoded);
                    
                    //Top joint mask image
                    lengthImageEncoded = bReader.ReadInt32();
                    imageEncoded = bReader.ReadBytes(lengthImageEncoded);
                    _topJointsMaskImage = new Texture2D(100, 100);
                    _topJointsMaskImage.LoadImage(imageEncoded);

                    //Bottom joint mask image
                    lengthImageEncoded = bReader.ReadInt32();
                    imageEncoded = bReader.ReadBytes(lengthImageEncoded);
                    _botJointsMaskImage = new Texture2D(100, 100);
                    _botJointsMaskImage.LoadImage(imageEncoded);

                    //Left joint mask image
                    lengthImageEncoded = bReader.ReadInt32();
                    imageEncoded = bReader.ReadBytes(lengthImageEncoded);
                    _leftJointsMaskImage = new Texture2D(100, 100);
                    _leftJointsMaskImage.LoadImage(imageEncoded);

                    //Right joint mask iamge
                    lengthImageEncoded = bReader.ReadInt32();
                    imageEncoded = bReader.ReadBytes(lengthImageEncoded);
                    _rightJointsMaskImage = new Texture2D(100, 100);
                    _rightJointsMaskImage.LoadImage(imageEncoded);


                    //Load joint mask array
                    int lengthJointMaskArr = bReader.ReadInt32();
                    _jointMask = new Texture2D[lengthJointMaskArr];
                    for (int i = 0; i < lengthJointMaskArr; i++)
                    {
                        int TempLength = bReader.ReadInt32();

                        _jointMask[i] = new Texture2D(100, 100);
                        imageEncoded = bReader.ReadBytes(TempLength);
                        _jointMask[i].LoadImage(imageEncoded);
                    }


#region "Retreive Pieces Metadata"

                    _CreatedPiecesData = new SPieceInfo[_noOfPiecesInCol, _noOfPiecesInRow];

                    for (int RowTrav = 0; RowTrav < _noOfPiecesInCol; RowTrav++)
                    {
                        for (int ColTrav = 0; ColTrav < _noOfPiecesInRow; ColTrav++)
                        {
                            int pieceID = bReader.ReadInt32();

                            //Get joints info
                            int JointInfoLength = bReader.ReadInt32();
                            SPieceInfo TempSPieceInfo = new SPieceInfo(pieceID);

                            for (int i = 0; i < JointInfoLength; i++)
                            {
                                int jointType = bReader.ReadInt32();
                                int jointWidth = bReader.ReadInt32();
                                int jointHeight = bReader.ReadInt32();
                                int jointPosition = bReader.ReadInt32();


                                TempSPieceInfo.AddJoint(new SJointInfo((EJointType)jointType, (EJointPosition)jointPosition,
                                                        jointWidth, jointHeight));
                            }
                            

                            //Insert this piece data in list
                            _CreatedPiecesData[RowTrav, ColTrav] = TempSPieceInfo;

                        }
                    }

#endregion

                    bReader.Close();

                }
            }
            catch (System.Exception ex)
            {
                throw new System.Exception("Exception in load data 2: " + ex.Message);
            }
            
            return true;
        }
    void OnRightCollision(int CollidingPieceId, GameObject ColP, SPieceInfo ColPPieceData, JPPieceController ColObjController)
    {
        //Check if this is child of current holding piece then apply collision logic
        bool IsChildOfHoldingPiece = false;

        JPPieceController[] ChildrenControllers = transform.GetComponentsInChildren<JPPieceController>();
        foreach (JPPieceController item in ChildrenControllers)
        {
            if (ThisPieceData.ID == item.ThisPieceData.ID)
            {
                IsChildOfHoldingPiece = true;
                break;
            }
        }


        if (ThisPieceData.ID == JpPuzzleControllerInstance.HoldingPieceID() || IsChildOfHoldingPiece)
        {

            if (ThisPieceData.ID == CollidingPieceId - 1)
            {

                //If is child of holding piece make it parent
                //Make this piece parent of all
                Transform Temp = transform.root;
                transform.parent = null;
                Temp.parent = transform;



                JpPuzzleControllerInstance.UnholdPiece();

                Vector3 CalculatedPos = new Vector3();


                float LeftJointWorldScale = 0;
                float RightJointWorldScale = 0;
                float TopJointWorldScale = 0;
                float BotJointWorldScale = 0;

                float ColPLeftJointWorldScale = 0;
                float ColPRightJointWorldScale = 0;
                float ColPTopJointWorldScale = 0;
                float ColPBotJointWorldScale = 0;


                //Calculate required data
                CalculateDataForCollisionPlacement(ColPPieceData, out ColPLeftJointWorldScale, out ColPRightJointWorldScale,
                                        out ColPTopJointWorldScale, out ColPBotJointWorldScale);
                CalculateDataForCollisionPlacement(ThisPieceData, out LeftJointWorldScale, out RightJointWorldScale,
                                        out TopJointWorldScale, out BotJointWorldScale);

                //Calculate X
                //Calculated X without joints
                float CalcXWJ = ColP.transform.position.x - JpPuzzleControllerInstance.PieceWidthInWorld;


                CalculatedPos.x = CalcXWJ - (ColPRightJointWorldScale / 2) + (ColPLeftJointWorldScale / 2) +
                                            (RightJointWorldScale / 2) - (LeftJointWorldScale / 2);



                //Calculate Y
                CalculatedPos.y = ColP.transform.position.y + (TopJointWorldScale / 2) - (BotJointWorldScale / 2)
                                                        - (ColPTopJointWorldScale / 2) + (ColPBotJointWorldScale / 2);



                CalculatedPos.z = transform.position.z;

                transform.position = CalculatedPos;

                ColP.transform.root.parent = transform;

                OnPieceJoined();

                CheckForPuzzleComplete(transform);
            }
        }
        else
        {
            //Wrong Piece

        }
        
    }