Beispiel #1
0
        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;
                }
            }
        }
Beispiel #2
0
        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");
        }
Beispiel #3
0
        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");
        }
Beispiel #4
0
        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)));
                    }
                }
            }
        }
Beispiel #5
0
        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;
        }
Beispiel #6
0
 public void ChangeHeight(BlockVertical vertical, BlockEdge edge, int increment)
 {
     if (increment != 0)
     {
         SetHeight(vertical, edge, (short)(GetHeight(vertical, edge) + increment));
     }
 }
Beispiel #7
0
        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");
        }
Beispiel #8
0
        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();
            }
        }
Beispiel #11
0
        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();
            }
        }
Beispiel #12
0
        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();
            }
        }
Beispiel #13
0
        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);
                }
            }
        }
Beispiel #14
0
        /// <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.");
            }
        }
Beispiel #15
0
        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();
            }
        }
Beispiel #16
0
        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();
            }
        }
Beispiel #17
0
 public static int DirectionZ(this BlockEdge edge) => (edge == BlockEdge.XnZp || edge == BlockEdge.XpZp) ? 1 : 0;
Beispiel #18
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();
            }
        }