297 lines
7.3 KiB
C#
297 lines
7.3 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using Godot;
|
|
using System;
|
|
|
|
|
|
|
|
namespace Rokojori
|
|
{
|
|
public abstract class MaterialSurfaceContainer
|
|
{
|
|
public enum MaterialSlot
|
|
{
|
|
None,
|
|
MeshSurface,
|
|
MeshSurfaceOverride,
|
|
Override,
|
|
Overlay
|
|
}
|
|
|
|
protected Node3D _owner;
|
|
protected int _surfaceIndex;
|
|
public int surfaceIndex => _surfaceIndex;
|
|
|
|
protected MaterialSurfaceContainer( Node3D owner, int surfaceIndex )
|
|
{
|
|
_owner = owner;
|
|
_surfaceIndex = surfaceIndex;
|
|
}
|
|
|
|
public abstract MaterialSlot GetActiveMaterialSlot();
|
|
public abstract Material GetMaterialInSlot( MaterialSlot slot );
|
|
public abstract void SetMaterialInSlot( MaterialSlot slot, Material material );
|
|
|
|
public void SetActiveMaterial( Material material )
|
|
{
|
|
SetMaterialInSlot( GetActiveMaterialSlot(), material );
|
|
}
|
|
|
|
public Material GetActiveMaterial()
|
|
{
|
|
return GetMaterialInSlot( GetActiveMaterialSlot() );
|
|
}
|
|
|
|
protected abstract void _MakeUnique( bool materials );
|
|
|
|
public void MakeUnique( bool materials )
|
|
{
|
|
if ( ! isOwner )
|
|
{
|
|
return;
|
|
}
|
|
|
|
_MakeUnique( materials );
|
|
}
|
|
|
|
public bool isOwner => _surfaceIndex == -1;
|
|
|
|
|
|
public virtual List<MaterialSurfaceContainer> GetOwnedSurfaceContainers()
|
|
{
|
|
if ( ! isOwner )
|
|
{
|
|
return null;
|
|
}
|
|
|
|
var surfaces = numSurfaces;
|
|
var type = GetType();
|
|
|
|
var list = new List<MaterialSurfaceContainer>();
|
|
|
|
for ( int i = 0; i < surfaces; i++ )
|
|
{
|
|
var surfaceContainer = ReflectionHelper.Create<MaterialSurfaceContainer>( type, _owner, i );
|
|
list.Add( surfaceContainer );
|
|
}
|
|
|
|
return list;
|
|
}
|
|
|
|
public virtual void ForAllSurfaces( Action<MaterialSurfaceContainer> action )
|
|
{
|
|
var surfaces = GetOwnedSurfaceContainers();
|
|
surfaces.ForEach( s => action( s ) );
|
|
}
|
|
|
|
public abstract int numSurfaces { get; }
|
|
|
|
|
|
}
|
|
|
|
public abstract class MaterialSurfaceContainer<T>:MaterialSurfaceContainer where T:Node3D
|
|
{
|
|
public T node => (T)_owner;
|
|
protected MaterialSurfaceContainer( Node3D owner, int surfaceIndex ):base( owner, surfaceIndex ){}
|
|
|
|
}
|
|
|
|
public class MeshSurfaceContainer: MaterialSurfaceContainer<MeshInstance3D>
|
|
{
|
|
public MeshSurfaceContainer( MeshInstance3D owner, int surfaceIndex = -1 ):base( owner, surfaceIndex ){}
|
|
|
|
public override int numSurfaces => node == null || node.Mesh == null ? -1 : node.Mesh.GetSurfaceCount();
|
|
|
|
public override MeshSurfaceContainer.MaterialSlot GetActiveMaterialSlot()
|
|
{
|
|
if ( node.MaterialOverride != null )
|
|
{
|
|
return MeshSurfaceContainer.MaterialSlot.Override;
|
|
}
|
|
|
|
if ( node.Mesh == null || surfaceIndex == -1 )
|
|
{
|
|
return MeshSurfaceContainer.MaterialSlot.None;
|
|
}
|
|
|
|
if ( node.GetSurfaceOverrideMaterial( surfaceIndex ) != null )
|
|
{
|
|
return MeshSurfaceContainer.MaterialSlot.MeshSurfaceOverride;
|
|
}
|
|
|
|
var material = node.Mesh.SurfaceGetMaterial( surfaceIndex );
|
|
|
|
return material == null ? MeshSurfaceContainer.MaterialSlot.None : MeshSurfaceContainer.MaterialSlot.MeshSurface;
|
|
}
|
|
|
|
public override void SetMaterialInSlot( MaterialSlot slot, Material material )
|
|
{
|
|
if ( surfaceIndex == -1 || MaterialSlot.None == slot )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( MaterialSlot.MeshSurface == slot )
|
|
{
|
|
node.Mesh.SurfaceSetMaterial( surfaceIndex, material );
|
|
}
|
|
else if ( MaterialSlot.MeshSurfaceOverride == slot )
|
|
{
|
|
node.SetSurfaceOverrideMaterial( surfaceIndex, material );
|
|
}
|
|
else if ( MaterialSlot.Override == slot )
|
|
{
|
|
node.MaterialOverride = material;
|
|
}
|
|
else if ( MaterialSlot.Overlay == slot )
|
|
{
|
|
node.MaterialOverlay = material;
|
|
}
|
|
}
|
|
|
|
public override Material GetMaterialInSlot( MaterialSlot slot )
|
|
{
|
|
if ( MaterialSlot.None == slot )
|
|
{
|
|
return null;
|
|
}
|
|
else if ( MaterialSlot.MeshSurface == slot )
|
|
{
|
|
return node.Mesh.SurfaceGetMaterial( surfaceIndex );
|
|
}
|
|
else if ( MaterialSlot.MeshSurfaceOverride == slot )
|
|
{
|
|
return node.GetSurfaceOverrideMaterial( surfaceIndex );
|
|
}
|
|
else if ( MaterialSlot.Override == slot )
|
|
{
|
|
return node.MaterialOverride;
|
|
}
|
|
else if ( MaterialSlot.Overlay == slot )
|
|
{
|
|
return node.MaterialOverlay;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected override void _MakeUnique( bool materials )
|
|
{
|
|
if ( node.Mesh == null )
|
|
{
|
|
return;
|
|
}
|
|
|
|
node.Mesh = (Mesh)node.Mesh.Duplicate();
|
|
|
|
if ( ! materials )
|
|
{
|
|
return;
|
|
}
|
|
|
|
for ( int i = 0; i < numSurfaces; i++ )
|
|
{
|
|
var m = node.Mesh.SurfaceGetMaterial( i );
|
|
node.Mesh.SurfaceSetMaterial( i, (Material)m.Duplicate() );
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
public class MultiMeshSurfaceContainer: MaterialSurfaceContainer<MultiMeshInstance3D>
|
|
{
|
|
public MultiMeshSurfaceContainer( MultiMeshInstance3D mi, int surfaceIndex = -1 ):base( mi, surfaceIndex ){}
|
|
|
|
public override int numSurfaces => node == null || node.Multimesh == null || node.Multimesh.Mesh == null ? -1 :
|
|
node.Multimesh.Mesh.GetSurfaceCount();
|
|
|
|
public override MeshSurfaceContainer.MaterialSlot GetActiveMaterialSlot()
|
|
{
|
|
if ( node.MaterialOverride != null )
|
|
{
|
|
return MeshSurfaceContainer.MaterialSlot.Override;
|
|
}
|
|
|
|
if ( node.Multimesh == null || node.Multimesh.Mesh == null || surfaceIndex == -1 )
|
|
{
|
|
return MeshSurfaceContainer.MaterialSlot.None;
|
|
}
|
|
|
|
|
|
var material = node.Multimesh.Mesh.SurfaceGetMaterial( surfaceIndex );
|
|
|
|
return material == null ? MeshSurfaceContainer.MaterialSlot.None : MeshSurfaceContainer.MaterialSlot.MeshSurface;
|
|
}
|
|
|
|
public override void SetMaterialInSlot( MaterialSlot slot, Material material )
|
|
{
|
|
if ( surfaceIndex == -1 || MaterialSlot.None == slot )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( MaterialSlot.MeshSurface == slot )
|
|
{
|
|
node.Multimesh.Mesh.SurfaceSetMaterial( surfaceIndex, material );
|
|
}
|
|
else if ( MaterialSlot.Override == slot )
|
|
{
|
|
node.MaterialOverride = material;
|
|
}
|
|
else if ( MaterialSlot.Overlay == slot )
|
|
{
|
|
node.MaterialOverlay = material;
|
|
}
|
|
}
|
|
|
|
public override Material GetMaterialInSlot( MaterialSlot slot )
|
|
{
|
|
if ( MaterialSlot.None == slot )
|
|
{
|
|
return null;
|
|
}
|
|
else if ( MaterialSlot.MeshSurface == slot )
|
|
{
|
|
return node.Multimesh.Mesh.SurfaceGetMaterial( surfaceIndex );
|
|
}
|
|
else if ( MaterialSlot.Override == slot )
|
|
{
|
|
return node.MaterialOverride;
|
|
}
|
|
else if ( MaterialSlot.Overlay == slot )
|
|
{
|
|
return node.MaterialOverlay;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
protected override void _MakeUnique( bool materials )
|
|
{
|
|
if ( node.Multimesh == null || node.Multimesh.Mesh == null )
|
|
{
|
|
return;
|
|
}
|
|
|
|
node.Multimesh.Mesh = (Mesh)node.Multimesh.Mesh.Duplicate();
|
|
|
|
if ( ! materials )
|
|
{
|
|
return;
|
|
}
|
|
|
|
for ( int i = 0; i < numSurfaces; i++ )
|
|
{
|
|
var m = node.Multimesh.Mesh .SurfaceGetMaterial( i );
|
|
node.Multimesh.Mesh.SurfaceSetMaterial( i, (Material)m.Duplicate() );
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|