/*/////////////////////////////////////////
          * UPDATE FUNCTION
          */
        ///////////////////////////////////////
        public void update(GameTime p_time,
                           Cursor p_player1_cursor,
                           Cursor p_player2_cursor)
        {
            // Update player 1's puzzle selection buttons:
            if (this.p1_next_piece != null)
            {
                this.p1_next_piece.Update(p_player1_cursor, p_time);

                if (this.p1_next_piece.isClicked())
                {
                    // Get next available piece:
                    for (int i = this.p1_current_piece; i < this.p1_pieces.Count; i++)
                    {
                        if (i != this.p1_current_piece &&
                            !this.p1_pieces[i].isInPlace() &&
                            !this.p1_pieces[i].lockedToCursor())
                        {
                            this.p1_current_piece = i;
                            break;
                        }
                    }
                }
            }

            if (this.p1_prev_piece != null)
            {
                this.p1_prev_piece.Update(p_player1_cursor, p_time);

                if (this.p1_prev_piece.isClicked())
                {
                    // Get next available piece:
                    for (int i = this.p1_current_piece; i >= 0; i--)
                    {
                        if (i != this.p1_current_piece &&
                            !this.p1_pieces[i].isInPlace() &&
                            !this.p1_pieces[i].lockedToCursor())
                        {
                            this.p1_current_piece = i;
                            break;
                        }
                    }
                }
            }

            // Update player 2's puzzle selection buttons:
            if(this.is_two_player)
            {
                if (this.p2_next_piece != null)
                {
                    this.p2_next_piece.Update(p_player2_cursor, p_time);

                    if (this.p2_next_piece.isClicked())
                    {
                        // Get next available piece:
                        for (int i = this.p2_current_piece; i < this.p2_pieces.Count; i++)
                        {
                            if (i != this.p2_current_piece &&
                                !this.p2_pieces[i].isInPlace() &&
                                !this.p2_pieces[i].lockedToCursor())
                            {
                                this.p2_current_piece = i;
                                break;
                            }
                        }
                    }
                }

                if (this.p2_prev_piece != null)
                {
                    this.p2_prev_piece.Update(p_player2_cursor, p_time);

                    if (this.p2_prev_piece.isClicked())
                    {
                        // Get next available piece:
                        for (int i = this.p2_current_piece; i >= 0; i--)
                        {
                            if (i != this.p2_current_piece &&
                                !this.p2_pieces[i].isInPlace() &&
                                !this.p2_pieces[i].lockedToCursor())
                            {
                                this.p2_current_piece = i;
                                break;
                            }
                        }
                    }
                }
            }

            // Check if puzzle is assembled:
            bool temp_finished = true;

            if(this.p1_pieces != null &&
                this.p1_pieces.Count > 0)
            {
                foreach(var piece in this.p1_pieces)
                {
                    if (!piece.isInPlace())
                    {
                        temp_finished = false;
                    }
                }
            }

            if (this.is_two_player &&
                this.p2_pieces != null &&
                this.p2_pieces.Count > 0)
            {
                foreach (var piece in this.p2_pieces)
                {
                    if (!piece.isInPlace())
                    {
                        temp_finished = false;
                    }
                }
            }

            this.is_finished = temp_finished;

            // Update/Set which pieces are visible:
            if (this.p1_pieces != null &&
                this.p1_pieces.Count > 0)
            {
                foreach (var piece in this.p1_pieces)
                {
                    // Update the current piece:
                    if (this.p1_pieces.IndexOf(piece) == this.p1_current_piece) piece.Update(p_player1_cursor);

                    if (piece.isInPlace())
                    {
                        piece.draw_piece = true;
                    }
                    else
                    {
                        piece.draw_piece = false;
                    }
                }
            }

            if (this.is_two_player &&
                this.p2_pieces != null &&
                this.p2_pieces.Count > 0)
            {
                foreach (var piece in this.p2_pieces)
                {
                    // Update the current piece:
                    if (this.p2_pieces.IndexOf(piece) == this.p2_current_piece) piece.Update(p_player2_cursor);

                    if (piece.isInPlace())
                    {
                        piece.draw_piece = true;
                    }
                    else
                    {
                        piece.draw_piece = false;
                    }
                }
            }

            // Check current pieces:
            if (this.p1_pieces != null &&
                this.p1_pieces.Count > 0 &&
                this.p1_current_piece < this.p1_pieces.Count)
            {
                p1_pieces[this.p1_current_piece].draw_piece = true;

                if(p1_pieces[this.p1_current_piece].isInPlace())
                {
                    // Keep at locked/solved position:
                    this.p1_pieces[this.p1_current_piece].destination_rect = this.p1_pieces[this.p1_current_piece].target_rect;

                    if(this.p1_current_piece < (this.p1_pieces.Count - 1))
                    {
                        this.p1_current_piece++;
                    }
                    else if(this.p1_current_piece > 0)
                    {
                        this.p1_current_piece--;
                    }
                }
            }

            if (this.is_two_player &&
                this.p2_pieces != null &&
                this.p2_pieces.Count > 0 &&
                this.p2_current_piece < this.p2_pieces.Count)
            {
                p2_pieces[this.p2_current_piece].draw_piece = true;

                if (p2_pieces[this.p2_current_piece].isInPlace())
                {
                    // Keep at locked/solved position:
                    this.p2_pieces[this.p2_current_piece].destination_rect = this.p2_pieces[this.p2_current_piece].target_rect;

                    if (this.p2_current_piece < (this.p2_pieces.Count - 1))
                    {
                        this.p2_current_piece++;
                    }
                    else if (this.p2_current_piece > 0)
                    {
                        this.p2_current_piece--;
                    }
                }
            }
        }
        /*/////////////////////////////////////////
         * GRAPHICAL DATA & RESOURCE LOADING
         */
        ////////////////////////////////////////
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            this.sprite_batch = new SpriteBatch(this.GraphicsDevice);

            // Load game logo:
            this.logo = this.Content.Load<Texture2D>("Textures/Interface/UI_Logo");
            this.logo_pos = new Vector2((float)Math.Ceiling((this.GraphicsDevice.Viewport.Width - this.logo.Width) / 2.0),
                                        (float)Math.Ceiling((this.GraphicsDevice.Viewport.Height - this.logo.Height) / 2.0));

            // Create Kinect manager:
            this.kinect_manager = new KinectManager(ColorImageFormat.RgbResolution640x480Fps30,
                                                    DepthImageFormat.Resolution640x480Fps30,
                                                    this);

            // Create player cursors:
            this.player_1_cursor = new Cursor(this.Content.Load<Texture2D>("Textures/Interface/UI_CursorHand"),
                                              this.Content.Load<Texture2D>("Textures/Interface/UI_CursorColourIcon"),
                                              this.Content.Load<SpriteFont>("Fonts/Segoe16"),
                                              JointType.HandLeft,
                                              1.0f,
                                              0);
            this.player_2_cursor = new Cursor(this.Content.Load<Texture2D>("Textures/Interface/UI_CursorHand"),
                                              this.Content.Load<Texture2D>("Textures/Interface/UI_CursorColourIcon"),
                                              this.Content.Load<SpriteFont>("Fonts/Segoe16"),
                                              JointType.HandRight,
                                              1.0f,
                                              1);

            // Create main-menu/player-selection buttons (with offset):
            this.mainmenu_button_1player = new Button(this.Content.Load<Texture2D>("Textures/Interface/UI_SinglePlayer"),
                                                      1.2f,
                                                      new Vector2((float)Math.Ceiling((this.GraphicsDevice.Viewport.Width / 2.0f) - 270),
                                                                  (float)Math.Ceiling((this.GraphicsDevice.Viewport.Height - 360) / 2.0f)),
                                                      GestureType.NONE);

            this.mainmenu_button_2player = new Button(this.Content.Load<Texture2D>("Textures/Interface/UI_MultiPlayer"),
                                                      1.2f,
                                                      new Vector2((float)Math.Ceiling((this.GraphicsDevice.Viewport.Width / 2.0f) + 10),
                                                                  (float)Math.Ceiling((this.GraphicsDevice.Viewport.Height - 360) / 2.0f)),
                                                      GestureType.NONE);

            // Create hand selection buttons (with offset):
            this.mainmenu_lefthand_1 = new Button(this.Content.Load<Texture2D>("Textures/Interface/UI_LeftHand"),
                                                  1.2f,
                                                  new Vector2((float)Math.Ceiling((this.GraphicsDevice.Viewport.Width / 2.0f) - 270),
                                                              (float)Math.Ceiling((this.GraphicsDevice.Viewport.Height / 2.0f) - 160)),
                                                  GestureType.NONE);

            this.mainmenu_lefthand_2 = new Button(this.Content.Load<Texture2D>("Textures/Interface/UI_LeftHand"),
                                                  1.2f,
                                                  new Vector2((float)Math.Ceiling((this.GraphicsDevice.Viewport.Width / 2.0f) + 110),
                                                              (float)Math.Ceiling((this.GraphicsDevice.Viewport.Height / 2.0f) - 160)),
                                                  GestureType.NONE);

            this.mainmenu_righthand_1 = new Button(this.Content.Load<Texture2D>("Textures/Interface/UI_RightHand"),
                                                   1.2f,
                                                   new Vector2((float)Math.Ceiling((this.GraphicsDevice.Viewport.Width / 2.0f) - 270),
                                                               (float)Math.Ceiling((this.GraphicsDevice.Viewport.Height / 2.0f))),
                                                   GestureType.NONE);

            this.mainmenu_righthand_2 = new Button(this.Content.Load<Texture2D>("Textures/Interface/UI_RightHand"),
                                                   1.2f,
                                                   new Vector2((float)Math.Ceiling((this.GraphicsDevice.Viewport.Width / 2.0f) + 110),
                                                               (float)Math.Ceiling((this.GraphicsDevice.Viewport.Height / 2.0f))),
                                                   GestureType.NONE);

            // Create start game button (with offset):
            this.mainmenu_startgame = new Button(this.Content.Load<Texture2D>("Textures/Interface/UI_StartGame"),
                                                 1.2f,
                                                 new Vector2((float)Math.Ceiling((this.GraphicsDevice.Viewport.Width - 160) / 2.0f),
                                                             (float)Math.Ceiling((this.GraphicsDevice.Viewport.Height / 2.0f) + 100)),
                                                 GestureType.NONE);

            this.player_1_cursor.selected_colour = Color.Red;
        }
        /*/////////////////////////////////////////
          * PUZZLE FUNCTION(S)
          */
        ///////////////////////////////////////
        public void Update(Cursor p_player_cursor)
        {
            if (!this.is_in_place)
            {
                // Update the position of the puzzle-piece:
                if (this.locked_to_cursor)
                {
                    var pos = p_player_cursor.get2DPosition();
                    this.destination_rect.X = (int)pos.X - this.destination_rect.Width / 2;
                    this.destination_rect.Y = (int)pos.Y - this.destination_rect.Height / 2;

                    // Check for placement:
                    this.is_in_place = false;
                    var current_pos = p_player_cursor.get2DPosition();

                    if (this.target_rect.Contains(new Point((int)Math.Ceiling(current_pos.X),
                                                            (int)Math.Ceiling(current_pos.Y))))
                    {
                        // If the player's cursor is hovering over the piece:
                        if (!this.hover)
                        {
                            this.hover = true;
                            if (!this.timer.IsRunning) this.timer.Restart();
                        }
                    }
                    else
                    {
                        this.hover = false;
                        this.is_in_place = false;
                        this.timer.Reset();
                    }

                    // Check if timer has elapsed:
                    if (this.hover && this.timer.IsRunning)
                    {
                        long current_time = this.timer.ElapsedMilliseconds;

                        if (current_time >= this.target_time)
                        {
                            this.timer.Reset();
                            this.is_in_place = true;
                        }
                    }
                }
                else
                {
                    // Check for activation:
                    this.locked_to_cursor = false;
                    var current_pos = p_player_cursor.get2DPosition();

                    if (this.destination_rect.Contains(new Point((int)Math.Ceiling(current_pos.X),
                                                                 (int)Math.Ceiling(current_pos.Y))))
                    {
                        // If the player's cursor is hovering over the piece:
                        if (!this.hover)
                        {
                            this.hover = true;
                            if (!this.timer.IsRunning) this.timer.Restart();
                        }
                    }
                    else
                    {
                        this.hover = false;
                        this.locked_to_cursor = false;
                        this.timer.Reset();
                    }

                    // Check if timer has elapsed:
                    if (this.hover && this.timer.IsRunning)
                    {
                        long current_time = this.timer.ElapsedMilliseconds;

                        if(current_time >= this.target_time)
                        {
                            this.timer.Reset();
                            this.locked_to_cursor = true;
                        }
                    }
                }
            }
        }
        /*/////////////////////////////////////////
          * UTILITY FUNCTION(S)
          */
        ///////////////////////////////////////
        public void update(Cursor p_player_cursor,
                           Vector2 p_modified_pos,
                           int p_rect_width)
        {
            // Update the paint section:
            this.clicked = false;

            if (this.isOverSection(p_modified_pos, p_rect_width))
            {
                // If the player's cursor is over the paint section's bounds:
                if (!this.hover)
                {
                    this.hover = true;
                    if (!this.timer.IsRunning) this.timer.Restart();
                }
            }
            else
            {
                this.hover = false;
                this.clicked = false;
                this.timer.Reset();
            }

            // Check if target hover time has elapsed:
            if (this.hover && this.timer.IsRunning)
            {
                long current_time = this.timer.ElapsedMilliseconds;

                if (current_time >= this.target_time)
                {
                    this.timer.Reset();

                    if (this.target_gesture == GestureType.NONE || p_player_cursor.gesture == this.target_gesture)
                    {
                        this.clicked = true;
                    }
                }
            }
        }
        /*/////////////////////////////////////////
          * UPDATE FUNCTION
          */
        ///////////////////////////////////////
        public void Update(Cursor p_player_cursor, GameTime p_time)
        {
            // Update the simple game button...
            this.clicked = false;
            Vector2 current_pos = p_player_cursor.get2DPosition();

            if (this.location.Contains(new Point((int)Math.Ceiling(current_pos.X),
                                                 (int)Math.Ceiling(current_pos.Y))))
            {
                // If the player's cursor is over the button's rect bounds:
                if (!this.hover)
                {
                    this.hover = true;
                    if (!this.timer.IsRunning) this.timer.Restart();
                }
            }
            else
            {
                this.hover = false;
                this.clicked = false;
                this.timer.Reset();
            }

            // Check if target hover time has elapsed:
            if (this.hover && this.timer.IsRunning)
            {
                long current_time = this.timer.ElapsedMilliseconds;

                if (current_time >= this.target_time)
                {
                    this.timer.Reset();

                    if (this.target_gesture == GestureType.NONE || p_player_cursor.gesture == this.target_gesture)
                    {
                        this.clicked = true;
                    }
                }
            }
        }
        /*/////////////////////////////////////////
          * UPDATE FUNCTION
          */
        ///////////////////////////////////////
        public void update(GameTime p_time,
                           Cursor p_player_1,
                           Cursor p_player_2)
        {
            // Process cursor positions for paint image:
            Vector2 p1 = ((p_player_1 != null) ? p_player_1.get2DPosition() : Vector2.Zero);
            Vector2 p2 = ((this.is_two_player && p_player_2 != null) ? p_player_2.get2DPosition() : Vector2.Zero);
            bool p1_can_paint = false,
                 p2_can_paint = false;

            // Round positions:
            p1.X = (float)Math.Ceiling(p1.X);
            p1.Y = (float)Math.Ceiling(p1.Y);
            p2.X = (float)Math.Ceiling(p2.X);
            p2.Y = (float)Math.Ceiling(p2.Y);

            // Adjust co-ordinates to paintable image rect:
            if(p1 != Vector2.Zero &&
               this.image_rect.Contains(new Point((int)p1.X,
                                                  (int)p1.Y)))
            {
                p1_can_paint = true;
                p1.X -= this.image_rect.X;
                p1.Y -= this.image_rect.Y;
            }

            if (this.is_two_player &&
                p2 != Vector2.Zero &&
                this.image_rect.Contains(new Point((int)p2.X,
                                                   (int)p2.Y)))
            {
                p2_can_paint = true;
                p2.X -= this.image_rect.X;
                p2.Y -= this.image_rect.Y;
            }

            // Check paint sections:
            int player_1_is_painting = -1;

            if (p1_can_paint)
            {
                for (int i = 0; i < this.image_sections.Length; i++)
                {
                    if (p1_can_paint)
                    {
                        this.image_sections[i].update(p_player_1,
                                                      p1,
                                                      this.image_rect.Width);
                        if (this.image_sections[i].hoverOver()) player_1_is_painting = i;

                        if (this.image_sections[i].isClicked())
                        {
                            this.image_sections[i].changeSectionColour(ref this.paint_colours,
                                                                       p_player_1.selected_colour);
                            this.update_texture = true;
                        }
                    }
                }
            }

            if (this.is_two_player &&
                p2_can_paint)
            {
                for (int i = 0; i < this.image_sections.Length; i++)
                {
                    if (i != player_1_is_painting)
                    {
                        this.image_sections[i].update(p_player_2,
                                                      p2,
                                                      this.image_rect.Width);

                        if (this.image_sections[i].isClicked())
                        {
                            this.image_sections[i].changeSectionColour(ref this.paint_colours,
                                                                       p_player_2.selected_colour);
                            this.update_texture = true;
                        }
                    }
                }
            }

            // Handle colour-changing button presses:
            if (this.p1_next_col != null)
            {
                this.p1_next_col.Update(p_player_1, p_time);

                if (this.p1_next_col.isClicked())
                {
                    // Update set of visible colours:
                    for (byte i = 0; i < (byte)this.p1_colours.Length; i++)
                    {
                        this.p1_colours[i]--;

                        if (this.p1_colours[i] < 0)
                        {
                            this.p1_colours[i] += (sbyte)this.valid_button_colours.Length;
                        }
                    }
                }
            }

            if (this.is_two_player &&
                this.p2_next_col != null)
            {
                this.p2_next_col.Update(p_player_2, p_time);

                if (this.p2_next_col.isClicked())
                {
                    // Update set of visible colours:
                    for (byte i = 0; i < (byte)this.p2_colours.Length; i++)
                    {
                        this.p2_colours[i]--;

                        if (this.p2_colours[i] < 0)
                        {
                            this.p2_colours[i] += (sbyte)this.valid_button_colours.Length;
                        }
                    }
                }
            }

            if (this.p1_prev_col != null)
            {
                this.p1_prev_col.Update(p_player_1, p_time);

                if (this.p1_prev_col.isClicked())
                {
                    // Update set of visible colours:
                    for (byte i = 0; i < (byte)this.p1_colours.Length; i++)
                    {
                        this.p1_colours[i]++;

                        if (this.p1_colours[i] >= (sbyte)this.valid_button_colours.Length)
                        {
                            this.p1_colours[i] -= (sbyte)this.valid_button_colours.Length;
                        }
                    }
                }
            }

            if (this.is_two_player &&
                this.p2_prev_col != null)
            {
                this.p2_prev_col.Update(p_player_2, p_time);

                if (this.p2_prev_col.isClicked())
                {
                    // Update set of visible colours:
                    for (byte i = 0; i < (byte)this.p2_colours.Length; i++)
                    {
                        this.p2_colours[i]++;

                        if (this.p2_colours[i] >= (sbyte)this.valid_button_colours.Length)
                        {
                            this.p2_colours[i] -= (sbyte)this.valid_button_colours.Length;
                        }
                    }
                }
            }

            // Handle colour button presses:
            for (int i = 0; i < this.p1_cbuttons.Length; i++)
            {
                if (this.p1_cbuttons[i] != null)
                {
                    this.p1_cbuttons[i].button_colour = this.valid_button_colours[this.p1_colours[i]];
                    this.p1_cbuttons[i].Update(p_player_1, p_time);

                    if(this.p1_cbuttons[i].isClicked())
                    {
                        p_player_1.selected_colour = this.p1_cbuttons[i].button_colour;
                    }
                }
            }

            if (this.is_two_player)
            {
                for (int i = 0; i < this.p2_cbuttons.Length; i++)
                {
                    if (this.p2_cbuttons[i] != null)
                    {
                        this.p2_cbuttons[i].button_colour = this.valid_button_colours[this.p2_colours[i]];
                        this.p2_cbuttons[i].Update(p_player_2, p_time);

                        if(this.p2_cbuttons[i].isClicked())
                        {
                            p_player_2.selected_colour = this.p2_cbuttons[i].button_colour;
                        }
                    }
                }
            }

            // Handle finish game press:
            if (this.finish_confirm != null)
            {
                this.finish_confirm.Update(p_player_1, p_time);

                if (this.finish_confirm.isClicked())
                {
                    this.is_finished = true;
                }
            }
        }