// MonoGame - Copyright (C) The MonoGame Team // This file is subject to the terms and conditions defined in // file 'LICENSE.txt', which is part of this source code package. using System; using System.Collections.Generic; using System.Globalization; using Microsoft.Xna.Framework.Graphics; namespace Microsoft.Xna.Framework.Content.Pipeline.Graphics { /// /// Provides properties for managing a collection of vertex channel names. /// public static class VertexChannelNames { /// /// A lookup for the TryDecodeUsage method. /// static Dictionary usages; static VertexChannelNames() { // Populate the lookup for TryDecodeUsage usages = new Dictionary(); string[] names = Enum.GetNames(typeof(VertexElementUsage)); Array values = Enum.GetValues(typeof(VertexElementUsage)); for (int i = 0; i < names.Length; ++i) usages.Add(names[i], (VertexElementUsage)values.GetValue(i)); } /// /// Gets the name of a binormal vector channel with the specified index. /// This will typically contain Vector3 data. /// /// Zero-based index of the vector channel being retrieved. /// Name of the retrieved vector channel. public static string Binormal(int usageIndex) { return EncodeName(VertexElementUsage.Binormal, usageIndex); } /// /// Gets the name of a color channel with the specified index. /// This will typically contain Vector3 data. /// /// Zero-based index of the color channel being retrieved. /// Name of the retrieved color channel. public static string Color(int usageIndex) { return EncodeName(VertexElementUsage.Color, usageIndex); } /// /// Gets a channel base name stub from the encoded string format. /// /// Encoded string to be decoded. /// Extracted base name. public static string DecodeBaseName(string encodedName) { if (string.IsNullOrEmpty(encodedName)) throw new ArgumentNullException("encodedName"); return encodedName.TrimEnd("0123456789".ToCharArray()); } /// /// Gets a channel usage index from the encoded format. /// /// Encoded name to be decoded. /// Resulting channel usage index. public static int DecodeUsageIndex(string encodedName) { if (string.IsNullOrEmpty(encodedName)) throw new ArgumentNullException("encodedName"); // Extract the base name string baseName = DecodeBaseName(encodedName); if (string.IsNullOrEmpty(baseName)) throw new InvalidOperationException("encodedName"); // Subtract the base name from the string and convert the remainder to an integer. // TryParse solves the problem when name is just 'BlendIndicies' for example, in // which case we default to index 0, assuming only 1 index. int index = 0; int.TryParse(encodedName.Substring(baseName.Length), NumberStyles.Integer, CultureInfo.InvariantCulture, out index); return index; } /// /// Combines a channel name stub and usage index into a string name. /// /// A channel base name stub. /// A channel usage index. /// Resulting encoded name. public static string EncodeName(string baseName, int usageIndex) { return baseName + usageIndex.ToString(CultureInfo.InvariantCulture); } /// /// Combines a vertex declaration usage and usage index into a string name. /// /// A vertex declaration. /// An index for the vertex declaration. /// Resulting encoded name. public static string EncodeName(VertexElementUsage vertexElementUsage, int usageIndex) { return vertexElementUsage.ToString() + usageIndex.ToString(CultureInfo.InvariantCulture); } /// /// Gets the name of the primary normal channel. /// This will typically contain Vector3 data. /// /// Primary normal channel name. public static string Normal() { return Normal(0); } /// /// Gets the name of a normal channel with the specified index. /// This will typically contain Vector3 data. /// /// Zero-based index of the normal channel being retrieved. /// Normal channel at the specified index. public static string Normal(int usageIndex) { return EncodeName(VertexElementUsage.Normal, usageIndex); } /// /// Gets the name of a tangent vector channel with the specified index. /// This will typically contain Vector3 data. /// /// Zero-based index of the tangent vector channel being retrieved. /// Name of the retrieved tangent vector channel. public static string Tangent(int usageIndex) { return EncodeName(VertexElementUsage.Tangent, usageIndex); } /// /// Gets the name of a texture coordinate channel with the specified index. /// This will typically contain Vector3 data. /// /// Zero-based index of the texture coordinate channel being retrieved. /// Name of the retrieved texture coordinate channel. public static string TextureCoordinate(int usageIndex) { return EncodeName(VertexElementUsage.TextureCoordinate, usageIndex); } /// /// Gets a vertex declaration usage enumeration from the encoded string format. /// /// Encoded name of a vertex declaration. /// Value of the declaration usage for the vertex declaration. /// true if the encoded name maps to a VertexElementUsage enumeration value; false otherwise. public static bool TryDecodeUsage(string encodedName, out VertexElementUsage usage) { if (string.IsNullOrEmpty(encodedName)) throw new ArgumentNullException("encodedName"); // Extract the base name string baseName = DecodeBaseName(encodedName); if (string.IsNullOrEmpty(baseName)) throw new InvalidOperationException("encodedName"); return usages.TryGetValue(baseName, out usage); } /// /// Gets the name of the primary animation weights channel. /// This will typically contain data on the bone weights for a vertex channel. For more information, see BoneWeightCollection. /// /// Name of the primary animation weights channel. public static string Weights() { return Weights(0); } /// /// Gets the name of an animation weights channel at the specified index. /// This will typically contain data on the bone weights for a vertex channel. For more information, see BoneWeightCollection. /// /// Index of the animation weight channel to be retrieved. /// Name of the retrieved animation weights channel. public static string Weights(int usageIndex) { // This appears to be the odd one out that doesn't use the VertexElementUsage enum. return EncodeName("Weights", usageIndex); } } }