Editor/InteriorLayoutBuilder/RoomLayoutTool.Materials.cs
using System;
using System.Linq;
namespace ReusableRoomLayout;
public sealed partial class RoomLayoutTool
{
public float WallHeight => document.Settings.WallHeight;
public float DoorWidth => document.Settings.DoorWidth;
public float DoorHeight => document.Settings.DoorHeight;
public float DoorFrameThickness => document.Settings.DoorFrameThickness;
public float WindowWidth => document.Settings.WindowWidth;
public float WindowHeight => document.Settings.WindowHeight;
public float WindowSillHeight => document.Settings.WindowSillHeight;
public float WindowFrameThickness => document.Settings.WindowFrameThickness;
public float? SelectedDoorWidth => SelectedDoor()?.Width;
public float? SelectedDoorHeight => SelectedDoor()?.Height;
public float? SelectedWindowWidth => SelectedWindow()?.Width;
public float? SelectedWindowHeight => SelectedWindow()?.Height;
public float? SelectedWindowSillHeight => SelectedWindow()?.SillHeight;
public bool BaseboardsEnabled => document.Settings.BaseboardsEnabled;
public bool ThresholdsEnabled => document.Settings.ThresholdsEnabled;
public bool RoofEnabled => document.Settings.RoofEnabled;
public float BaseboardHeight => document.Settings.BaseboardHeight;
public float BaseboardDepth => document.Settings.BaseboardDepth;
public float ThresholdDepth => document.Settings.ThresholdDepth;
public float RoofThickness => document.Settings.RoofThickness;
public float TextureWorldSize => document.Settings.TextureWorldSize;
public bool HasSelectedLayout =>
document.FindDoor( selectedDoorId ) is not null ||
document.FindWindow( selectedWindowId ) is not null ||
SelectedCorridor() is not null ||
SelectedFloorCutout() is not null ||
document.FindRoom( selectedRoomId ) is not null;
public bool HasSelectedRoom => selectedDoorId == 0 && selectedWindowId == 0 && document.FindRoom( selectedRoomId ) is not null;
public bool HasSelectedDoor => SelectedDoor() is not null;
public bool HasSelectedWindow => SelectedWindow() is not null;
public bool HasSelectedCorridor => SelectedCorridor() is not null;
public bool HasRooms => document.Rooms.Count > 0;
public string SelectedRoomName => document.FindRoom( selectedRoomId ) is { } room
? $"{FloorLabel( document.FloorFor( room ) )}: {(string.IsNullOrWhiteSpace( room.Name ) ? $"Room {room.Id}" : room.Name)}"
: "No room selected";
public string SelectedCorridorName => SelectedCorridor() is { } corridor ? $"{FloorLabel( document.FloorFor( corridor ) )}: Corridor {corridor.Id}" : "No corridor selected";
public string SelectedLayoutName => document.FindDoor( selectedDoorId ) is { } door
? $"{FloorLabel( document.FloorFor( door ) )}: Door {door.Id}"
: document.FindWindow( selectedWindowId ) is { } window
? $"{FloorLabel( document.FloorFor( window ) )}: Window {window.Id}"
: SelectedCorridor() is { } corridor
? $"{FloorLabel( document.FloorFor( corridor ) )}: Corridor {corridor.Id}"
: SelectedFloorCutout() is { } cutout
? $"{FloorLabel( document.FloorFor( cutout ) )}: {(string.IsNullOrWhiteSpace( cutout.Name ) ? $"Floor Cutout {cutout.Id}" : cutout.Name)}"
: document.FindRoom( selectedRoomId ) is { } room
? $"{FloorLabel( document.FloorFor( room ) )}: {(string.IsNullOrWhiteSpace( room.Name ) ? $"Room {room.Id}" : room.Name)}"
: "None";
private RoomLayoutWindow SelectedWindow()
{
return document.FindWindow( selectedWindowId );
}
private RoomLayoutDoor SelectedDoor()
{
return document.FindDoor( selectedDoorId );
}
public bool CanSetSelectedMaterialSlot( RoomLayoutMaterialSlot slot )
{
return slot switch
{
RoomLayoutMaterialSlot.DoorFrame => SelectedDoor() is not null,
RoomLayoutMaterialSlot.WindowFrame => HasSelectedWindow,
RoomLayoutMaterialSlot.Floor or
RoomLayoutMaterialSlot.Wall or
RoomLayoutMaterialSlot.OuterWall or
RoomLayoutMaterialSlot.InnerWall or
RoomLayoutMaterialSlot.WallCap or
RoomLayoutMaterialSlot.Baseboard or
RoomLayoutMaterialSlot.Threshold or
RoomLayoutMaterialSlot.Roof => HasSelectedRoom || HasSelectedCorridor,
_ => false
};
}
public string GetMaterialPath( RoomLayoutMaterialSlot slot )
{
var settings = document.Settings;
return slot switch
{
RoomLayoutMaterialSlot.Floor => settings.FloorMaterialPath,
RoomLayoutMaterialSlot.Wall => settings.WallMaterialPath,
RoomLayoutMaterialSlot.OuterWall => FirstMaterialPath( settings.OuterWallMaterialPath, settings.WallMaterialPath ),
RoomLayoutMaterialSlot.InnerWall => FirstMaterialPath( settings.InnerWallMaterialPath, settings.WallMaterialPath ),
RoomLayoutMaterialSlot.WallCap => settings.WallCapMaterialPath,
RoomLayoutMaterialSlot.Baseboard => settings.BaseboardMaterialPath,
RoomLayoutMaterialSlot.DoorFrame => settings.DoorFrameMaterialPath,
RoomLayoutMaterialSlot.WindowFrame => settings.WindowFrameMaterialPath,
RoomLayoutMaterialSlot.CorridorFloor => settings.CorridorFloorMaterialPath,
RoomLayoutMaterialSlot.Threshold => settings.ThresholdMaterialPath,
RoomLayoutMaterialSlot.Roof => settings.RoofMaterialPath,
_ => ""
};
}
public string GetSelectedMaterialPath( RoomLayoutMaterialSlot slot )
{
if ( SelectedDoor() is { } door )
{
return slot == RoomLayoutMaterialSlot.DoorFrame
? door.DoorFrameMaterialPath
: "";
}
if ( SelectedWindow() is { } window )
{
return slot == RoomLayoutMaterialSlot.WindowFrame
? window.WindowFrameMaterialPath
: "";
}
if ( HasSelectedRoom && document.FindRoom( selectedRoomId ) is { } room )
{
return slot switch
{
RoomLayoutMaterialSlot.Floor => room.FloorMaterialPath,
RoomLayoutMaterialSlot.Wall => room.WallMaterialPath,
RoomLayoutMaterialSlot.OuterWall => FirstMaterialPath( room.OuterWallMaterialPath, room.WallMaterialPath ),
RoomLayoutMaterialSlot.InnerWall => room.InnerWallMaterialPath,
RoomLayoutMaterialSlot.WallCap => room.WallCapMaterialPath,
RoomLayoutMaterialSlot.Baseboard => room.BaseboardMaterialPath,
RoomLayoutMaterialSlot.Threshold => room.ThresholdMaterialPath,
RoomLayoutMaterialSlot.Roof => room.RoofMaterialPath,
_ => ""
};
}
if ( SelectedCorridor() is { } corridor )
{
return slot switch
{
RoomLayoutMaterialSlot.Floor => corridor.FloorMaterialPath,
RoomLayoutMaterialSlot.Wall => corridor.WallMaterialPath,
RoomLayoutMaterialSlot.OuterWall => FirstMaterialPath( corridor.OuterWallMaterialPath, corridor.WallMaterialPath ),
RoomLayoutMaterialSlot.InnerWall => corridor.InnerWallMaterialPath,
RoomLayoutMaterialSlot.WallCap => corridor.WallCapMaterialPath,
RoomLayoutMaterialSlot.Baseboard => corridor.BaseboardMaterialPath,
RoomLayoutMaterialSlot.Threshold => corridor.ThresholdMaterialPath,
RoomLayoutMaterialSlot.Roof => corridor.RoofMaterialPath,
_ => ""
};
}
return "";
}
public float GetMaterialScale( RoomLayoutMaterialSlot slot )
{
var settings = document.Settings;
return slot switch
{
RoomLayoutMaterialSlot.Floor => MaterialScaleOrFallback( settings.FloorMaterialScale, settings.TextureWorldSize ),
RoomLayoutMaterialSlot.Wall => MaterialScaleOrFallback( settings.WallMaterialScale, settings.TextureWorldSize ),
RoomLayoutMaterialSlot.OuterWall => MaterialScaleOrFallback( settings.OuterWallMaterialScale, MaterialScaleOrFallback( settings.WallMaterialScale, settings.TextureWorldSize ) ),
RoomLayoutMaterialSlot.InnerWall => MaterialScaleOrFallback( settings.InnerWallMaterialScale, MaterialScaleOrFallback( settings.WallMaterialScale, settings.TextureWorldSize ) ),
RoomLayoutMaterialSlot.WallCap => MaterialScaleOrFallback( settings.WallCapMaterialScale, settings.TextureWorldSize ),
RoomLayoutMaterialSlot.Baseboard => MaterialScaleOrFallback( settings.BaseboardMaterialScale, settings.TextureWorldSize ),
RoomLayoutMaterialSlot.DoorFrame => MaterialScaleOrFallback( settings.DoorFrameMaterialScale, settings.TextureWorldSize ),
RoomLayoutMaterialSlot.WindowFrame => MaterialScaleOrFallback( settings.WindowFrameMaterialScale, settings.TextureWorldSize ),
RoomLayoutMaterialSlot.CorridorFloor => MaterialScaleOrFallback( settings.CorridorFloorMaterialScale, settings.TextureWorldSize ),
RoomLayoutMaterialSlot.Threshold => MaterialScaleOrFallback( settings.ThresholdMaterialScale, settings.TextureWorldSize ),
RoomLayoutMaterialSlot.Roof => MaterialScaleOrFallback( settings.RoofMaterialScale, settings.TextureWorldSize ),
_ => MaterialScaleOrFallback( 0.0f, settings.TextureWorldSize )
};
}
public float GetSelectedMaterialScale( RoomLayoutMaterialSlot slot )
{
if ( SelectedDoor() is { } door )
{
return slot == RoomLayoutMaterialSlot.DoorFrame
? door.DoorFrameMaterialScale
: 0.0f;
}
if ( SelectedWindow() is { } window )
{
return slot == RoomLayoutMaterialSlot.WindowFrame
? window.WindowFrameMaterialScale
: 0.0f;
}
if ( HasSelectedRoom && document.FindRoom( selectedRoomId ) is { } room )
{
return slot switch
{
RoomLayoutMaterialSlot.Floor => room.FloorMaterialScale,
RoomLayoutMaterialSlot.Wall => room.WallMaterialScale,
RoomLayoutMaterialSlot.OuterWall => FirstMaterialScale( room.OuterWallMaterialScale, room.WallMaterialScale ),
RoomLayoutMaterialSlot.InnerWall => room.InnerWallMaterialScale,
RoomLayoutMaterialSlot.WallCap => room.WallCapMaterialScale,
RoomLayoutMaterialSlot.Baseboard => room.BaseboardMaterialScale,
RoomLayoutMaterialSlot.Threshold => room.ThresholdMaterialScale,
RoomLayoutMaterialSlot.Roof => room.RoofMaterialScale,
_ => 0.0f
};
}
if ( SelectedCorridor() is { } corridor )
{
return slot switch
{
RoomLayoutMaterialSlot.Floor => corridor.FloorMaterialScale,
RoomLayoutMaterialSlot.Wall => corridor.WallMaterialScale,
RoomLayoutMaterialSlot.OuterWall => FirstMaterialScale( corridor.OuterWallMaterialScale, corridor.WallMaterialScale ),
RoomLayoutMaterialSlot.InnerWall => corridor.InnerWallMaterialScale,
RoomLayoutMaterialSlot.WallCap => corridor.WallCapMaterialScale,
RoomLayoutMaterialSlot.Baseboard => corridor.BaseboardMaterialScale,
RoomLayoutMaterialSlot.Threshold => corridor.ThresholdMaterialScale,
RoomLayoutMaterialSlot.Roof => corridor.RoofMaterialScale,
_ => 0.0f
};
}
return 0.0f;
}
public float GetEffectiveSelectedMaterialScale( RoomLayoutMaterialSlot slot )
{
var selectedScale = GetSelectedMaterialScale( slot );
if ( selectedScale > 0.0f )
{
return selectedScale;
}
if ( SelectedCorridor() is not null && slot == RoomLayoutMaterialSlot.Floor )
{
return GetMaterialScale( RoomLayoutMaterialSlot.CorridorFloor );
}
return GetMaterialScale( slot );
}
public void SetMaterialPath( RoomLayoutMaterialSlot slot, string path )
{
EnsureLayoutLoadedForControls();
path = NormalizeMaterialPath( path );
if ( string.Equals( GetMaterialPath( slot ), path, StringComparison.OrdinalIgnoreCase ) )
{
return;
}
PushLayoutUndo();
var settings = document.Settings;
switch ( slot )
{
case RoomLayoutMaterialSlot.Floor:
settings.FloorMaterialPath = path;
break;
case RoomLayoutMaterialSlot.Wall:
settings.WallMaterialPath = path;
break;
case RoomLayoutMaterialSlot.OuterWall:
settings.OuterWallMaterialPath = path;
break;
case RoomLayoutMaterialSlot.InnerWall:
settings.InnerWallMaterialPath = path;
break;
case RoomLayoutMaterialSlot.WallCap:
settings.WallCapMaterialPath = path;
break;
case RoomLayoutMaterialSlot.Baseboard:
settings.BaseboardMaterialPath = path;
break;
case RoomLayoutMaterialSlot.DoorFrame:
settings.DoorFrameMaterialPath = path;
break;
case RoomLayoutMaterialSlot.WindowFrame:
settings.WindowFrameMaterialPath = path;
break;
case RoomLayoutMaterialSlot.CorridorFloor:
settings.CorridorFloorMaterialPath = path;
break;
case RoomLayoutMaterialSlot.Threshold:
settings.ThresholdMaterialPath = path;
break;
case RoomLayoutMaterialSlot.Roof:
settings.RoofMaterialPath = path;
break;
}
CommitLayoutChange();
}
public void SetMaterialScale( RoomLayoutMaterialSlot slot, float scale )
{
EnsureLayoutLoadedForControls();
scale = NormalizeMaterialScale( scale, allowInherit: true );
if ( Math.Abs( GetMaterialScaleOverride( slot ) - scale ) < 0.001f )
{
return;
}
PushLayoutUndo();
var settings = document.Settings;
switch ( slot )
{
case RoomLayoutMaterialSlot.Floor:
settings.FloorMaterialScale = scale;
break;
case RoomLayoutMaterialSlot.Wall:
settings.WallMaterialScale = scale;
break;
case RoomLayoutMaterialSlot.OuterWall:
settings.OuterWallMaterialScale = scale;
break;
case RoomLayoutMaterialSlot.InnerWall:
settings.InnerWallMaterialScale = scale;
break;
case RoomLayoutMaterialSlot.WallCap:
settings.WallCapMaterialScale = scale;
break;
case RoomLayoutMaterialSlot.Baseboard:
settings.BaseboardMaterialScale = scale;
break;
case RoomLayoutMaterialSlot.DoorFrame:
settings.DoorFrameMaterialScale = scale;
break;
case RoomLayoutMaterialSlot.WindowFrame:
settings.WindowFrameMaterialScale = scale;
break;
case RoomLayoutMaterialSlot.CorridorFloor:
settings.CorridorFloorMaterialScale = scale;
break;
case RoomLayoutMaterialSlot.Threshold:
settings.ThresholdMaterialScale = scale;
break;
case RoomLayoutMaterialSlot.Roof:
settings.RoofMaterialScale = scale;
break;
}
CommitLayoutChange();
}
public void SetSelectedMaterialPath( RoomLayoutMaterialSlot slot, string path )
{
EnsureLayoutLoadedForControls();
if ( !CanSetSelectedMaterialSlot( slot ) )
{
return;
}
path = NormalizeMaterialPath( path );
if ( string.Equals( GetSelectedMaterialPath( slot ), path, StringComparison.OrdinalIgnoreCase ) )
{
return;
}
if ( SelectedDoor() is { } door )
{
PushLayoutUndo();
door.DoorFrameMaterialPath = path;
CommitLayoutChange();
return;
}
if ( SelectedWindow() is { } window )
{
PushLayoutUndo();
window.WindowFrameMaterialPath = path;
CommitLayoutChange();
return;
}
if ( HasSelectedRoom && document.FindRoom( selectedRoomId ) is { } room )
{
PushLayoutUndo();
switch ( slot )
{
case RoomLayoutMaterialSlot.Floor:
room.FloorMaterialPath = path;
break;
case RoomLayoutMaterialSlot.Wall:
room.WallMaterialPath = path;
break;
case RoomLayoutMaterialSlot.OuterWall:
room.OuterWallMaterialPath = path;
room.WallMaterialPath = "";
break;
case RoomLayoutMaterialSlot.InnerWall:
room.InnerWallMaterialPath = path;
break;
case RoomLayoutMaterialSlot.WallCap:
room.WallCapMaterialPath = path;
break;
case RoomLayoutMaterialSlot.Baseboard:
room.BaseboardMaterialPath = path;
break;
case RoomLayoutMaterialSlot.Threshold:
room.ThresholdMaterialPath = path;
break;
case RoomLayoutMaterialSlot.Roof:
room.RoofMaterialPath = path;
break;
}
CommitLayoutChange();
return;
}
if ( SelectedCorridor() is not { } corridor )
{
return;
}
PushLayoutUndo();
switch ( slot )
{
case RoomLayoutMaterialSlot.Floor:
corridor.FloorMaterialPath = path;
break;
case RoomLayoutMaterialSlot.Wall:
corridor.WallMaterialPath = path;
break;
case RoomLayoutMaterialSlot.OuterWall:
corridor.OuterWallMaterialPath = path;
corridor.WallMaterialPath = "";
break;
case RoomLayoutMaterialSlot.InnerWall:
corridor.InnerWallMaterialPath = path;
break;
case RoomLayoutMaterialSlot.WallCap:
corridor.WallCapMaterialPath = path;
break;
case RoomLayoutMaterialSlot.Baseboard:
corridor.BaseboardMaterialPath = path;
break;
case RoomLayoutMaterialSlot.Threshold:
corridor.ThresholdMaterialPath = path;
break;
case RoomLayoutMaterialSlot.Roof:
corridor.RoofMaterialPath = path;
break;
}
CommitLayoutChange();
}
public void SetSelectedMaterialScale( RoomLayoutMaterialSlot slot, float scale )
{
EnsureLayoutLoadedForControls();
if ( !CanSetSelectedMaterialSlot( slot ) )
{
return;
}
scale = NormalizeMaterialScale( scale, allowInherit: true );
if ( Math.Abs( GetSelectedMaterialScale( slot ) - scale ) < 0.001f )
{
return;
}
if ( SelectedDoor() is { } door )
{
PushLayoutUndo();
door.DoorFrameMaterialScale = scale;
CommitLayoutChange();
return;
}
if ( SelectedWindow() is { } window )
{
PushLayoutUndo();
window.WindowFrameMaterialScale = scale;
CommitLayoutChange();
return;
}
if ( HasSelectedRoom && document.FindRoom( selectedRoomId ) is { } room )
{
PushLayoutUndo();
switch ( slot )
{
case RoomLayoutMaterialSlot.Floor:
room.FloorMaterialScale = scale;
break;
case RoomLayoutMaterialSlot.Wall:
room.WallMaterialScale = scale;
break;
case RoomLayoutMaterialSlot.OuterWall:
room.OuterWallMaterialScale = scale;
room.WallMaterialScale = 0.0f;
break;
case RoomLayoutMaterialSlot.InnerWall:
room.InnerWallMaterialScale = scale;
break;
case RoomLayoutMaterialSlot.WallCap:
room.WallCapMaterialScale = scale;
break;
case RoomLayoutMaterialSlot.Baseboard:
room.BaseboardMaterialScale = scale;
break;
case RoomLayoutMaterialSlot.Threshold:
room.ThresholdMaterialScale = scale;
break;
case RoomLayoutMaterialSlot.Roof:
room.RoofMaterialScale = scale;
break;
}
CommitLayoutChange();
return;
}
if ( SelectedCorridor() is not { } corridor )
{
return;
}
PushLayoutUndo();
switch ( slot )
{
case RoomLayoutMaterialSlot.Floor:
corridor.FloorMaterialScale = scale;
break;
case RoomLayoutMaterialSlot.Wall:
corridor.WallMaterialScale = scale;
break;
case RoomLayoutMaterialSlot.OuterWall:
corridor.OuterWallMaterialScale = scale;
corridor.WallMaterialScale = 0.0f;
break;
case RoomLayoutMaterialSlot.InnerWall:
corridor.InnerWallMaterialScale = scale;
break;
case RoomLayoutMaterialSlot.WallCap:
corridor.WallCapMaterialScale = scale;
break;
case RoomLayoutMaterialSlot.Baseboard:
corridor.BaseboardMaterialScale = scale;
break;
case RoomLayoutMaterialSlot.Threshold:
corridor.ThresholdMaterialScale = scale;
break;
case RoomLayoutMaterialSlot.Roof:
corridor.RoofMaterialScale = scale;
break;
}
CommitLayoutChange();
}
public void SetTextureWorldSize( float size )
{
EnsureLayoutLoadedForControls();
size = Math.Clamp( size, 1.0f, 8192.0f );
if ( Math.Abs( document.Settings.TextureWorldSize - size ) < 0.001f )
{
return;
}
PushLayoutUndo();
document.Settings.TextureWorldSize = size;
CommitLayoutChange();
}
public void SetWallHeight( float height )
{
EnsureLayoutLoadedForControls();
height = Math.Clamp( height, 8.0f, 4096.0f );
if ( Math.Abs( document.Settings.WallHeight - height ) < 0.001f )
{
return;
}
PushLayoutUndo();
document.Settings.WallHeight = height;
CommitLayoutChange();
}
public void SetWindowWidth( float width )
{
SetFloatSetting( width, 1.0f, 4096.0f, () => document.Settings.WindowWidth, value => document.Settings.WindowWidth = value );
}
private float WindowWallLength( RoomLayoutWindow window )
{
if ( window.CorridorId != 0 )
{
var corridor = document.Corridors.FirstOrDefault( candidate => candidate.Id == window.CorridorId );
if ( corridor is not null &&
TryGetCorridorPath( corridor, out var points ) &&
window.CorridorSegmentIndex >= 0 &&
window.CorridorSegmentIndex < points.Count - 1 )
{
var a = points[window.CorridorSegmentIndex];
var b = points[window.CorridorSegmentIndex + 1];
return MathF.Abs( b.x - a.x ) >= MathF.Abs( b.y - a.y )
? MathF.Abs( b.x - a.x )
: MathF.Abs( b.y - a.y );
}
return 4096.0f;
}
var room = document.FindRoom( window.RoomId );
if ( room is null )
{
return 4096.0f;
}
return window.Side is RoomLayoutWallSide.North or RoomLayoutWallSide.South
? room.Bounds.Width
: room.Bounds.Height;
}
public void SetWindowHeight( float height )
{
SetFloatSetting( height, 1.0f, 4096.0f, () => document.Settings.WindowHeight, value => document.Settings.WindowHeight = value );
}
public void SetWindowSillHeight( float height )
{
SetFloatSetting( height, 0.0f, 4096.0f, () => document.Settings.WindowSillHeight, value => document.Settings.WindowSillHeight = value );
}
public void SetWindowFrameThickness( float thickness )
{
SetFloatSetting( thickness, 0.1f, 512.0f, () => document.Settings.WindowFrameThickness, value => document.Settings.WindowFrameThickness = value );
}
public void SetDoorWidth( float width )
{
SetFloatSetting( width, 1.0f, 4096.0f, () => document.Settings.DoorWidth, value => document.Settings.DoorWidth = value );
}
public void SetDoorHeight( float height )
{
SetFloatSetting( height, 1.0f, 4096.0f, () => document.Settings.DoorHeight, value => document.Settings.DoorHeight = value );
}
public void SetDoorFrameThickness( float thickness )
{
SetFloatSetting( thickness, 0.1f, 512.0f, () => document.Settings.DoorFrameThickness, value => document.Settings.DoorFrameThickness = value );
}
public void SetBaseboardsEnabled( bool enabled )
{
EnsureLayoutLoadedForControls();
if ( document.Settings.BaseboardsEnabled == enabled )
{
return;
}
PushLayoutUndo();
document.Settings.BaseboardsEnabled = enabled;
CommitLayoutChange();
}
public void SetThresholdsEnabled( bool enabled )
{
EnsureLayoutLoadedForControls();
if ( document.Settings.ThresholdsEnabled == enabled )
{
return;
}
PushLayoutUndo();
document.Settings.ThresholdsEnabled = enabled;
CommitLayoutChange();
}
public void SetRoofEnabled( bool enabled )
{
EnsureLayoutLoadedForControls();
if ( document.Settings.RoofEnabled == enabled )
{
return;
}
PushLayoutUndo();
document.Settings.RoofEnabled = enabled;
CommitLayoutChange();
}
public void SetBaseboardHeight( float height )
{
SetFloatSetting( height, 0.5f, 512.0f, () => document.Settings.BaseboardHeight, value => document.Settings.BaseboardHeight = value );
}
public void SetBaseboardDepth( float depth )
{
SetFloatSetting( depth, 0.5f, 512.0f, () => document.Settings.BaseboardDepth, value => document.Settings.BaseboardDepth = value );
}
public void SetThresholdDepth( float depth )
{
SetFloatSetting( depth, 0.5f, 512.0f, () => document.Settings.ThresholdDepth, value => document.Settings.ThresholdDepth = value );
}
public void SetRoofThickness( float thickness )
{
SetFloatSetting( thickness, 0.5f, 512.0f, () => document.Settings.RoofThickness, value => document.Settings.RoofThickness = value );
}
private void SetFloatSetting( float value, float min, float max, Func<float> getter, Action<float> setter )
{
EnsureLayoutLoadedForControls();
value = Math.Clamp( value, min, max );
if ( Math.Abs( getter() - value ) < 0.001f )
{
return;
}
PushLayoutUndo();
setter( value );
CommitLayoutChange();
}
private static string NormalizeMaterialPath( string path )
{
if ( string.IsNullOrWhiteSpace( path ) )
{
return "";
}
path = path.Trim().Replace( '\\', '/' ).TrimStart( '/' );
if ( path.StartsWith( "assets/", StringComparison.OrdinalIgnoreCase ) )
{
path = path[7..];
}
return path.EndsWith( ".vmat_c", StringComparison.OrdinalIgnoreCase )
? path[..^2]
: path;
}
private static string FirstMaterialPath( string preferred, string fallback )
{
return string.IsNullOrWhiteSpace( preferred )
? fallback ?? ""
: preferred;
}
private float GetMaterialScaleOverride( RoomLayoutMaterialSlot slot )
{
var settings = document.Settings;
return slot switch
{
RoomLayoutMaterialSlot.Floor => settings.FloorMaterialScale,
RoomLayoutMaterialSlot.Wall => settings.WallMaterialScale,
RoomLayoutMaterialSlot.OuterWall => settings.OuterWallMaterialScale,
RoomLayoutMaterialSlot.InnerWall => settings.InnerWallMaterialScale,
RoomLayoutMaterialSlot.WallCap => settings.WallCapMaterialScale,
RoomLayoutMaterialSlot.Baseboard => settings.BaseboardMaterialScale,
RoomLayoutMaterialSlot.DoorFrame => settings.DoorFrameMaterialScale,
RoomLayoutMaterialSlot.WindowFrame => settings.WindowFrameMaterialScale,
RoomLayoutMaterialSlot.CorridorFloor => settings.CorridorFloorMaterialScale,
RoomLayoutMaterialSlot.Threshold => settings.ThresholdMaterialScale,
RoomLayoutMaterialSlot.Roof => settings.RoofMaterialScale,
_ => 0.0f
};
}
private static float FirstMaterialScale( float preferred, float fallback )
{
return preferred > 0.0f ? preferred : MathF.Max( 0.0f, fallback );
}
private static float NormalizeMaterialScale( float scale, bool allowInherit = false )
{
if ( allowInherit && scale <= 0.0f )
{
return 0.0f;
}
return Math.Clamp( scale, 1.0f, 8192.0f );
}
private static float MaterialScaleOrFallback( float scale, float fallback )
{
return Math.Clamp( scale > 0.0f ? scale : fallback, 1.0f, 8192.0f );
}
}
public enum RoomLayoutMaterialSlot
{
Floor,
Wall,
OuterWall,
InnerWall,
WallCap,
Baseboard,
DoorFrame,
WindowFrame,
CorridorFloor,
Threshold,
Roof
}