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

210 lines
4.3 KiB
C#
Raw Normal View History

2025-01-03 12:09:23 +00:00
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 )
{
2025-01-17 17:44:27 +00:00
return ReflectionHelper.GetDataMemberValue<M>( node, "material" );
2025-01-03 12:09:23 +00:00
}
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 )
{
2025-01-17 17:44:27 +00:00
ReflectionHelper.SetDataMemberValue( node, "material", material );
2025-01-03 12:09:23 +00:00
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;
}
}
2025-01-19 20:35:51 +00:00
public static Material GetLastMaterial( Material material )
{
while ( material != null )
{
var nextMaterial = material.NextPass;
if ( nextMaterial == null )
{
return material;
}
material = nextMaterial;
}
return null;
}
public static Material GetLastMaterialOverlay( Node node )
{
if ( node is GeometryInstance3D gi )
{
return GetLastMaterial( gi.MaterialOverlay );
}
return null;
}
public static Material GetPreviousPass( Material firstMaterial, Material nextMaterial )
{
var material = firstMaterial;
while ( material != null )
{
if ( material.NextPass == nextMaterial )
{
return material;
}
material = material.NextPass;
}
return null;
}
2025-01-03 12:09:23 +00:00
public static void AddOverlay( Node node, Material material, bool forceTop = true )
{
2025-01-19 20:35:51 +00:00
if ( node is GeometryInstance3D gi )
2025-01-03 12:09:23 +00:00
{
if ( gi.MaterialOverlay == null || forceTop )
{
gi.MaterialOverlay = material;
2025-01-19 20:35:51 +00:00
return;
2025-01-03 12:09:23 +00:00
}
2025-01-19 20:35:51 +00:00
GetLastMaterial( gi.MaterialOverlay ).NextPass = material;
2025-01-03 12:09:23 +00:00
return;
}
}
public static void RemoveOverlay( Node node, Material material, bool forceTop = true )
{
if ( node is GeometryInstance3D gi )
{
2025-01-19 20:35:51 +00:00
if ( gi.MaterialOverlay == material || forceTop )
2025-01-03 12:09:23 +00:00
{
gi.MaterialOverlay = null;
}
else
{
2025-01-19 20:35:51 +00:00
var previous = GetPreviousPass( gi.MaterialOverlay, material );
previous.NextPass = null;
2025-01-03 12:09:23 +00:00
}
return;
}
}
}
}