Editor/Carve/ArchExtrude.cs
using System;
namespace Sunless.Architecture;
// The deliberate sibling of a damage zone. Where that one breaks a corner open, this stands work PROUD of
// whichever elevation it covers - a pier between two shopfronts, a rusticated corner, a banded ground storey.
// Both are one dragged box asking the walls under it for a response, which is why neither is a part of its own.
public enum ArchExtrudeKind {
None,
Face,
Quoins,
Courses,
// The one kind that goes the other way. It belongs here rather than beside Subtract because a recess in an
// elevation is a FINISH on that elevation - it takes no wall away - and because the zone is the only thing
// that can give it a real height band: a modifier dragged in plan can only ever climb to the wall head.
Indent,
// A real dressed COLUMN engaged against the wall - footing, plinth, banded shaft and capital off an authored
// .pillartype - rather than a block on the face. It is the only kind whose work is not a wall modifier, so it
// is stood by ArchExtrudeAffector as a part the wall does not own, and its band crosses floor lines: that is
// what makes one gesture a support running the whole height of a building.
Pier
}
public static class ArchExtrude {
public const float LeastDepth = 0.5f;
public static ArchCutAffects Targets( ArchExtrudeKind kind ) {
return kind == ArchExtrudeKind.None ? ArchCutAffects.None : ArchCutAffects.Walls;
}
// Every kind is a wall modifier the tool already emitted, so the block stack, the material role and the piece
// it comes out as are answers ArchWallModKinds already had rather than three new ones.
public static ArchWallMod Section( ArchExtrudeKind kind ) => kind switch {
ArchExtrudeKind.Quoins => ArchWallMod.Quoin,
ArchExtrudeKind.Courses => ArchWallMod.Course,
ArchExtrudeKind.Indent => ArchWallMod.Indent,
_ => ArchWallMod.Pilaster
};
// A recess bites ONE elevation whatever the zone says. Offering it both faces would be offering a hole
// through the wall, which is Subtract's job and not a finish.
public static bool Coursed( ArchExtrudeKind kind ) => kind is ArchExtrudeKind.Quoins or ArchExtrudeKind.Courses;
// Whether the zone's work is a real part standing beside the wall rather than a modifier the wall carries.
// Asked here and never re-tested inline, so the wall generator and the affector cannot disagree about which
// zones are theirs.
public static bool Stands( ArchExtrudeKind kind ) => kind == ArchExtrudeKind.Pier;
public static bool Dresses( ArchExtrudeKind kind ) => kind != ArchExtrudeKind.None && !Stands( kind );
public static float Reach( ArchCutPart cut ) => MathF.Max( LeastDepth, cut?.ExtrudeDepth ?? LeastDepth );
public static string Label( ArchExtrudeKind kind ) => kind switch {
ArchExtrudeKind.Face => "Face — one proud block over everything the zone covers",
ArchExtrudeKind.Quoins => "Quoins — alternately long and short blocks, the rusticated corner",
ArchExtrudeKind.Courses => "Courses — level bands across the whole width, parted by a recessed joint",
ArchExtrudeKind.Indent => "Indent — a recess bitten out of the elevation, on the outside face only",
ArchExtrudeKind.Pier => "Pier — a real dressed column engaged against the wall, climbing the zone's whole band",
_ => "None — the zone stands nothing"
};
public static string Glyph( ArchExtrudeKind kind ) => kind switch {
ArchExtrudeKind.Face => "crop_square",
ArchExtrudeKind.Quoins => "grid_view",
ArchExtrudeKind.Courses => "view_stream",
ArchExtrudeKind.Indent => "check_box_outline_blank",
ArchExtrudeKind.Pier => "view_column",
_ => "block"
};
}