/// <summary> /// Create a wall section as a subsection along the given external facade section /// </summary> /// <param name="roomPlan"></param> /// <param name="facade"></param> /// <param name="externalSection"></param> /// <returns></returns> // ReSharper disable once VirtualMemberNeverOverriden.Global (Justification: External API) protected virtual IConfigurableFacade CreateExternalWall(IRoomPlan roomPlan, Facade facade, IConfigurableFacade externalSection) { Contract.Requires(roomPlan != null); Contract.Requires(facade != null); Contract.Requires(externalSection != null); //Make sure the room subdivides before the facade (and thus has a chance to configure it externalSection.GetDependencyContext().AddPrerequisite(roomPlan.Node); //Calculate X position of subsection (map room section onto full wall section) var at = externalSection.Section.InternalLineSegment.LongLine.ClosestPointDistanceAlongLine(facade.Section.ExternalLineSegment.Start); var bt = externalSection.Section.InternalLineSegment.LongLine.ClosestPointDistanceAlongLine(facade.Section.ExternalLineSegment.End); //Transform distance along facade into facade local coordinates var minAlong = Math.Min(at, bt) * externalSection.Section.Width - externalSection.Section.Width * 0.5f; var maxAlong = Math.Max(at, bt) * externalSection.Section.Width - externalSection.Section.Width * 0.5f; return(new SubsectionFacade( externalSection, new Vector2(minAlong, -Bounds.Height / 2 + _floorThickness), new Vector2(maxAlong, -Bounds.Height / 2 + _floorThickness + _roomHeight), 0, 1, facade.Section )); }
public static IEnumerable <LineSegment2> Edges(this IRoomPlan room) { Contract.Requires(room != null); Contract.Ensures(Contract.Result <IEnumerable <LineSegment2> >() != null); return(Edges(room.OuterFootprint)); }
public static LineSegment2 GetEdge(this IRoomPlan room, uint index) { Contract.Requires(room != null); var idx = ((int)index) % room.OuterFootprint.Count; return(new LineSegment2(room.OuterFootprint[idx], room.OuterFootprint[(idx + 1) % room.OuterFootprint.Count])); }
public IRoomPlan Other(IRoomPlan room) { if (RoomAB == room) { return(RoomCD); } else { return(RoomAB); } }
public static bool PassesAllFilters(IRoomPlan plan, List <BaseRoomFilter> filters) { foreach (BaseRoomFilter filter in filters) { if (!filter.PassesFilter(plan)) { return(false); } } return(true); }
public override bool PassesFilter(IRoomPlan plan) { ConnectivityRoom.Connectivity testConnection = ConnectivityRoom.Connectivity.None; ConnectivityRoom component; if (plan.Components.TryGet <ConnectivityRoom>(out component)) { testConnection = component.Connection; } return((testConnection & Connection) != ConnectivityRoom.Connectivity.None); }
public override bool PassesFilter(IRoomPlan plan) { foreach (RoomComponent component in this.Components) { if (plan.Components.Contains(component.GetType()) == this.Negate) { return(false); } } return(true); }
public LineSegment2 Segment(IRoomPlan room) { if (RoomAB == room) { return(new LineSegment2(A, B)); } else if (RoomCD == room) { return(new LineSegment2(C, D)); } throw new ArgumentException("Must supply either RoomAB or RoomCD", "room"); }
public IEnumerable <Neighbour> this[IRoomPlan key] { get { Contract.Requires(key != null); Contract.Ensures(Contract.Result <IEnumerable <Neighbour> >() != null); GenerateNeighbours(); List <Neighbour> value; if (!_neighbours.TryGetValue(key, out value) || value == null) { throw new InvalidOperationException("Failed to find neighbour information for given room"); } return(value); } }
public Neighbour(uint edgeAbIndex, IRoomPlan ab, uint edgeCdIndex, IRoomPlan cd, Vector2 a, float at, Vector2 b, float bt, Vector2 c, float ct, Vector2 d, float dt) { EdgeIndexRoomAB = edgeAbIndex; EdgeIndexRoomCD = edgeCdIndex; RoomAB = ab; RoomCD = cd; A = a; B = b; C = c; D = d; At = at; Bt = bt; Ct = ct; Dt = dt; }
// ReSharper disable once VirtualMemberNeverOverriden.Global (Justification: External API) protected virtual IConfigurableFacade CreateInternalWall(IRoomPlan room, Facade facade, float yOffset) { Contract.Requires(room != null); Contract.Requires(facade != null); Contract.Ensures(Contract.Result <IConfigurableFacade>() != null); var wall = (IConfigurableFacade)CreateChild( new Prism(_roomHeight, facade.Section.GetCorners()), Quaternion.Identity, new Vector3(0, yOffset, 0), InternalFacadeScripts(room) ); wall.Section = facade.Section; //Make sure the room subdivides before the facade (and thus has a chance to configure it ((ISubdivisionContext)wall).AddPrerequisite(room.Node); return(wall); }
public static Section FindSection(this IRoomPlan room, LineSegment2 segment) { Contract.Requires(room != null); var segmentLongLine = segment.LongLine; foreach (var section in room.Sections) { var externalLongRay = section.ExternalLineSegment.LongLine; //Check that the lines are collinear if (externalLongRay.Parallelism(segmentLongLine) != Parallelism.Collinear) { continue; } return(section); } throw new InvalidOperationException("Cannot find a section for the given line segment"); }
protected override IConfigurableFacade FailedToFindExternalSection(IRoomPlan roomPlan, Facade facade) { return(null); }
/// <summary> /// External wall generation failed to find a setion which is co-linear with the given facade section. /// Default behaviour is to return null to do nothing /// </summary> /// <param name="roomPlan"></param> /// <param name="facade"></param> // ReSharper disable UnusedParameter.Global (Justification: External API) protected virtual IConfigurableFacade FailedToFindExternalSection(IRoomPlan roomPlan, Facade facade) // ReSharper restore UnusedParameter.Global { return(null); }
// ReSharper disable once VirtualMemberNeverOverriden.Global (Justification: External API) // ReSharper disable once UnusedParameter.Global (Justification: External API) protected virtual IEnumerable <KeyValuePair <float, ScriptReference> > InternalFacadeScripts(IRoomPlan room) { yield return(new KeyValuePair <float, ScriptReference>(1, new ScriptReference(typeof(ConfigurableFacade)))); }
/// <summary> /// A room was created but it resulted in a null result, this is a chance to substitute in another set of scripts and try again /// </summary> /// <param name="room"></param> /// <param name="plan"></param> /// <returns>A set of scripts to try to create another room, or null to not attempt again</returns> protected virtual IReadOnlyList <KeyValuePair <float, ScriptReference> > SubstituteNullRoomScripts(IRoomPlan room, IFloorPlan plan) { Contract.Requires(room != null); Contract.Requires(plan != null); return(null); }
public void TrainCarriageTest2() { // ReSharper disable InconsistentNaming var r = new Random(); Func <double> Random = r.NextDouble; const int Length = 20; const int Width = 10; Func <Vector2, float, float, Vector2> Offset = (start, length, width) => start + new Vector2(Length * length, -Width * width); Func <IFloorPlanBuilder, bool, float, IEnumerable <IRoomPlan> > CreateBalcony = (pl, start, bl) => { var p = pl.ExternalFootprint.First(); const float wt = 0.11f; if (start) { return(pl.Add(new Vector2[] { Offset(p, 0, 0.01f), Offset(p, bl / Length, 0.01f), Offset(p, bl / Length, 0.99f), Offset(p, 0, 0.99f), }, wt)); } else { return(pl.Add(new Vector2[] { Offset(p, 1 - (bl / Length), 0.01f), Offset(p, 1, 0.01f), Offset(p, 1, 0.99f), Offset(p, 1 - bl / Length, 0.99f), }, wt)); } }; var plan = new GeometricFloorplan(new ReadOnlyCollection <Vector2>(new Vector2[] { new Vector2(-Length / 2f, Width / 2f), new Vector2(Length / 2f, Width / 2f), new Vector2(Length / 2f, -Width / 2f), new Vector2(-Length / 2f, -Width / 2f), })); // ReSharper restore InconsistentNaming //Create balconies on either end float balconyLength = Math.Min(3, Length / 10f); CreateBalcony(plan, true, balconyLength); CreateBalcony(plan, false, balconyLength); //Reference point to create rooms relative to var point = plan.ExternalFootprint.First(); //Create corridor section along entire train (along one side) const float CORRIDOR_WIDTH = 3; plan.Add(new Vector2[] { Offset(point, (balconyLength + 0.05f) / Length, 0), Offset(point, (Length - balconyLength - 0.05f) / Length, 0), Offset(point, (Length - balconyLength - 0.05f) / Length, CORRIDOR_WIDTH / Width), Offset(point, (balconyLength + 0.05f) / Length, CORRIDOR_WIDTH / Width), }, 0.55f); //Create compartments var compartmentAreaLength = Length - (balconyLength + 0.05f) * 2; var compartmentCount = Random.CompartmentalizeSpace(compartmentAreaLength, 1, int.MaxValue, 6, 10); var compartmentLength = compartmentAreaLength / compartmentCount; var compartments = new IRoomPlan[compartmentCount]; for (var i = 0; i < compartmentCount; i++) { var xStart = balconyLength + 0.05f + i * compartmentLength; var xEnd = xStart + compartmentLength - 0.05f; const float Y_START = CORRIDOR_WIDTH; compartments[i] = plan.Add(new Vector2[] { Offset(point, xStart / Length, Y_START / Width), Offset(point, xEnd / Length, Y_START / Width), Offset(point, xEnd / Length, 1), Offset(point, xStart / Length, 1), }, 0.55f).Single(); } plan.Freeze(); DrawPlan(plan); }
public void PlaceRoom(IRandom rand, FloorPlan floorPlan, IRoomGen newGen, RoomHallIndex oldRoomHall) { // first get the adjacents of the removed room Dictionary <Dir4, List <RoomHallIndex> > adjacentsByDir = GetDirectionAdjacents(floorPlan, oldRoomHall); IRoomPlan oldPlan = floorPlan.GetRoomHall(oldRoomHall); // remove the room; update the adjacents too floorPlan.EraseRoomHall(oldRoomHall); foreach (Dir4 dir in DirExt.VALID_DIR4) { for (int jj = 0; jj < adjacentsByDir[dir].Count; jj++) { RoomHallIndex adjRoomHall = adjacentsByDir[dir][jj]; if (adjRoomHall.IsHall == oldRoomHall.IsHall && adjRoomHall.Index > oldRoomHall.Index) { adjacentsByDir[dir][jj] = new RoomHallIndex(adjRoomHall.Index - 1, adjRoomHall.IsHall); } } } var newAdjacents = new List <RoomHallIndex>(); var supportHalls = new Dictionary <Dir4, IPermissiveRoomGen>(); foreach (Dir4 dir in DirExt.VALID_DIR4) { if (newGen.Draw.GetScalar(dir) == oldPlan.RoomGen.Draw.GetScalar(dir)) { newAdjacents.AddRange(adjacentsByDir[dir]); } else if (adjacentsByDir[dir].Count > 0) { Rect supportRect = GetSupportRect(floorPlan, oldPlan.RoomGen, newGen, dir, adjacentsByDir[dir]); var supportHall = (IPermissiveRoomGen)this.Halls.Pick(rand).Copy(); supportHall.PrepareSize(rand, supportRect.Size); supportHall.SetLoc(supportRect.Start); supportHalls[dir] = supportHall; } } // add the new room var newRoomInd = new RoomHallIndex(floorPlan.RoomCount, false); ComponentCollection newCollection = oldPlan.Components.Clone(); foreach (RoomComponent component in this.RoomComponents) { newCollection.Set(component.Clone()); } floorPlan.AddRoom(newGen, newCollection, newAdjacents.ToArray()); // add supporting halls foreach (Dir4 dir in DirExt.VALID_DIR4) { if (supportHalls.ContainsKey(dir)) { // include an attachment to the newly added room List <RoomHallIndex> adjToAdd = new List <RoomHallIndex> { newRoomInd }; adjToAdd.AddRange(adjacentsByDir[dir]); ComponentCollection newHallCollection = oldPlan.Components.Clone(); foreach (RoomComponent component in this.HallComponents) { newHallCollection.Set(component.Clone()); } floorPlan.AddHall(supportHalls[dir], newHallCollection.Clone(), adjToAdd.ToArray()); } } }
public RoomPlanSegment(IRoomPlan room, ushort edgeIndex) { EdgeIndex = edgeIndex; Room = room; }
public abstract bool PassesFilter(IRoomPlan plan);