public void Initialize(ILiftManager manager) { foreach (var floor in manager.Floors) { var controller = Instantiate(floorPrefab, root); controller.Floor = floor; var selection = controller.GetComponent <FloorSelection>(); if (selection == null) { continue; } selection.OnFloorFocusStateChanged += FloorFocusStateChanged; if (selection.Floor != manager.CurrentFloor) { continue; } _selected = selection; _selected.Selected = true; } OnFloorSelected?.Invoke(_selected != null ? _selected.Floor : manager.CurrentFloor); }
public override bool Check(FloorSelection floor, IReadOnlyList <BuildingSideInfo> neighbours, Vector2 edgeStart, Vector2 edgeEnd, float bottom, float top) { Contract.Requires(floor != null); Contract.Requires(neighbours != null); return(false); }
public override bool Check(FloorSelection floor, IReadOnlyList <BuildingSideInfo> sides, Vector2 edgeStart, Vector2 edgeEnd, float bottom, float top) { //Direction of the edge of the building var eDir = Vector2.Normalize(edgeEnd - edgeStart); foreach (var side in sides) { var sideLine = new Ray2(side.EdgeStart, side.EdgeEnd - side.EdgeStart); //Project out edgeStart/edgeEnd perpendicular and convert to distance along edge var iStart = new Ray2(edgeStart, eDir.Perpendicular()).Intersects(sideLine); var iEnd = new Ray2(edgeEnd, eDir.Perpendicular()).Intersects(sideLine); //No intersections means we have nothing to do with this neighbour if (!iStart.HasValue || !iEnd.HasValue) { continue; } //Extract start and end distances along side var st = Math.Min(iStart.Value.DistanceAlongB, iEnd.Value.DistanceAlongB); var et = Math.Max(iStart.Value.DistanceAlongB, iEnd.Value.DistanceAlongB); //We can select a subsection of the neighbour edge (distances along edge B) //Check if all of the neighbours along that subsection have the resource we're looking for foreach (var neighbour in side.Neighbours) { var ns = Math.Min(neighbour.Start, neighbour.End); var ne = Math.Max(neighbour.Start, neighbour.End); //Skip this subsection if it does not overlap our area of interest if (ns > et || ne < st) { continue; } //Try to find the resource we want bool resource = neighbour.Resources.Any(r => r.Bottom <= bottom && r.Top >= top && r.Type == Type); //If we did not find the resource, then this entire section does not have the resource (obviously) so we have failed if (!resource) { return(false); } } } //We worked through all applicable edges, and did not find the resource lacking along any of them: success! return(true); }
private void FloorFocusStateChanged(FloorSelection selection) { if (selection.Selected && _selected != selection) { _selected.Selected = false; _selected = selection; } if (selection.Focused) { _focused = selection; } else if (_focused == selection) { _focused = null; } OnFloorSelected?.Invoke(_focused != null ? _focused.Floor : _selected.Floor); }
/// <summary> /// Check if this constraint is not violated for a given facade /// </summary> /// <param name="floor">The floor we're checking</param> /// <param name="neighbours">Neighbour information around the base footprint of this building</param> /// <param name="edgeStart">The 2D start location of the wall we're applying a facade to</param> /// <param name="edgeEnd">The 2D end location of the wall we're applying a facade to</param> /// <param name="bottom">Altitude of the bottom of the wall we're applying this facade to</param> /// <param name="top">Altitude of the top of the wall we're applying this facade to</param> /// <returns></returns> public abstract bool Check(FloorSelection floor, IReadOnlyList <BuildingSideInfo> neighbours, Vector2 edgeStart, Vector2 edgeEnd, float bottom, float top);
private static bool Check(float distance, FloorSelection floor, IReadOnlyList <BuildingSideInfo> sides, Vector2 edgeStart, Vector2 edgeEnd) { Contract.Requires(floor != null); Contract.Requires(sides != null); //Direction of the edge of the building var eDir = Vector2.Normalize(edgeEnd - edgeStart); foreach (var side in sides) { //No point checking sides with no neighbours! if (!side.Neighbours.Any()) { continue; } var sideLine = new Ray2(side.EdgeStart, side.EdgeEnd - side.EdgeStart); //Project out edgeStart/edgeEnd perpendicular and convert to distance along edge var iStart = new Ray2(edgeStart, -eDir.Perpendicular()).Intersects(sideLine); var iEnd = new Ray2(edgeEnd, -eDir.Perpendicular()).Intersects(sideLine); //No intersections means we can't possibly be obscured by this neighbour if (!iStart.HasValue || !iEnd.HasValue) { continue; } //If the intersection is to the wrong side of this line, skip it if (iStart.Value.DistanceAlongA < 0 || iEnd.Value.DistanceAlongA < 0) { continue; } //Extract start and end distances along side var st = Math.Min(iStart.Value.DistanceAlongB, iEnd.Value.DistanceAlongB); var et = Math.Max(iStart.Value.DistanceAlongB, iEnd.Value.DistanceAlongB); //We can select a subsection of the neighbour edge (distances along edge B) //Check if any of the buildings along that subsection break the clearance constraint foreach (var neighbour in side.Neighbours) { //Skip this subsection if it is too low to have any impact on this floor if (neighbour.Height <= floor.CompoundHeight) { continue; } var ns = Math.Min(neighbour.Start, neighbour.End); var ne = Math.Max(neighbour.Start, neighbour.End); //Skip this subsection if it does not overlap our area of interest if (ns > et || ne < st) { continue; } //Distance from the start point of this neighbour, to the closest point on the edge of this facade section bool cont; var startClear = MeasureClearance(out cont, sideLine, sideLine.Position + sideLine.Direction * ns, new LineSegment2(edgeStart, edgeEnd), eDir); if (cont) { continue; } //Distance from the end point of this neighbour, to the closest point on the edge of this facade section var endClear = MeasureClearance(out cont, sideLine, sideLine.Position + sideLine.Direction * ne, new LineSegment2(edgeStart, edgeEnd), eDir); if (cont) { continue; } //Check clearance if (endClear < distance || startClear < distance) { return(false); } } } return(true); }
public override bool Check(FloorSelection floor, IReadOnlyList <BuildingSideInfo> neighbours, Vector2 edgeStart, Vector2 edgeEnd, float bottom, float top) { return(Check(Clearance, floor, neighbours, edgeStart, edgeEnd)); }