Editor/InteriorLayoutBuilder/RoomLayoutGeometryBuilder.Corners.cs
using System;
using System.Collections.Generic;
using System.Linq;
using Sandbox;
namespace ReusableRoomLayout;
public sealed partial class RoomLayoutGeometryBuilder
{
private static void BuildRoomCorners(
ICollection<RoomLayoutSolidSlab> solidSlabs,
RoomLayoutDocument document,
RoomLayoutRoom room )
{
var bounds = room.Bounds;
var settings = document.Settings;
var thickness = settings.WallThickness;
var baseboardInset = settings.BaseboardDepth * 0.5f - TrimEmbedForDepth( settings.BaseboardDepth );
BuildRoomCorner(
solidSlabs,
document,
room,
"NW",
RoomLayoutWallSide.North,
0.0f,
RoomLayoutWallSide.West,
bounds.Height,
new Vector2( bounds.X - thickness * 0.5f, bounds.Y + bounds.Height + thickness * 0.5f ),
new Vector2( bounds.X + baseboardInset, bounds.Y + bounds.Height - baseboardInset ) );
BuildRoomCorner(
solidSlabs,
document,
room,
"NE",
RoomLayoutWallSide.North,
bounds.Width,
RoomLayoutWallSide.East,
bounds.Height,
new Vector2( bounds.X + bounds.Width + thickness * 0.5f, bounds.Y + bounds.Height + thickness * 0.5f ),
new Vector2( bounds.X + bounds.Width - baseboardInset, bounds.Y + bounds.Height - baseboardInset ) );
BuildRoomCorner(
solidSlabs,
document,
room,
"SE",
RoomLayoutWallSide.South,
bounds.Width,
RoomLayoutWallSide.East,
0.0f,
new Vector2( bounds.X + bounds.Width + thickness * 0.5f, bounds.Y - thickness * 0.5f ),
new Vector2( bounds.X + bounds.Width - baseboardInset, bounds.Y + baseboardInset ) );
BuildRoomCorner(
solidSlabs,
document,
room,
"SW",
RoomLayoutWallSide.South,
0.0f,
RoomLayoutWallSide.West,
0.0f,
new Vector2( bounds.X - thickness * 0.5f, bounds.Y - thickness * 0.5f ),
new Vector2( bounds.X + baseboardInset, bounds.Y + baseboardInset ) );
}
private static void BuildRoomCorner(
ICollection<RoomLayoutSolidSlab> solidSlabs,
RoomLayoutDocument document,
RoomLayoutRoom room,
string suffix,
RoomLayoutWallSide firstSide,
float firstOffset,
RoomLayoutWallSide secondSide,
float secondOffset,
Vector2 center,
Vector2 baseboardCenter )
{
var settings = document.Settings;
var hasFirstWall = HasSolidWallAt( document, room, firstSide, firstOffset );
var hasSecondWall = HasSolidWallAt( document, room, secondSide, secondOffset );
if ( !hasFirstWall && !hasSecondWall )
{
return;
}
var footprint = new Vector3( settings.WallThickness, settings.WallThickness, settings.WallHeight );
var cap = new Vector3( settings.WallThickness, settings.WallThickness, settings.WallCapHeight );
var name = $"{RoomName( room )} Corner {suffix}";
var wallCenter = new Vector3( center.x, center.y, settings.WallHeight * 0.5f );
var capCenter = new Vector3( center.x, center.y, settings.WallHeight + settings.WallCapHeight * 0.5f );
var wallMaterialPath = RoomMaterialPath( settings, room, RoomLayoutSurface.Wall );
var innerWallMaterialPath = RoomInnerWallMaterialPath( settings, room );
var capMaterialPath = RoomMaterialPath( settings, room, RoomLayoutSurface.Cap );
var wallMaterialScale = RoomMaterialScale( settings, room, RoomLayoutSurface.Wall );
var innerWallMaterialScale = RoomInnerWallMaterialScale( settings, room );
var capMaterialScale = RoomMaterialScale( settings, room, RoomLayoutSurface.Cap );
var northMaterialPath = wallMaterialPath;
var southMaterialPath = wallMaterialPath;
var eastMaterialPath = wallMaterialPath;
var westMaterialPath = wallMaterialPath;
var northMaterialScale = wallMaterialScale;
var southMaterialScale = wallMaterialScale;
var eastMaterialScale = wallMaterialScale;
var westMaterialScale = wallMaterialScale;
var bounds = room.Bounds;
if ( center.x < bounds.X )
{
eastMaterialPath = innerWallMaterialPath;
eastMaterialScale = innerWallMaterialScale;
}
else if ( center.x > bounds.X + bounds.Width )
{
westMaterialPath = innerWallMaterialPath;
westMaterialScale = innerWallMaterialScale;
}
if ( center.y < bounds.Y )
{
northMaterialPath = innerWallMaterialPath;
northMaterialScale = innerWallMaterialScale;
}
else if ( center.y > bounds.Y + bounds.Height )
{
southMaterialPath = innerWallMaterialPath;
southMaterialScale = innerWallMaterialScale;
}
AddSolidSlab(
solidSlabs,
name,
wallCenter,
footprint,
RoomLayoutSurface.Wall,
materialPath: wallMaterialPath,
textureWorldSize: wallMaterialScale,
northMaterialPath: northMaterialPath,
southMaterialPath: southMaterialPath,
eastMaterialPath: eastMaterialPath,
westMaterialPath: westMaterialPath,
northTextureWorldSize: northMaterialScale,
southTextureWorldSize: southMaterialScale,
eastTextureWorldSize: eastMaterialScale,
westTextureWorldSize: westMaterialScale );
AddSolidSlab( solidSlabs, $"{name} Cap", capCenter, cap, RoomLayoutSurface.Cap, materialPath: capMaterialPath, textureWorldSize: capMaterialScale );
if ( hasFirstWall && hasSecondWall )
{
BuildBaseboardCorner(
solidSlabs,
settings,
$"{name} Baseboard",
baseboardCenter,
RoomMaterialPath( settings, room, RoomLayoutSurface.Baseboard ),
RoomMaterialScale( settings, room, RoomLayoutSurface.Baseboard ) );
}
}
private static void BuildBaseboardCorner(
ICollection<RoomLayoutSolidSlab> solidSlabs,
RoomLayoutSettings settings,
string name,
Vector2 center,
string materialPath,
float textureWorldSize )
{
if ( !settings.BaseboardsEnabled ||
settings.BaseboardHeight < 0.5f ||
settings.BaseboardDepth < 0.5f )
{
return;
}
AddSolidSlab(
solidSlabs,
name,
new Vector3( center.x, center.y, settings.BaseboardHeight * 0.5f ),
new Vector3( settings.BaseboardDepth, settings.BaseboardDepth, settings.BaseboardHeight ),
RoomLayoutSurface.Baseboard,
hasCollider: false,
materialPath: materialPath,
textureWorldSize: textureWorldSize );
}
private static bool HasSolidWallAt( RoomLayoutDocument document, RoomLayoutRoom room, RoomLayoutWallSide side, float offset )
{
var length = side is RoomLayoutWallSide.North or RoomLayoutWallSide.South
? room.Bounds.Width
: room.Bounds.Height;
var ownDoors = document.Doors
.Where( door => door.RoomId == room.Id && door.Side == side )
.ToArray();
var openings = WallOpeningsForSide( document, room, side, ownDoors );
var minimumWallRun = MinimumWallRunLength( document.Settings );
foreach ( var opening in openings )
{
var openStart = Math.Clamp( opening.Start, 0.0f, length );
var openEnd = Math.Clamp( opening.End, 0.0f, length );
SnapOpeningToWallEnds( length, minimumWallRun, ref openStart, ref openEnd );
if ( offset >= openStart - 0.5f && offset <= openEnd + 0.5f )
{
return false;
}
}
return true;
}
}