private void Move(BlockEdge edge, int delta, bool floor) { if (floor) { switch (edge) { case BlockEdge.XnZn: Floor.XnZn += (short)delta; break; case BlockEdge.XnZp: Floor.XnZp += (short)delta; break; case BlockEdge.XpZn: Floor.XpZn += (short)delta; break; case BlockEdge.XpZp: Floor.XpZp += (short)delta; break; } } else { switch (edge) { case BlockEdge.XnZn: Ceiling.XnZn += (short)delta; break; case BlockEdge.XnZp: Ceiling.XnZp += (short)delta; break; case BlockEdge.XpZn: Ceiling.XpZn += (short)delta; break; case BlockEdge.XpZp: Ceiling.XpZp += (short)delta; break; } } }
public float[] GetEdge(BlockEdge edge) { switch (edge) { case BlockEdge.Front: return(Front); case BlockEdge.Right: return(Right); case BlockEdge.Back: return(Back); case BlockEdge.Left: return(Left); case BlockEdge.Top: return(Top); case BlockEdge.Bottom: return(Bottom); } throw new ArgumentException("Unknown surface"); }
public static Vector3[] GetEdge(BlockEdge edge) { switch (edge) { case BlockEdge.Front: return(FrontVertices); case BlockEdge.Right: return(RightVertices); case BlockEdge.Back: return(BackVertices); case BlockEdge.Left: return(LeftVertices); case BlockEdge.Top: return(TopVertices); case BlockEdge.Bottom: return(BottomVertices); } throw new ArgumentException("Unknown surface"); }
public void FixHeights(BlockVertical?vertical = null) { for (BlockEdge i = 0; i < BlockEdge.Count; i++) { SetHeight(BlockVertical.Ed, i, Math.Min(GetHeight(BlockVertical.Ed, i), Floor.GetHeight(i))); SetHeight(BlockVertical.Rf, i, Math.Max(GetHeight(BlockVertical.Rf, i), Ceiling.GetHeight(i))); if (vertical == null || vertical.Value.IsOnFloor()) { if (Floor.DiagonalSplit != DiagonalSplit.None) { Floor.SetHeight(i, Math.Min(Floor.GetHeight(i), Ceiling.Min)); } else { Floor.SetHeight(i, Math.Min(Floor.GetHeight(i), Ceiling.GetHeight(i))); } } if (vertical == null || vertical.Value.IsOnCeiling()) { if (Ceiling.DiagonalSplit != DiagonalSplit.None) { Ceiling.SetHeight(i, Math.Max(Ceiling.GetHeight(i), Floor.Max)); } else { Ceiling.SetHeight(i, Math.Max(Ceiling.GetHeight(i), Floor.GetHeight(i))); } } } }
public void ReplaceGeometry(Level level, Block replacement) { if (Type != BlockType.BorderWall) { Type = replacement.Type; } Flags = replacement.Flags; ForceFloorSolid = replacement.ForceFloorSolid; for (BlockFace face = 0; face < BlockFace.Count; face++) { var texture = replacement.GetFaceTexture(face); if (texture.TextureIsInvisible || level.Settings.Textures.Contains(texture.Texture)) { SetFaceTexture(face, texture); } } for (BlockEdge edge = 0; edge < BlockEdge.Count; edge++) { SetHeight(BlockVertical.Ed, edge, replacement.GetHeight(BlockVertical.Ed, edge)); SetHeight(BlockVertical.Rf, edge, replacement.GetHeight(BlockVertical.Rf, edge)); } Floor = replacement.Floor; Ceiling = replacement.Ceiling; }
public void ChangeHeight(BlockVertical vertical, BlockEdge edge, int increment) { if (increment != 0) { SetHeight(vertical, edge, (short)(GetHeight(vertical, edge) + increment)); } }
public static Vector3[] GetEdge(BlockEdge edge) { switch (edge) { case BlockEdge.Front: case BlockEdge.Right: case BlockEdge.Back: return(MainDiagonalVertices); case BlockEdge.Left: case BlockEdge.Top: case BlockEdge.Bottom: return(CollateralDiagonalVertices); } throw new ArgumentException("Unknown surface"); }
private bool HasNeighbourOn(int x, int y, int z, BlockEdge edge) { var dx = 0; var dy = 0; var dz = 0; switch (edge) { case BlockEdge.Right: dx = 1; break; case BlockEdge.Left: dx = -1; break; case BlockEdge.Front: dz = 1; break; case BlockEdge.Back: dz = -1; break; case BlockEdge.Top: dy = 1; break; case BlockEdge.Bottom: dy = -1; break; } var neighbour = 0; try { neighbour = chunk.Map[x + dx, y + dy, z + dz]; } catch (IndexOutOfRangeException) { return(false); } return(neighbour != 0); }
public Block[,] GetSectors() { if (_data == null) { return(null); } var sectors = new Block[Width, Height]; using (var ms = new MemoryStream(_data)) { using (var reader = new BinaryReader(ms)) { for (int x = 0; x < Width; x++) { for (int z = 0; z < Height; z++) { var b = sectors[x, z] = new Block(0, 12); for (BlockVertical vertical = 0; vertical < BlockVertical.Count; ++vertical) { for (BlockEdge edge = 0; edge < BlockEdge.Count; ++edge) { b.SetHeight(vertical, edge, reader.ReadInt16()); } } b.Type = (BlockType)reader.ReadInt32(); b.ForceFloorSolid = reader.ReadBoolean(); b.Floor.SplitDirectionToggled = reader.ReadBoolean(); b.Floor.SplitDirectionIsXEqualsZ = reader.ReadBoolean(); b.Floor.DiagonalSplit = (DiagonalSplit)reader.ReadInt32(); b.Ceiling.SplitDirectionToggled = reader.ReadBoolean(); b.Ceiling.SplitDirectionIsXEqualsZ = reader.ReadBoolean(); b.Ceiling.DiagonalSplit = (DiagonalSplit)reader.ReadInt32(); b.Flags = (BlockFlags)reader.ReadInt32(); sectors[x, z] = b; } } } } return(sectors); }
public SectorsClipboardData(Editor editor) { var selection = editor.SelectedSectors; Width = selection.Area.Width + 1; Height = selection.Area.Height + 1; using (var ms = new MemoryStream()) { using (var writer = new BinaryWriter(ms)) { Block[,] sectors = new Block[selection.Area.Width, selection.Area.Height]; for (int x = 0; x < Width; x++) { for (int z = 0; z < Height; z++) { var currX = selection.Area.X0 + x; var currZ = selection.Area.Y0 + z; var b = editor.SelectedRoom.Blocks[currX, currZ]; for (BlockVertical vertical = 0; vertical < BlockVertical.Count; ++vertical) { for (BlockEdge edge = 0; edge < BlockEdge.Count; ++edge) { writer.Write((short)b.GetHeight(vertical, edge)); } } writer.Write((int)b.Type); writer.Write(b.ForceFloorSolid); writer.Write(b.Floor.SplitDirectionToggled); writer.Write(b.Floor.SplitDirectionIsXEqualsZ); writer.Write((int)b.Floor.DiagonalSplit); writer.Write(b.Ceiling.SplitDirectionToggled); writer.Write(b.Ceiling.SplitDirectionIsXEqualsZ); writer.Write((int)b.Ceiling.DiagonalSplit); writer.Write((int)b.Flags); } } } _data = ms.ToArray(); } }
public short GetHeight(BlockVertical vertical, BlockEdge edge) { switch (vertical) { case BlockVertical.Floor: return(Floor.GetHeight(edge)); case BlockVertical.Ceiling: return(Ceiling.GetHeight(edge)); case BlockVertical.Ed: return(_ed[(int)edge]); case BlockVertical.Rf: return(_rf[(int)edge]); default: throw new ArgumentOutOfRangeException(); } }
public short GetHeight(BlockEdge edge) { switch (edge) { case BlockEdge.XnZp: return(XnZp); case BlockEdge.XpZp: return(XpZp); case BlockEdge.XpZn: return(XpZn); case BlockEdge.XnZn: return(XnZn); default: throw new ArgumentOutOfRangeException(); } }
public void Raise(BlockVertical vertical, int increment, bool diagonalStep = false) { var split = vertical == BlockVertical.Floor || vertical == BlockVertical.Ed ? Floor.DiagonalSplit : Ceiling.DiagonalSplit; if (diagonalStep) { switch (split) { case DiagonalSplit.XpZn: ChangeHeight(vertical, BlockEdge.XnZp, increment); break; case DiagonalSplit.XnZn: ChangeHeight(vertical, BlockEdge.XpZp, increment); break; case DiagonalSplit.XnZp: ChangeHeight(vertical, BlockEdge.XpZn, increment); break; case DiagonalSplit.XpZp: ChangeHeight(vertical, BlockEdge.XnZn, increment); break; } } else { for (BlockEdge edge = 0; edge < BlockEdge.Count; edge++) { if (edge == BlockEdge.XnZp && split == DiagonalSplit.XpZn || edge == BlockEdge.XnZn && split == DiagonalSplit.XpZp || edge == BlockEdge.XpZn && split == DiagonalSplit.XnZp || edge == BlockEdge.XpZp && split == DiagonalSplit.XnZn) { continue; } ChangeHeight(vertical, edge, increment); } } }
/// <summary>Returns the height of the 4 edges if the sector is split</summary> public int GetActualMin(BlockEdge edge) { switch (DiagonalSplit) { case DiagonalSplit.None: return(GetHeight(edge)); case DiagonalSplit.XnZn: if (edge == BlockEdge.XnZp || edge == BlockEdge.XpZn) { return(Math.Min(GetHeight(edge), XpZp)); } return(GetHeight(edge)); case DiagonalSplit.XpZp: if (edge == BlockEdge.XnZp || edge == BlockEdge.XpZn) { return(Math.Min(GetHeight(edge), XnZn)); } return(GetHeight(edge)); case DiagonalSplit.XpZn: if (edge == BlockEdge.XpZp || edge == BlockEdge.XnZn) { return(Math.Min(GetHeight(edge), XnZp)); } return(GetHeight(edge)); case DiagonalSplit.XnZp: if (edge == BlockEdge.XpZp || edge == BlockEdge.XnZn) { return(Math.Min(GetHeight(edge), XpZn)); } return(GetHeight(edge)); default: throw new ApplicationException("\"splitType\" in unknown state."); } }
public void SetHeight(BlockVertical vertical, BlockEdge edge, int newValue) { switch (vertical) { case BlockVertical.Floor: Floor.SetHeight(edge, newValue); return; case BlockVertical.Ceiling: Ceiling.SetHeight(edge, newValue); return; case BlockVertical.Ed: _ed[(int)edge] = checked ((short)newValue); return; case BlockVertical.Rf: _rf[(int)edge] = checked ((short)newValue); return; default: throw new ArgumentOutOfRangeException(); } }
public void SetHeight(BlockEdge edge, int value) { switch (edge) { case BlockEdge.XnZp: XnZp = checked ((short)value); return; case BlockEdge.XpZp: XpZp = checked ((short)value); return; case BlockEdge.XpZn: XpZn = checked ((short)value); return; case BlockEdge.XnZn: XnZn = checked ((short)value); return; default: throw new ArgumentOutOfRangeException(); } }
public static int DirectionZ(this BlockEdge edge) => (edge == BlockEdge.XnZp || edge == BlockEdge.XpZp) ? 1 : 0;
private static void WriteRooms(ChunkWriter chunkIO, Dictionary <Room, int> rooms, LevelSettingsIds levelSettingIds) { // Allocate object indices var objectInstanceLookup = new Dictionary <ObjectInstance, int>(); foreach (Room room in rooms.Keys) { foreach (ObjectInstance objectInstance in room.AnyObjects) { objectInstanceLookup.Add(objectInstance, objectInstanceLookup.Count); } } // Save using (var chunkRooms = chunkIO.WriteChunk(Prj2Chunks.Rooms, long.MaxValue)) { foreach (Room room in rooms.Keys) { using (var chunkRoom = chunkIO.WriteChunk(Prj2Chunks.Room, long.MaxValue)) { LEB128.Write(chunkIO.Raw, room.NumXSectors); LEB128.Write(chunkIO.Raw, room.NumZSectors); // Write basic properties chunkIO.WriteChunkInt(Prj2Chunks.RoomIndex, rooms.TryGetOrDefault(room, -1)); chunkIO.WriteChunkString(Prj2Chunks.RoomName, room.Name); chunkIO.WriteChunkVector3(Prj2Chunks.RoomPosition, room.Position); chunkIO.WriteChunkArrayOfBytes(Prj2Chunks.RoomTags, System.Text.Encoding.UTF8.GetBytes(string.Join(" ", room.Tags))); // Write sectors using (var chunkRoomSectors = chunkIO.WriteChunk(Prj2Chunks.RoomSectors)) { for (int z = 0; z < room.NumZSectors; z++) { for (int x = 0; x < room.NumXSectors; x++) { using (var chunkSector = chunkIO.WriteChunk(Prj2Chunks.Sector, LEB128.MaximumSize2Byte)) { chunkIO.Raw.Write(x + z * room.NumXSectors); var b = room.Blocks[x, z]; long combinedFlag = (b.IsAnyWall ? 1L : 0) | (b.ForceFloorSolid ? 2L : 0) | ((long)b.Flags << 2); chunkIO.WriteChunkInt(Prj2Chunks.SectorProperties, combinedFlag); using (var chunkSectorFloor = chunkIO.WriteChunk(Prj2Chunks.SectorFloor, LEB128.MaximumSize1Byte)) { long flag = (b.Floor.SplitDirectionIsXEqualsZ ? 1L : 0) | ((long)b.Floor.DiagonalSplit << 1); LEB128.Write(chunkIO.Raw, flag); for (BlockEdge edge = 0; edge < BlockEdge.Count; ++edge) { LEB128.Write(chunkIO.Raw, b.Floor.GetHeight(edge)); } for (BlockEdge edge = 0; edge < BlockEdge.Count; ++edge) { LEB128.Write(chunkIO.Raw, b.GetHeight(BlockVertical.Ed, edge)); } } using (var chunkSectorCeiling = chunkIO.WriteChunk(Prj2Chunks.SectorCeiling, LEB128.MaximumSize1Byte)) { long flag = (b.Ceiling.SplitDirectionIsXEqualsZ ? 1L : 0) | ((long)b.Ceiling.DiagonalSplit << 1); LEB128.Write(chunkIO.Raw, flag); for (BlockEdge edge = 0; edge < BlockEdge.Count; ++edge) { LEB128.Write(chunkIO.Raw, b.Ceiling.GetHeight(edge)); } for (BlockEdge edge = 0; edge < BlockEdge.Count; ++edge) { LEB128.Write(chunkIO.Raw, b.GetHeight(BlockVertical.Rf, edge)); } } for (BlockFace face = 0; face < BlockFace.Count; face++) { var texture = b.GetFaceTexture(face); if (texture.Texture == null) { continue; } if (texture.Texture is LevelTexture) { using (var chunkTextureLevelTexture = chunkIO.WriteChunk(Prj2Chunks.TextureLevelTexture2, LEB128.MaximumSize1Byte)) { int textureIndex = levelSettingIds.LevelTextures[(LevelTexture)texture.Texture]; LEB128.Write(chunkIO.Raw, (long)face); chunkIO.Raw.Write(texture.TexCoord0); chunkIO.Raw.Write(texture.TexCoord1); chunkIO.Raw.Write(texture.TexCoord2); chunkIO.Raw.Write(texture.TexCoord3); chunkIO.Raw.Write(texture.ParentArea.Start); chunkIO.Raw.Write(texture.ParentArea.End); LEB128.Write(chunkIO.Raw, (texture.DoubleSided ? 1L : 0) | ((long)texture.BlendMode << 1)); LEB128.Write(chunkIO.Raw, textureIndex); } } else if (texture.Texture == TextureInvisible.Instance) { chunkIO.WriteChunkInt(Prj2Chunks.TextureInvisible, (long)face); } else { throw new NotSupportedException("Unsupported texture type " + texture.Texture.GetType().Name); } } chunkIO.WriteChunkEnd(); } } } chunkIO.WriteChunkEnd(); } // Write room properties chunkIO.WriteChunkVector3(Prj2Chunks.RoomAmbientLight, room.AmbientLight); chunkIO.WriteChunkBool(Prj2Chunks.RoomFlagCold, room.FlagCold); chunkIO.WriteChunkBool(Prj2Chunks.RoomFlagDamage, room.FlagDamage); chunkIO.WriteChunkBool(Prj2Chunks.RoomFlagHorizon, room.FlagHorizon); chunkIO.WriteChunkBool(Prj2Chunks.RoomFlagOutside, room.FlagOutside); chunkIO.WriteChunkBool(Prj2Chunks.RoomFlagNoLensflare, room.FlagNoLensflare); chunkIO.WriteChunkBool(Prj2Chunks.RoomFlagExcludeFromPathFinding, room.FlagExcludeFromPathFinding); chunkIO.WriteChunkInt(Prj2Chunks.RoomType, (int)room.Type); chunkIO.WriteChunkInt(Prj2Chunks.RoomTypeStrength, room.TypeStrength); chunkIO.WriteChunkInt(Prj2Chunks.RoomLightEffect, (int)room.LightEffect); chunkIO.WriteChunkInt(Prj2Chunks.RoomLightEffectStrength2, room.LightEffectStrength); chunkIO.WriteChunkInt(Prj2Chunks.RoomReverberation, (int)room.Reverberation); chunkIO.WriteChunkInt(Prj2Chunks.RoomLightInterpolationMode, (int)room.LightInterpolationMode); chunkIO.WriteChunkBool(Prj2Chunks.RoomLocked, room.Locked); chunkIO.WriteChunkBool(Prj2Chunks.RoomHidden, room.Hidden); if (room.AlternateRoom != null && rooms.ContainsKey(room.AlternateRoom)) { using (var chunkRoomAlternate = chunkIO.WriteChunk(Prj2Chunks.RoomAlternate, LEB128.MaximumSize1Byte)) { chunkIO.WriteChunkInt(Prj2Chunks.AlternateGroup, room.AlternateGroup); chunkIO.WriteChunkInt(Prj2Chunks.AlternateRoom, rooms[room.AlternateRoom]); chunkIO.WriteChunkEnd(); } } // Write room objects WriteObjects(chunkIO, room.AnyObjects, rooms, levelSettingIds, objectInstanceLookup); chunkIO.WriteChunkEnd(); } } chunkIO.WriteChunkEnd(); } }