/// <summary> Creates a texture for the given element. </summary> /// <param name="elementStyle"> The style of the element. </param> /// <param name="bounds"> The bounds of the element. </param> /// <returns> The element texture. </returns> public Texture2D CreateElementTexture(ElementStyle elementStyle, Rectangle bounds) { //The graphics device to load the textures onto GraphicsDevice graphicsDevice = textures.First().Value.GraphicsDevice; //A 3x3 array of the corners, edges, and fill of the texture. Imagine the texture being split into 3s based on the edges and corners //Calculates the borders and fills in the edges of the array with the relevant textures Texture2D[,] textureComponents = calculateBorder(elementStyle, graphicsDevice); //Sets the centre of the texture to the background texture textureComponents[1, 1] = calculateBackground(elementStyle, graphicsDevice); //Create the full texture from the components and return it return(constructElementTexture(elementStyle, graphicsDevice, textureComponents, bounds)); }
/// <summary> Cuts a texture from the main atlas based on given parameters. </summary> /// <param name="elementStyle"> The style of the element to read. </param> /// <param name="graphicsDevice"> The graphics device to create the texture on. </param> /// <returns></returns> private Texture2D calculateBackground(ElementStyle elementStyle, GraphicsDevice graphicsDevice) { //A new texture to be returned Texture2D backgroundTexture; //Information about the style parameters bool containsBackgroundNode = elementStyle.Parameters.ContainsKey("Background"); bool containsImageParameter = containsBackgroundNode ? elementStyle.Parameters["Background"].Parameters.ContainsKey("Image") : false; bool containsColourParameter = containsBackgroundNode ? elementStyle.Parameters["Background"].Parameters.ContainsKey("Colour") : false; //If there's no background style node or no image name parameter, return a default background if (!containsBackgroundNode || (containsBackgroundNode && !containsImageParameter)) { //Create a 1x1 texture backgroundTexture = new Texture2D(graphicsDevice, 1, 1); //Since we know there's no image parameter, check if there's a colour parameter and use that to colour the texture instead of the default colour Color backgroundColour = containsColourParameter ? elementStyle.Parameters["Background"].Parameters["Colour"].ParseColour() : Color.Honeydew; //Set the texture to the colour and return it backgroundTexture.SetData(new Color[1] { backgroundColour }); return(backgroundTexture); } //The Background node of the style StyleParameter backgroundParameter = elementStyle.Parameters["Background"]; //If the texture doesn't exist within the list, throw an error if (!textures.ContainsKey(backgroundParameter.Parameters["Image"])) { throw new Exception("Image parameter does not match texture defined in Resources node."); } //The main image the background will be cut from Texture2D backgroundAtlas = textures[backgroundParameter.Parameters["Image"]]; //If a source is given, return that cut from the atlas, otherwise return the atlas itself if (backgroundParameter.Parameters.ContainsKey("Source")) { return(backgroundAtlas.GetTexture(backgroundParameter.Parameters["Source"].ParseRectangle())); } else { return(backgroundAtlas); } }
public Color GetElementFontColour(ElementStyle elementStyle) { //Throw an error if the text node doesn't exist if (!elementStyle.Parameters.ContainsKey("Text")) { throw new Exception("Text node was missing from style node."); } if (elementStyle.Parameters["Text"].Parameters.ContainsKey("Colour")) { return(elementStyle.Parameters["Text"].Parameters["Colour"].ParseColour()); } else { return(Color.Black); } }
/// <summary> Pieces together the components of the element texture and constructs it. </summary> /// <param name="elementStyle"> The style of the element. </param> /// <param name="graphicsDevice"> The graphics device to create the texture with. </param> /// <param name="components"> The components of the texture. </param> /// <param name="bounds"> The bounds of the element. </param> /// <returns> The constructed texture. </returns> private Texture2D constructElementTexture(ElementStyle elementStyle, GraphicsDevice graphicsDevice, Texture2D[,] components, Rectangle bounds) { //Tints the texture based on the given colour, or doesn't tint at all if no colour is given Color backgroundColour = (elementStyle.Parameters.ContainsKey("Background") && elementStyle.Parameters["Background"].Parameters.ContainsKey("Colour")) ? elementStyle.Parameters["Background"].Parameters["Colour"].ParseColour() : Color.White; Color borderColour = (elementStyle.Parameters.ContainsKey("Border") && elementStyle.Parameters["Border"].Parameters.ContainsKey("Colour")) ? elementStyle.Parameters["Border"].Parameters["Colour"].ParseColour() : Color.White; //If the background should tile bool tileBackground = (elementStyle.Parameters.ContainsKey("Background") && elementStyle.Parameters["Background"].Parameters.ContainsKey("Tiled")) ? bool.Parse(elementStyle.Parameters["Background"].Parameters["Tiled"]) : true; //Changes what the spritebatch draws to, so it can be saved to a Texture2D RenderTarget2D target = new RenderTarget2D(graphicsDevice, bounds.Width, bounds.Height); graphicsDevice.SetRenderTarget(target); graphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Transparent, 1f, 0); //Creates a new spritebatch to draw to the target using (SpriteBatch sprite = new SpriteBatch(graphicsDevice)) { //Begins drawing sprite.Begin(); //Draws the background drawBackground(sprite, components, target.Bounds, backgroundColour, tileBackground); //Draws the edges drawEdges(sprite, components, target.Bounds, borderColour); //Draws the corners drawCorners(sprite, components, target.Bounds, borderColour); //Finishes drawing sprite.End(); } //Creates a texture from the target Texture2D elementTexture = target; //Sets the render target back to the screen graphicsDevice.SetRenderTarget(null); //Returns the final texture return(elementTexture); }
/// <summary> Gets the best suited style from the given element. </summary> /// <param name="element"> The element to find a style for. </param> /// <returns> The best suited style. </returns> public ElementStyle GetElementStyle(Element element, string styleName) { //Creates a new blank style to return ElementStyle finalStyle = new ElementStyle() { Parameters = new Dictionary <string, StyleParameter>() }; //Finds all styles in the main list that are valid for the given element, then sort them from least to most relevant List <ElementStyle> applicableStyles = styles.FindAll(s => element.GetType().DerivesFrom(s.Type) && (s.Name == styleName || s.Name == string.Empty)); applicableStyles = applicableStyles.OrderBy(s => s.Type.InheritanceLevel(element.GetType())).ThenBy(s => s.Name).ToList(); //Go through each applicable style foreach (ElementStyle style in applicableStyles) { foreach (StyleParameter parameter in style.Parameters.Values) { //If the parameters doesn't exist, make a new StyleParameter for it. This avoids reference type fuckery if (!finalStyle.Parameters.ContainsKey(parameter.Name)) { finalStyle.Parameters[parameter.Name] = new StyleParameter() { Parameters = new Dictionary <string, string>() } } ; //Copy all the parameters, overwriting any old ones foreach (KeyValuePair <string, string> subParam in parameter.Parameters) { finalStyle.Parameters[parameter.Name].Parameters[subParam.Key] = subParam.Value; } } } //Once the finalStyle has been overwritten fully, return it return(finalStyle); }
public SpriteFont GetElementFont(ElementStyle elementStyle) { //Throw an error if the text node doesn't exist if (!elementStyle.Parameters.ContainsKey("Text")) { throw new Exception("Text node was missing from style node."); } //Throw an error if the font parameter doesn't exist if (!elementStyle.Parameters["Text"].Parameters.ContainsKey("Font")) { throw new Exception("Font parameter was missing from Text node."); } //Throw an error if the font doesn't exist if (!fonts.ContainsKey(elementStyle.Parameters["Text"].Parameters["Font"])) { throw new Exception("Font parameter does not match SpriteFont defined in Resources node."); } return(fonts[elementStyle.Parameters["Text"].Parameters["Font"]]); }
/// <summary> Calculates the corners and edges of the border and fills them into a 3x3 array. </summary> /// <param name="elementStyle"> The style of the element. </param> /// <param name="graphicsDevice"> The graphics device to load onto. </param> /// <returns> A 3x3 Texture2D array with the edges and corners filled in. </returns> private Texture2D[,] calculateBorder(ElementStyle elementStyle, GraphicsDevice graphicsDevice) { //A new texture to be returned Texture2D borderAtlas; //Information about the style parameters bool containsBorderNode = elementStyle.Parameters.ContainsKey("Border"); bool containsImageParameter = containsBorderNode ? elementStyle.Parameters["Border"].Parameters.ContainsKey("Image") : false; bool containsColourParameter = containsBorderNode ? elementStyle.Parameters["Border"].Parameters.ContainsKey("Colour") : false; //If there's no border style node or no image name parameter, return a default background if (!containsBorderNode || (containsBorderNode && !containsImageParameter)) { //Create a 1x1 texture borderAtlas = new Texture2D(graphicsDevice, 1, 1); //Since we know there's no image parameter, check if there's a colour parameter and use that to colour the texture instead of the default colour Color borderColour = containsColourParameter ? elementStyle.Parameters["Border"].Parameters["Colour"].ParseColour() : Color.Black; //Set the texture to the colour borderAtlas.SetData(new Color[1] { borderColour }); //Use this texture for the edges of an array and return it return(new Texture2D[3, 3] { { borderAtlas, borderAtlas, borderAtlas }, { borderAtlas, null, borderAtlas }, { borderAtlas, borderAtlas, borderAtlas } }); } //The border node of the style StyleParameter borderParameter = elementStyle.Parameters["Border"]; //If the texture doesn't exist within the list, throw an error if (!textures.ContainsKey(borderParameter.Parameters["Image"])) { throw new Exception("Image parameter does not match texture defined in Resources node."); } //The atlas that the edges and corners are cut from borderAtlas = textures[borderParameter.Parameters["Image"]]; //Initialises the array Texture2D[,] borderArray = new Texture2D[3, 3]; //Local function that cuts from the given atlas using the given string rectangle Texture2D calculateBorderPiece(string source, Texture2D atlas) => atlas.GetTexture(source.ParseRectangle()); //Given a corner source, all corners will use this unless specified otherwise. Defaults to the atlas Texture2D defaultCorner = (borderParameter.Parameters.ContainsKey("Corner")) ? calculateBorderPiece(borderParameter.Parameters["Corner"], borderAtlas) : borderAtlas; //Sets the corners borderArray[0, 0] = (borderParameter.Parameters.ContainsKey("TopLeft-Corner")) ? calculateBorderPiece(borderParameter.Parameters["TopLeft-Corner"], borderAtlas) : defaultCorner; borderArray[2, 0] = (borderParameter.Parameters.ContainsKey("TopRight-Corner")) ? calculateBorderPiece(borderParameter.Parameters["TopRight-Corner"], borderAtlas) : defaultCorner.Rotate(1); borderArray[0, 2] = (borderParameter.Parameters.ContainsKey("BottomLeft-Corner")) ? calculateBorderPiece(borderParameter.Parameters["BottomLeft-Corner"], borderAtlas) : defaultCorner.Rotate(3); borderArray[2, 2] = (borderParameter.Parameters.ContainsKey("BottomRight-Corner")) ? calculateBorderPiece(borderParameter.Parameters["BottomRight-Corner"], borderAtlas) : defaultCorner.Rotate(2); //Given an edge source, all edges will use this unless specified otherwise. Defaults to the atlas Texture2D defaultEdge = (borderParameter.Parameters.ContainsKey("Edge")) ? calculateBorderPiece(borderParameter.Parameters["Edge"], borderAtlas) : borderAtlas; //Sets the edges borderArray[1, 0] = (borderParameter.Parameters.ContainsKey("Top-Edge")) ? calculateBorderPiece(borderParameter.Parameters["Top-Edge"], borderAtlas) : defaultEdge; borderArray[0, 1] = (borderParameter.Parameters.ContainsKey("Left-Edge")) ? calculateBorderPiece(borderParameter.Parameters["Left-Edge"], borderAtlas) : defaultEdge.Rotate(3); borderArray[1, 2] = (borderParameter.Parameters.ContainsKey("Bottom-Edge")) ? calculateBorderPiece(borderParameter.Parameters["Bottom-Edge"], borderAtlas) : defaultEdge.Rotate(2); borderArray[2, 1] = (borderParameter.Parameters.ContainsKey("Right-Edge")) ? calculateBorderPiece(borderParameter.Parameters["Right-Edge"], borderAtlas) : defaultEdge.Rotate(1); //Returns the final array return(borderArray); }
/// <summary> Goes through the main style node and loads it into a list of data. </summary> /// <param name="styleNode"> The style node. </param> private void loadStyles(XmlNode styleNode) { //Checks that the style node exists and has children if (styleNode == null) { throw new Exception("Missing Style node."); } if (!styleNode.HasChildNodes) { throw new Exception("Style node has no child nodes."); } //Initialises the style list styles = new List <ElementStyle>(styleNode.ChildNodes.Count); //Goes through each element style node and adds it to the styles for (int s = 0; s < styleNode.ChildNodes.Count; s++) { //This style's node XmlNode elementStyleNode = styleNode.ChildNodes[s]; //Creates a new ElementStyle to store this style ElementStyle style = new ElementStyle(); //Sets the style's type, as long as the type is within the Element namespace if (typeof(Element).Assembly.GetType(typeof(Element).Namespace + "." + elementStyleNode.Name) != null) { style.Type = typeof(Element).Assembly.GetType(typeof(Element).Namespace + "." + elementStyleNode.Name); } else { throw new Exception("Invalid style type, style node's name must match element name."); } //Sets the style's name if supplied, otherwise defaults to string.Empty style.Name = (elementStyleNode.Attributes.GetNamedItem("Name") == null) ? string.Empty : elementStyleNode.Attributes.GetNamedItem("Name").Value; //Initialises the style's parameters array style.Parameters = new Dictionary <string, StyleParameter>(elementStyleNode.ChildNodes.Count); //Goes through each node within the element style node foreach (XmlNode styleParameter in elementStyleNode.ChildNodes) { //Creates a StyleParameter with the given name StyleParameter parameter = new StyleParameter() { Name = styleParameter.Name, Parameters = new Dictionary <string, string>(styleParameter.Attributes.Count) }; //Goes through each attribute of the parameter and adds it to the styleParameter's dictionary foreach (XmlAttribute attribute in styleParameter.Attributes) { parameter.Parameters[attribute.Name] = attribute.Value; } //Adds the parameter to the style style.Parameters[styleParameter.Name] = parameter; } //Adds the style to the list styles.Add(style); } }