rj-action-library/Runtime/Shading/Materials/Materials.cs

179 lines
3.6 KiB
C#

using Godot;
using System.Reflection;
using System.Collections.Generic;
namespace Rokojori
{
public class Materials
{
public static int CountOf( Node node )
{
var s = new StandardMaterial3D();
if ( node is MeshInstance3D mi )
{
return mi.GetSurfaceOverrideMaterialCount();
}
return 1;
}
public static List<M> GetAll<M>( Node node, int index = 0 ) where M:Material
{
var list = new List<M>();
var count = CountOf( node );
for ( int i = 0; i < count; i++ )
{
list.Add( Get<M>( node, index ) );
}
return list;
}
public static M Get<M>( Node node, int index = 0 ) where M:Material
{
if ( node is MeshInstance3D mi )
{
var material = mi.GetSurfaceOverrideMaterial( index ) as M;
if ( material != null )
{
return material;
}
}
else if ( node is CsgPrimitive3D )
{
return ReflectionHelper.GetMemberValue( node, "material" ) as M;
}
else if ( node is GpuParticles3D gp)
{
return gp.ProcessMaterial as M;
}
if ( node is GeometryInstance3D gi )
{
return gi.MaterialOverride as M;
}
return null;
}
public static void SetAll( Node node, Material material )
{
var count = CountOf( node );
for ( int i = 0; i < count; i++ )
{
Set( node, material, i );
}
}
public static void Set( Node node, List<Material> materials )
{
var count = CountOf( node );
for ( int i = 0; i < count && i < materials.Count; i++ )
{
Set( node, materials[ i ], i );
}
}
public static void Set( Node node, Material material, int index = 0 )
{
if ( node is MeshInstance3D mi)
{
mi.SetSurfaceOverrideMaterial( index, material );
if ( index == 0 && mi.MaterialOverride != null )
{
mi.MaterialOverride = null;
}
return;
}
if ( node is CsgPrimitive3D csg )
{
ReflectionHelper.SetMemberValue( node, "material", material );
if ( csg.MaterialOverride != null )
{
csg.MaterialOverride = null;
}
return;
}
if ( node is GpuParticles3D gp )
{
gp.ProcessMaterial = material;
if ( gp.MaterialOverride != null )
{
gp.MaterialOverride = null;
}
}
if ( node is GeometryInstance3D gi )
{
gi.MaterialOverride = material;
return;
}
}
public static void AddOverlay( Node node, Material material, bool forceTop = true )
{
if ( node is GeometryInstance3D gi )
{
if ( gi.MaterialOverlay == null || forceTop )
{
gi.MaterialOverlay = material;
}
else
{
gi.MaterialOverlay.NextPass = material;
}
return;
}
}
public static void RemoveOverlay( Node node, Material material, bool forceTop = true )
{
if ( node is GeometryInstance3D gi )
{
if ( forceTop )
{
gi.MaterialOverlay = null;
}
else if ( gi.MaterialOverlay == material )
{
gi.MaterialOverlay = gi.MaterialOverlay.NextPass;
}
else
{
var mo = gi.MaterialOverlay;
while ( mo != null && mo.NextPass != material )
{
mo = mo.NextPass;
}
var next = material.NextPass;
mo.NextPass = next;
}
return;
}
}
}
}