Interface and runtime host for architecture-related configuration. IArchHost declares two string properties for blockout shader and material library paths. ArchHost provides defaults, loads an implementation via ArchDiscovery.EnrolledByName<IArchHost>().FirstOrDefault(), and returns an instance using provided answers or stock fallbacks.
namespace Sunless.Architecture;
// What the tool cannot know about the game it generates into. A game answers here rather than repainting what the
// tool produced; nothing answering is the tool standing on its own, so every fact has a stock answer.
public interface IArchHost
{
// The shader a generated blockout material is written against. A game with its own lighting model names it
// here instead of rewriting every .vmat the tool just wrote.
string BlockoutShader { get; }
// Where the material browser looks for the surface library, relative to the open project's root.
string MaterialLibrary { get; }
}
// Never held between asks, for the reason ArchDoorFitters is not: hotload carries a static over.
public sealed class ArchHost
{
// The library's own, because complex.shader tints through g_vColorTint and every generated blockout material
// states its colour as g_flTintColor - on the stock shader the tint was dropped and the lot rendered white.
public const string StockShader = "shaders/arch_blockout.shader";
public const string StockLibrary = "Assets/materials";
public string BlockoutShader { get; private init; } = StockShader;
public string MaterialLibrary { get; private init; } = StockLibrary;
// Ordered by name and first answer taken, so two games open in one editor cannot make the result depend on
// which assembly enrolled first. A fact left blank falls back rather than writing an empty shader path.
public static ArchHost Load()
{
var spoken = ArchDiscovery.EnrolledByName<IArchHost>().FirstOrDefault();
if ( spoken is null )
{
return new ArchHost();
}
return new ArchHost
{
BlockoutShader = Answered( spoken.BlockoutShader, StockShader ),
MaterialLibrary = Answered( spoken.MaterialLibrary, StockLibrary )
};
}
static string Answered( string answer, string stock )
{
return string.IsNullOrWhiteSpace( answer ) ? stock : answer;
}
}