content: /*
   * -----------------------------------------------------------------------
   * Copyright 2012 - Alistair Rutherford - www.netthreads.co.uk
   * -----------------------------------------------------------------------
   * 
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   * 
   *     http://www.apache.org/licenses/LICENSE-2.0
   * 
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   * 
   */
  
  package com.netthreads.libgdx.scene;
  
  import com.badlogic.gdx.math.Vector2;
  import com.badlogic.gdx.scenes.scene2d.Actor;
  import com.badlogic.gdx.scenes.scene2d.Group;
  import com.badlogic.gdx.scenes.scene2d.Stage;
  import com.badlogic.gdx.utils.SnapshotArray;
  
  /**
   * Helper methods for traversing through scenes and actors.
   * 
   * I have put this stuff here to void having to subclass the base types from LibGdx anymore than I have to.
   * 
   */
  public class SceneHelper
  {
  	private static final Vector2 point = new Vector2();
  
  	/**
  	 * Find hit class.
  	 * 
  	 * @param x
  	 *            Current x position.
  	 * @param y
  	 *            Current y position
  	 * @param group
  	 *            The starting Group.
  	 * @param targetClass
  	 *            The target class type.
  	 * 
  	 * @return The target or null if not found.
  	 */
  	@SuppressWarnings("rawtypes")
  	public static Actor hit(float x, float y, Group group, Class targetClass)
  	{
  		SnapshotArray<Actor> children = group.getChildren();
  
  		Actor hit = null;
  		boolean found = false;
  		int index = children.size - 1;
  		while (!found && index >= 0)
  		{
  			Actor child = children.get(index);
  
  			if (child.getClass().isAssignableFrom(targetClass))
  			{
  				point.x = x;
  				point.y = y;
  
  				group.localToDescendantCoordinates(child, point);
  
  				if (child.hit(point.x, point.y, true) != null)
  				{
  					found = true;
  					hit = child;
  				}
  				else if (child instanceof Group)
  				{
  					child = hit(x, y, (Group) child, targetClass);
  				}
  			}
  
  			index--;
  		}
  
  		return hit;
  	}
  
  	/**
  	 * Look for intersection between two actors.
  	 * 
  	 * I have defined this here as I can't extend the base classes Actor and Group.
  	 * 
  	 * @param x
  	 *            The x pos rectangle.
  	 * @param y
  	 *            The y pos rectangle.
  	 * @param width
  	 *            The rectangle width.
  	 * @param height
  	 *            The rectangle height.
  	 * @param group
  	 *            The group.
  	 * @param targetClass
  	 *            The target class.
  	 * 
  	 * @return Target class, null if no intersection.
  	 */
  	@SuppressWarnings("rawtypes")
  	public static Actor intersects(float x, float y, float width, float height, Group group, Class targetClass)
  	{
  		SnapshotArray<Actor> children = group.getChildren();
  
  		Actor hit = null;
  		int index = children.size - 1;
  		while (hit == null && index >= 0)
  		{
  			Actor child = children.get(index);
  
  			point.x = x;
  			point.y = y;
  
  			group.localToDescendantCoordinates(child, point);
  
  			// If child is our target class then immediately check for
  			// intersection
  			if (child.getClass().equals(targetClass))
  			{
  				if (isIntersect(point.x, point.y, width, height, 0, 0, child.getWidth(), child.getHeight()))
  				{
  					hit = child;
  				}
  			}
  			else if (child instanceof Group)
  			{
  				hit = intersects(point.x, point.y, width, height, (Group) child, targetClass);
  			}
  
  			index--;
  		}
  
  		return hit;
  	}
  
  	/**
  	 * Makes simple intersection check.
  	 * 
  	 * @param sourceX
  	 *            Source rectangle x pos.
  	 * @param sourceY
  	 *            Source rectangle x pos.
  	 * @param sourceWidth
  	 *            Source rectangle width.
  	 * @param sourceHeight
  	 *            Source rectangle height.
  	 * @param targetX
  	 *            Target rectangle x pos.
  	 * @param targetY
  	 *            Source rectangle y pos.
  	 * @param targetWidth
  	 *            Source rectangle width.
  	 * @param targetHeight
  	 *            Source rectangle height.
  	 * 
  	 * @return True if two rectangles intersect.
  	 */
  	public static boolean isIntersect(float sourceX, float sourceY, float sourceWidth, float sourceHeight, float targetX, float targetY, float targetWidth, float targetHeight)
  	{
  		float left1 = sourceX;
  		float left2 = targetX;
  		float right1 = sourceX + sourceWidth;
  		float right2 = targetX + targetWidth;
  
  		float top1 = sourceY;
  		float top2 = targetY;
  		float bottom1 = sourceY + sourceHeight;
  		float bottom2 = targetY + targetHeight;
  
  		if (bottom1 < top2)
  			return false;
  		if (top1 > bottom2)
  			return false;
  
  		if (right1 < left2)
  			return false;
  		if (left1 > right2)
  			return false;
  
  		return true;
  	}
  
  	/**
  	 * Look for target hit of specified class.
  	 * 
  	 * @param x
  	 *            Current x position.
  	 * @param y
  	 *            Current y position
  	 * @param stage
  	 *            The starting stage.
  	 * @param targetClass
  	 *            The target class type.
  	 * @return Target class or null if not found.
  	 */
  	@SuppressWarnings("rawtypes")
  	public static Actor hit(float x, float y, Stage stage, Class targetClass)
  	{
  		Group root = stage.getRoot();
  
  		SnapshotArray<Actor> children = root.getChildren();
  
  		Actor hit = null;
  		boolean found = false;
  		int index = children.size - 1;
  		while (!found && index >= 0)
  		{
  			Actor child = children.get(index);
  
  			point.x = x;
  			point.y = y;
  
  			root.localToDescendantCoordinates(child, point);
  
  			Actor childHit = root.hit(point.x, point.y, true);
  
  			if (childHit != null && childHit.getClass().isAssignableFrom(targetClass))
  			{
  				found = true;
  				hit = childHit;
  			}
  			else
  			{
  				index--;
  			}
  		}
  
  		return hit;
  	}
  
  }
  