handle modules larger than 1x1, widen door size to allow walking around it

This commit is contained in:
2022-11-24 19:32:51 +01:00
parent 74fd757d20
commit 2eec53fe87
11 changed files with 649 additions and 43 deletions

View File

@@ -1,47 +1,122 @@
using System.Collections.Generic;
using System.Linq;
using System;
using System.Collections.Generic;
using UnityEngine;
using Range = EscapeRoomEngine.Engine.Runtime.Utilities.Range;
namespace EscapeRoomEngine.Engine.Runtime
{
public struct Placement
{
/// <summary>
/// The placement position is always considered to be at <c>(0.5, 0.5)</c> relative to the placement.
///
/// <example>In a placement of size <c>(1, 1)</c>, the position is at the center of the placement. In a larger placement, the position is in the center of the bottom left square meter.</example>
/// </summary>
public Vector3Int position;
public Vector2Int size;
public Orientation orientation;
/// <summary>
/// Create a set with every possible combination of position and orientation given the dimensions.
///
/// <remarks>
/// The size of all placements will be (1, 1).
/// </remarks>
/// </summary>
public List<Placement> EveryPlacement
{
public Vector3Int BottomLeft {
get
{
var placements = new List<Placement>();
for (var zIter = 0; zIter < size.y; zIter++)
var sizeMinusOne = size - Vector2Int.one;
return orientation switch
{
for (var xIter = 0; xIter < size.x; xIter++)
{
placements.AddRange(OrientationExtensions.EveryOrientation().Select(o => new Placement
{
position = new Vector3Int(xIter, 0, zIter),
size = Vector2Int.one,
orientation = o
}));
}
}
Orientation.North => position,
Orientation.East => position - new Vector3Int(0, 0, sizeMinusOne.x),
Orientation.South => position - new Vector3Int(sizeMinusOne.x, 0, sizeMinusOne.y),
Orientation.West => position - new Vector3Int(sizeMinusOne.y, 0, 0),
_ => throw new ArgumentOutOfRangeException()
};
}
}
/// <summary>
/// Create a set with every possible combination of position and orientation of placements that fit in a given space.
/// The size of the placements are given by this placement.
/// </summary>
/// <param name="space">The generated placements will fit inside the placement of the given space.</param>
public List<Placement> EveryPlacementInSpace(Space space)
{
var placements = new List<Placement>();
var sizeMinusOne = size - Vector2Int.one;
var spaceSize = space.rrPlacement.size;
return placements;
foreach (var o in OrientationExtensions.EveryOrientation())
{
Range x;
Range z;
switch (o)
{
case Orientation.North:
x = new Range(0, spaceSize.x - sizeMinusOne.x);
z = new Range(0, spaceSize.y - sizeMinusOne.y);
break;
case Orientation.East:
x = new Range(0, spaceSize.x - sizeMinusOne.y);
z = new Range(sizeMinusOne.x, spaceSize.y);
break;
case Orientation.South:
x = new Range(sizeMinusOne.x, spaceSize.x);
z = new Range(sizeMinusOne.y, spaceSize.y);
break;
case Orientation.West:
x = new Range(sizeMinusOne.y, spaceSize.x);
z = new Range(0, spaceSize.y - sizeMinusOne.x);
break;
default:
throw new ArgumentOutOfRangeException();
}
placements.AddRange(ConstrainedPlacements(o, size, x, z));
}
return placements;
}
private static IEnumerable<Placement> ConstrainedPlacements(
Orientation orientation,
Vector2Int size,
Range xRange, Range zRange)
{
var placements = new List<Placement>(xRange.Length * zRange.Length);
for (var z = zRange.min; z < zRange.max; z++)
{
for (var x = xRange.min; x < xRange.max; x++)
{
placements.Add(new Placement
{
position = new Vector3Int(x, 0, z),
size = size,
orientation = orientation
});
}
}
return placements;
}
/// <summary>
/// Performs the specified action for each position inside the size of this placement.
///
/// <example>For the placement {(2, 0, 3), (1, 2), East} the action would be called twice with the parameters (2, 0, 3) and (3, 0, 3).</example>
/// </summary>
public void ForEachPosition(Action<Vector3Int> action)
{
var bottomLeft = BottomLeft;
for (var z = 0; z < (orientation is Orientation.North or Orientation.South ? size.y : size.x); z++)
{
for (var x = 0; x < (orientation is Orientation.North or Orientation.South ? size.x : size.y); x++)
{
action(bottomLeft + new Vector3Int(x, 0, z));
}
}
}
public string PositionAndOrientation() => $"{{({position.x}, {position.z}), {orientation}}}";
public string ToStringShort() => $"{{{position}, {orientation}}}";
public override string ToString() => $"{{{position}, {size}, {orientation}}}";
}
}