/* * GUIComponent.cs * Authors: Bradley R. Blankenship * Copyright (c) 2007-2008 Cornell University This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Util; using System; namespace tAC_Engine.GUI { /// /// Defines the base attributes of all GUI components /// public abstract class GUIComponent : IComparable { #region Fields /// /// The position of the component (in world space) /// protected Vector2 mPosition; /// /// Offsets the text when drawing /// protected Vector2 mTextOffset; /// /// Transforms the position of the component from world space to screen space (keep as (0,0) to keep object in screen space) /// protected Vector2 mScreenOffset; /// /// The size of the component on screen /// protected Vector2 mSize; /// /// The rotation to draw the component /// protected float mRotation; /// /// SpriteEffects to use when drawing the component /// protected SpriteEffects mSpriteEffects = SpriteEffects.None; /// /// The bounds of the component /// protected Rectangle mBounds; /// /// The parent screen of the component /// protected GUIScreen mParentScreen; /// /// The parent component of the component /// protected GUIComponent mParentComponent; /// /// The sprite batch for drawing to the screen /// protected SpriteBatchProxy mSpriteBatch; /// /// The color to add to the sprite. /// protected Color mAddColor = Color.White; /// /// Whether we are visible or not /// protected bool mIsVisible = false; /// /// Whether we are considered enabled or not. /// protected bool mIsEnabled = false; /// /// The text for a tool tip /// protected string mToolTipText; /// /// Whether this can be clicked through or not /// protected bool mClickThrough = false; /// /// Draw order of this component. /// protected float mLayerDepth; #endregion #region Properties /// /// Allows access to the position of the component. /// public virtual Vector2 Position { get { return mPosition; } set { mPosition = value; calculateBounds(); } } /// /// Access the X position of the component. /// public virtual float X { get { return mPosition.X; } set { Position = new Vector2(value, Position.Y); } } /// /// Access the Y position of the component. /// public virtual float Y { get { return mPosition.Y; } set { Position = new Vector2(Position.X, value); } } /// /// Displaces the component from the screen /// public virtual Vector2 ScreenOffset { get { return mScreenOffset; } set { mScreenOffset = value; calculateBounds(); } } /// /// Allows access to the size of the component. /// public virtual Vector2 Size { get { return mSize; } set { mSize = value; calculateBounds(); } } /// /// Allows access to the rotation of the component. /// public virtual float Rotation { get { return mRotation; } set { mRotation = value; } } /// /// Allows access to the sprite effects of the component. /// public virtual SpriteEffects SpriteEffects { get { return mSpriteEffects; } set { mSpriteEffects = value; } } /// /// Allows others to view the bounds of the component. /// public Rectangle Bounds { get { return mBounds; } } /// /// Allows internal access to the parent screen. /// public GUIScreen ParentScreen { get { return mParentScreen; } set { mParentScreen = value; } } /// /// Allows internal access to the parent component. /// public GUIComponent ParentComponent { get { // Do this if the parent is null if (mParentComponent == null) { // Return ourselves return this; } else { // Return the real parent return mParentComponent; } } set { mParentComponent = value; } } /// /// Allows public access to the sprite batch. /// public SpriteBatchProxy Batch { get { return mSpriteBatch; } set { mSpriteBatch = value; } } /// /// Allows access to the additive color for the sprites. /// public virtual Color AddColor { get { return mAddColor; } set { mAddColor = value; } } /// /// Allows access to the visibility of the component. /// public virtual bool Visible { get { return mIsVisible; } set { mIsVisible = value; } } /// /// Sets the enabled quality of a value. /// public virtual bool Enabled { get { return mIsEnabled; } set { mIsEnabled = value; if (mIsEnabled) mAddColor = Color.White; else mAddColor = new Color(new Vector3(0.25f, 0.25f, 0.25f)); } } /// /// Allows access to the tool tip text. /// public string ToolTipText { get { return mToolTipText; } set { mToolTipText = value; } } /// /// Allow access to set whether the component can be clicked through /// or not. /// public bool ClickThrough { get { return mClickThrough; } set { mClickThrough = value; } } /// /// The draw order of this GUIComponent. /// [Obsolete("LayerDepth or DrawOrder should be determined by order in the Components list.")] public float LayerDepth { get { return mLayerDepth; } set { mLayerDepth = value; } } #endregion #region Constructs /// /// Create the intial values /// public GUIComponent() { // Initialize our other values Position = Vector2.Zero; Size = Vector2.Zero; // Initialize our bounds calculateBounds(); } #endregion #region Initialization /// /// Initializes the component. Override this method to load any non-graphics /// resources and query for any required services. /// public abstract void Initialize(); /// /// Called when graphics resources need to be loaded. Override this method to /// load any component-specific graphics resources. /// public virtual void LoadContent() { } /// /// Reinitializes the values of the component. /// public virtual void Resize() { } /// /// Reinitialize the values. /// public virtual void Reinitialize() { } #endregion #region Management /// /// Registers us with the given screen and allows the screen /// to add us to its list of components. /// /// The parent screen. public void Register(GUIScreen screen) { // Get the values for the GUI screen ParentScreen = screen; } /// /// Registers us with the given container and allows the /// container to add us to its list of components. /// /// public void Register(GUIContainer container) { // Get the values for the GUI Container ParentComponent = container; ParentScreen = container.ParentScreen; } #endregion #region Update /// /// Update the component based on its needs. /// /// The current game time. public abstract void Update(GameTime gameTime); /// /// Recalculates the bounds based on size, position, and screen offset /// protected void calculateBounds() { mBounds = new Rectangle( (int)(Position.X - mScreenOffset.X), (int)(Position.Y - mScreenOffset.Y), (int)Size.X, (int)Size.Y); } #endregion #region Event Handling /// /// Determines if the given point is inside of any of the GUI elements. /// /// The point to test. /// Whether the point is inside the GUI or not. public virtual bool IsInside(Point pPoint) { // the return value bool retVal = false; // Get the initialize value bool test = !ClickThrough; // If test if(test && Visible) { if (mRotation == 0) { // Do a global bounds check retVal = Bounds.Contains(pPoint); } else { // Rotate pPoint into local coordinates and check against that Vector2 localOffset = new Vector2(pPoint.X - Bounds.Location.X, pPoint.Y - Bounds.Location.Y); float localDiagonal = localOffset.Length(); double localRotation = Math.Atan2(localOffset.Y, localOffset.X) - mRotation; Point localPoint = new Point((int)(Math.Cos(localRotation) * localDiagonal), (int)(Math.Sin(localRotation) * localDiagonal)); if (localPoint.X > 0 && localPoint.Y < Bounds.Width && localPoint.Y > 0 && localPoint.Y < Bounds.Height) localRotation = 0; retVal = localPoint.X > 0 && localPoint.Y < Bounds.Width && localPoint.Y > 0 && localPoint.Y < Bounds.Height; } } // Return return retVal; } /// /// Handle the given mouse event we've received. /// /// The mouse event to handle. public abstract bool HandleMouseEvent(MouseInputEvent e); /// /// Handle the given key input event we've received. /// /// The key input event to handle. public abstract bool HandleKeyEvent(KeyInputEvent e); /// /// Returns the component that will be used for the tool tip. /// /// The vector position. /// The component for the tool tip. public virtual GUIComponent GetToolTipComponent(Point p) { // The return value GUIComponent retVal = null; // If we contain the vector if( this.Bounds.Contains(p) && this.Visible ) { // Set the retval retVal = this; } // Return the value return retVal; } #endregion #region Draw /// /// Draw the component to the screen. /// /// The current game time. public abstract void Draw(GameTime gameTime); #endregion #region IComparable Members public int CompareTo(object obj) { if (obj is GUIComponent) { float diff = this.LayerDepth - ((GUIComponent)obj).LayerDepth; if (diff < 0) return -1; else if (diff > 0) return 1; else return 0; } else { throw new ArgumentException("x and y are of different types."); } } #endregion } }