Editor/MaterialHelper.cs
using System.Linq;
using Sandbox;
namespace SboxMcpServer;
/// <summary>
/// Helper utilities for material loading and application operations on PolygonMesh.
/// Provides centralized methods for material handling in mesh editing tools.
/// </summary>
internal static class MaterialHelper
{
/// <summary>
/// Default material path to use when no material is specified or loading fails.
/// </summary>
private const string DefaultMaterialPath = "materials/dev/reflectivity_30.vmat";
/// <summary>
/// Loads a Material asset from the given path.
/// Returns null if the path is invalid or loading fails.
/// </summary>
/// <param name="materialPath">Path to the material asset (e.g., "materials/dev/dev_01.vmat")</param>
/// <returns>The loaded Material, or null if loading fails</returns>
internal static Material LoadMaterial( string materialPath )
{
if ( string.IsNullOrEmpty( materialPath ) )
return null;
try
{
var material = Material.Load( materialPath );
return material;
}
catch
{
return null;
}
}
/// <summary>
/// Loads a Material asset from the given path, falling back to a default material if loading fails.
/// </summary>
/// <param name="materialPath">Path to the material asset (e.g., "materials/dev/dev_01.vmat")</param>
/// <returns>The loaded Material, or a default material if loading fails</returns>
internal static Material LoadMaterialOrDefault( string materialPath )
{
var material = LoadMaterial( materialPath );
if ( material != null )
return material;
return Material.Load( DefaultMaterialPath );
}
/// <summary>
/// Applies a material to a specific face in a PolygonMesh.
/// </summary>
/// <param name="mesh">The PolygonMesh to modify</param>
/// <param name="faceIndex">Index of the face (0-based)</param>
/// <param name="material">Material to apply</param>
/// <returns>True if successful, false otherwise</returns>
internal static bool ApplyMaterialToFace( PolygonMesh mesh, int faceIndex, Material material )
{
if ( mesh == null || material == null )
return false;
try
{
var faceHandle = mesh.FaceHandleFromIndex( faceIndex );
if ( !faceHandle.IsValid )
return false;
mesh.SetFaceMaterial( faceHandle, material );
return true;
}
catch
{
return false;
}
}
/// <summary>
/// Applies a material to a specific face in a PolygonMesh by material path.
/// </summary>
/// <param name="mesh">The PolygonMesh to modify</param>
/// <param name="faceIndex">Index of the face (0-based)</param>
/// <param name="materialPath">Path to the material asset</param>
/// <returns>True if successful, false otherwise</returns>
internal static bool ApplyMaterialToFace( PolygonMesh mesh, int faceIndex, string materialPath )
{
var material = LoadMaterial( materialPath );
if ( material == null )
return false;
return ApplyMaterialToFace( mesh, faceIndex, material );
}
/// <summary>
/// Aligns the texture coordinates of a face to the world grid.
/// This ensures textures align properly across faces.
/// </summary>
/// <param name="mesh">The PolygonMesh to modify</param>
/// <param name="faceIndex">Index of the face (0-based)</param>
/// <returns>True if successful, false otherwise</returns>
internal static bool TextureAlignToGrid( PolygonMesh mesh, int faceIndex )
{
if ( mesh == null )
return false;
try
{
var faceHandle = mesh.FaceHandleFromIndex( faceIndex );
if ( !faceHandle.IsValid )
return false;
mesh.TextureAlignToGrid( mesh.Transform, faceHandle );
return true;
}
catch
{
return false;
}
}
/// <summary>
/// Sets texture parameters for a specific face (UV axes and scale).
/// </summary>
/// <param name="mesh">The PolygonMesh to modify</param>
/// <param name="faceIndex">Index of the face (0-based)</param>
/// <param name="vAxisU">U axis direction vector</param>
/// <param name="vAxisV">V axis direction vector</param>
/// <param name="scale">Texture scale</param>
/// <returns>True if successful, false otherwise</returns>
internal static bool SetTextureParameters( PolygonMesh mesh, int faceIndex,
Vector3 vAxisU, Vector3 vAxisV, Vector2 scale )
{
if ( mesh == null )
return false;
try
{
var faceHandle = mesh.FaceHandleFromIndex( faceIndex );
if ( !faceHandle.IsValid )
return false;
mesh.SetFaceTextureParameters( faceHandle, vAxisU, vAxisV, scale );
return true;
}
catch
{
return false;
}
}
/// <summary>
/// Gets the current material assigned to a face.
/// </summary>
/// <param name="mesh">The PolygonMesh to query</param>
/// <param name="faceIndex">Index of the face (0-based)</param>
/// <returns>The Material assigned to the face, or null if invalid</returns>
internal static Material GetFaceMaterial( PolygonMesh mesh, int faceIndex )
{
if ( mesh == null )
return null;
try
{
var faceHandle = mesh.FaceHandleFromIndex( faceIndex );
if ( !faceHandle.IsValid )
return null;
return mesh.GetFaceMaterial( faceHandle );
}
catch
{
return null;
}
}
/// <summary>
/// Gets the number of faces in the mesh.
/// </summary>
internal static int GetFaceCount( PolygonMesh mesh )
{
return mesh?.FaceHandles?.Count() ?? 0;
}
/// <summary>
/// Gets the number of vertices in the mesh.
/// </summary>
internal static int GetVertexCount( PolygonMesh mesh )
{
return mesh?.VertexHandles?.Count() ?? 0;
}
/// <summary>
/// Gets the number of edges in the mesh.
/// </summary>
internal static int GetEdgeCount( PolygonMesh mesh )
{
return mesh?.HalfEdgeHandles?.Count() ?? 0;
}
}