|
#region Using Statements
using System;
using System.Xml;
using System.IO;
using System.Reflection;
using System.Collections.Generic;
using Microsoft.DirectX.Direct3D;
using System.Collections.ObjectModel;
using Microsoft.DirectX;
using AViD.Figures;
#endregion Using Statements
namespace AViD
{
/// <summary>
/// The abstract <see cref="Figure"/> class is used to provide a basic
/// layer of functionality to simplify the rendering of the dendrimer
/// sub-components.
/// </summary>
public abstract class Figure
{
#region Constants
private const string _XML_GENERATION = "Generation";
private const string _XML_POSITION = "Position";
private const string _XML_RENDER_FIGURE = "RenderFigure";
#endregion Constants
#region Static Methods
/// <summary>
/// Gets the current figure and all of its children (and subsequent children)
/// into a single array.
/// </summary>
/// <param name="figure">The figure at which to start processing from.</param>
/// <param name="blnIncludeOnlyVisible">True - Includes only visible figures. False - Includes all figures.</param>
/// <returns>An array of the current figure and all of its children (and subsequent children).</returns>
public static Figure[] GetAllFigures(Figure figure, bool blnIncludeOnlyVisible)
{
List<Figure> lstResult;
lstResult = new List<Figure>(figure.Children.Length + 1);
if (figure.Visible || !blnIncludeOnlyVisible)
{
lstResult.Add(figure);
foreach (Figure child in figure.Children)
lstResult.AddRange(Figure.GetAllFigures(child, blnIncludeOnlyVisible));
}
return lstResult.ToArray();
}
/// <summary>
/// Loads the figure from an <see cref="XmlNode"/>.
/// </summary>
/// <param name="device">The <see cref="Device"/> to bind the stick to.</param>
/// <param name="xmlNode">The <see cref="XmlNode"/> containing the figure's data.</param>
/// <exception cref="ArgumentException">In the event that the file contains a value that is invalid,
/// an <see cref="ArgumentException"/> could be thrown.</exception>
/// <exception cref="ArgumentNullException">In the event that the file contains a value that is invalid,
/// an <see cref="ArgumentNullException"/> could be thrown.</exception>
/// <exception cref="ArgumentOutOfRangeException">In the event that the file contains a value that is invalid,
/// an <see cref="ArgumentOutOfRangeException"/> could be thrown.</exception>
/// <returns>The resulting figure stored in the <see cref="XmlDocument"/>.</returns>
public static Figure LoadFigure(Device device, XmlNode xmlNode)
{
Figure figure;
XmlAttribute xmlAtt;
int intGeneration;
Vector3 vecPosition;
bool blnRenderFigure;
// Take the first xml node in the document and load it.
switch (xmlNode.Name)
{
case Ball.XmlName:
figure = Ball.Load(device, xmlNode);
break;
case SimpleLine.XmlName:
figure = SimpleLine.Load(device, xmlNode);
break;
case Stick.XmlName:
figure = Stick.Load(device, xmlNode);
break;
default:
throw new NotImplementedException(string.Format("Unable to load a figure of type, {0}, from the xml.", xmlNode.Name));
}
// Load any base 'figure' elements.
if (((xmlAtt = xmlNode.Attributes[Figure._XML_GENERATION]) == null) || !int.TryParse(xmlAtt.InnerText, out intGeneration))
intGeneration = 0;
if (((xmlAtt = xmlNode.Attributes[Figure._XML_POSITION]) == null) || !Utility.LoadVectorFromString(xmlAtt.InnerText, out vecPosition))
vecPosition = Vector3.Empty;
if (((xmlAtt = xmlNode.Attributes[Figure._XML_RENDER_FIGURE]) == null) || !bool.TryParse(xmlAtt.InnerText, out blnRenderFigure))
blnRenderFigure = true;
// Set the values into the figure.
figure.Generation = intGeneration;
figure.Position = vecPosition;
figure.Visible = blnRenderFigure;
// Load any children.
foreach (XmlNode xmlChild in xmlNode.ChildNodes)
figure.AddChild(Figure.LoadFigure(device, xmlChild));
return figure;
}
#endregion Static Methods
#region Constructor
/// <summary>
/// Initializes the underlying components necessary for the <see cref="Figure"/>
/// class.
/// </summary>
/// <param name="intGeneration">The number indicating the generation of the figure.</param>
/// <param name="position">The starting position of the figure.</param>
public Figure(int intGeneration, Vector3 position)
{
this.Generation = intGeneration;
this.Position = position;
this.m_blnRenderFigure = true;
this.m_lstChildren = new List<Figure>();
}
#endregion Constructor
#region Public Properties
/// <summary>
/// Gets the number indicating the generation of the figure.
/// </summary>
public int Generation
{
get
{
return this.m_intGeneration;
}
protected set
{
this.m_intGeneration = value;
}
}
/// <summary>
/// Gets/sets the position of the figure.
/// </summary>
public virtual Vector3 Position
{
get
{
return this.m_vecPosition;
}
set
{
this.m_vecPosition = value;
}
}
/// <summary>
/// Gets the material associated to the figure.
/// </summary>
public virtual Material Material
{
get
{
return this.m_Material;
}
set
{
this.m_Material = value;
}
}
/// <summary>
/// Gets the <see cref="Figure"/> parent of the current <see cref="Figure"/>.
/// </summary>
public Figure Parent
{
get
{
return this.m_Parent;
}
}
/// <summary>
/// Gets the <see cref="Figure"/> children of the current <see cref="Figure"/>.
/// </summary>
public Figure[] Children
{
get
{
return this.m_lstChildren.ToArray();
}
}
/// <summary>
/// Gets/sets whether or not the parent should render the figure.
/// </summary>
public bool RenderFigure
{
get
{
return this.m_blnRenderFigure;
}
set
{
this.m_blnRenderFigure = value;
}
}
/// <summary>
/// Gets/sets whether or not the current figure is visible.
/// </summary>
public bool Visible
{
get
{
return this.m_blnVisible;
}
set
{
this.m_blnVisible = value;
}
}
#endregion Public Properties
#region Public Methods
/// <summary>
/// Adds the <see cref="Figure"/> to the current parent.
/// </summary>
/// <param name="figure">The figure to add to the parent.</param>
public void AddChild(Figure figure)
{
figure.m_Parent = this;
this.m_lstChildren.Add(figure);
}
/// <summary>
/// Removes the <see cref="Figure"/> from the current parent.
/// </summary>
/// <param name="figure">The figure to remove from the parent.</param>
/// <returns>True - Indicating it was removed, False - indicating it was not.</returns>
public bool RemoveChild(Figure figure)
{
if (this.m_lstChildren.Remove(figure))
{
// Clear the parent.
figure.m_Parent = null;
return true;
}
else
return false;
}
/// <summary>
/// Attempts to find the figure that intersects with the provided ray. The parent figure
/// and all of its children will be searched.
/// </summary>
/// <param name="vecPosition">The <see cref="Vector3"/> indicating the origin of the ray.</param>
/// <param name="vecDirection">The <see cref="Vector3"/> indicating the direction of the ray.</param>
/// <param name="figure">The figure that intersected the ray.</param>
/// <returns>Indicates true if the ray intersects a face on the figure. Otherwise, the value is false.</returns>
public bool FindFigure(Vector3 vecPosition, Vector3 vecDirection, out Figure figure)
{
Figure tempFigure;
float fltFigureDistance, fltTempFigureDistance;
if (this.RenderFigure && this.Visible && this.Intersect(vecPosition, vecDirection))
{
figure = this;
fltFigureDistance = Vector3.Subtract(vecPosition, this.Position).Length();
}
else
{
figure = null;
fltFigureDistance = float.MaxValue;
}
if (this.RenderFigure)
{
foreach (Figure childFigure in this.Children)
{
if (childFigure.FindFigure(vecPosition, vecDirection, out tempFigure))
{
// Find the distance from the position for the figure.
fltTempFigureDistance = Vector3.Subtract(vecPosition, tempFigure.Position).Length();
if ((figure == null) || (fltTempFigureDistance < fltFigureDistance))
{
figure = tempFigure;
fltFigureDistance = fltTempFigureDistance;
}
}
}
}
return (figure != null);
}
/// <summary>
/// Determines whether a ray intersects with the figure.
/// </summary>
/// <param name="vecPosition">The <see cref="Vector3"/> indicating the origin of the ray.</param>
/// <param name="vecDirection">The <see cref="Vector3"/> indicating the direction of the ray.</param>
/// <returns>Indicates true if the ray intersects a face on the figure. Otherwise, the value is false.</returns>
public virtual bool Intersect(Vector3 vecPosition, Vector3 vecDirection)
{
return false;
}
/// <summary>
/// Renders the entire figure to the user.
/// </summary>
/// <param name="device">The device to render to.</param>
public void Render(Device device)
{
if (this.RenderFigure)
{
// We mark which objects are rendered to help in the pin-pointing of objects
// are interactable on the UI.
this.m_blnVisible = true;
this._RenderCurrentFigure(device);
foreach (Figure childFigure in this.Children)
childFigure.Render(device);
}
else
this._ResetVisibleFlag();
}
/// <summary>
/// Renders the figure to the user.
/// </summary>
/// <param name="device">The device to render to.</param>
/// <param name="intMaximumGeneration">The maximum generation to render to.</param>
public void RenderToGeneration(Device device, int intMaximumGeneration)
{
if (this.Generation <= intMaximumGeneration)
{
if (this.RenderFigure)
{
// We mark which objects are rendered to help in the pin-pointing of objects
// are interactable on the UI.
this.m_blnVisible = true;
this._RenderCurrentFigure(device);
foreach (Figure childFigure in this.Children)
childFigure.RenderToGeneration(device, intMaximumGeneration);
}
else
this._ResetVisibleFlag();
}
else
this._ResetVisibleFlag();
}
/// <summary>
/// Resets all RenderChildren flags on the current figure and its children to True.
/// </summary>
public void ResetRenderChildrenFlags()
{
this.RenderFigure = true;
foreach (Figure child in this.Children)
child.ResetRenderChildrenFlags();
}
/// <summary>
/// Saves the figure to an <see cref="XmlDocument"/>.
/// </summary>
/// <param name="xmlNode">The <see cref="XmlNode"/> to save the Figure to.</param>
public void Save(XmlNode xmlNode)
{
// Insert into the document the current figure's data.
xmlNode.AppendChild(this._SaveRecursive(xmlNode.OwnerDocument));
}
#endregion Public Methods
#region Protected Members
protected int m_intGeneration;
protected Vector3 m_vecPosition;
protected Material m_Material;
protected bool m_blnVisible;
protected bool m_blnRenderFigure;
protected Figure m_Parent;
protected List<Figure> m_lstChildren;
#endregion Protected Members
#region Protected Methods
/// <summary>
/// Saves the current <see cref="Figure"/> and all of its children resursively.
/// </summary>
/// <param name="xmlDoc">The <see cref="XmlDocument"/> to save the data to.</param>
/// <returns>The <see cref="XmlElement"/> containing the information of the current <see cref="Figure"/> and its children.</returns>
private XmlElement _SaveRecursive(XmlDocument xmlDoc)
{
XmlElement xmlElement;
XmlAttribute xmlAtt;
// Save the current figure.
xmlElement = this._Save(xmlDoc);
// Add on all the base 'figure' elements.
xmlElement.Attributes.Append(xmlAtt = xmlDoc.CreateAttribute(Figure._XML_GENERATION));
xmlAtt.InnerText = this.Generation.ToString();
xmlElement.Attributes.Append(xmlAtt = xmlDoc.CreateAttribute(Figure._XML_POSITION));
xmlAtt.InnerText = Utility.SaveVectorToString(this.Position);
xmlElement.Attributes.Append(xmlAtt = xmlDoc.CreateAttribute(Figure._XML_RENDER_FIGURE));
xmlAtt.InnerText = this.RenderFigure.ToString();
// Save all of its children recursively.
foreach (Figure child in this.Children)
xmlElement.AppendChild(child._SaveRecursive(xmlDoc));
return xmlElement;
}
/// <summary>
/// Resets the visible flag for the current figure and its children, the
/// flag is used to determine whether or not the figure is visible.
/// </summary>
protected void _ResetVisibleFlag()
{
this.m_blnVisible = false;
foreach (Figure childFigure in this.Children)
childFigure._ResetVisibleFlag();
}
/// <summary>
/// Saves the figure to a <see cref="XmlElement"/>.
/// </summary>
/// <param name="xmlDocument">The <see cref="XmlDocument"/> to create the element for.</param>
/// <returns>The XmlElement the Figure was saved to.</returns>
protected abstract XmlElement _Save(XmlDocument xmlDocument);
/// <summary>
/// Renders the current figure to the user.
/// </summary>
/// <param name="device">The device to render to.</param>
protected abstract void _RenderCurrentFigure(Device device);
#endregion Protected Methods
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
Since I've begun my profession as a software developer, I've learned one important fact - change is inevitable. Requirements change, code changes, and life changes.
So..If you're not moving forward, you're moving backwards.