World Builder – MapEditor.cs

 

#region Using Statements
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using ParadigmEngine;
using ParadigmEngine.ParticleSystem;
using ParadigmEngine.TileEngine;
#endregion

namespace Paradigm
{
    /// <summary>
    /// Static class which handles map editing
    /// </summary>
    public static class MapEditor
    {
        #region Public Methods
        /// <summary>
        /// Set tile collision
        /// </summary>
        public static void SetCollision(Map map, Vector2 tileLocation, EditorBrush brush)
        {
            // get the tile in question
            Tile tile = map.GetTile((int)tileLocation.X, (int)tileLocation.Y);

            // identify the collision layer index
            int collisionIndex = tile.Layers.Count - 2;

            TileCollision collisionType = TileCollision.Passable;

            switch (brush)
            {
                case EditorBrush.Collision_Passable:
                    collisionType = TileCollision.Passable;
                    break;

                case EditorBrush.Collision_Impassable:
                    collisionType = TileCollision.Impassable;
                    break;

                case EditorBrush.Collision_Platform:
                    collisionType = TileCollision.Platform;
                    break;

                case EditorBrush.Collision_SlopeDown:
                    collisionType = TileCollision.SlopeDown;
                    break;

                case EditorBrush.Collision_SlopeUp:
                    collisionType = TileCollision.SlopeUp;
                    break;

                case EditorBrush.Collision_Abnormal:
                    collisionType = TileCollision.Abnormal;
                    break;

                case EditorBrush.Collision_NPC:
                    collisionType = TileCollision.NPC;
                    break;
            }

            tile.Layers[collisionIndex] = (int)collisionType;
            tile.CollisionType = collisionType;
        }
        /*
        /// <summary>
        /// Mark tile at selected location as passable
        /// </summary>
        public static void CollisionPassible(Map map, Vector2 tileLocation)
        {
            // get the tile in question
            Tile tile = map.GetTile((int)tileLocation.X, (int)tileLocation.Y);

            // identify the collision layer index
            int collisionIndex = tile.Layers.Count - 2;

            tile.Layers[collisionIndex] = (float)TileCollision.Passable;
            tile.CollisionType = TileCollision.Passable;
        }

        /// <summary>
        /// Mark tile at selected location as impassable
        /// </summary>
        public static void CollisionImpassable(Map map, Vector2 tileLocation)
        {
            // get the tile in question
            Tile tile = map.GetTile((int)tileLocation.X, (int)tileLocation.Y);

            // identify the collision layer index
            int collisionIndex = tile.Layers.Count - 2;

            tile.Layers[collisionIndex] = (float)TileCollision.Impassable;
            tile.CollisionType = TileCollision.Impassable;
        }

        /// <summary>
        /// Mark tile at selected location as being a ladder
        /// </summary>
        public static void CollisionPlatform(Map map, Vector2 tileLocation)
        {
            // get the tile in question
            Tile tile = map.GetTile((int)tileLocation.X, (int)tileLocation.Y);

            // identify the collision layer index
            int collisionIndex = tile.Layers.Count - 2;

            tile.Layers[collisionIndex] = (float)TileCollision.Platform;
            tile.CollisionType = TileCollision.Platform;
        }

        /// <summary>
        /// Mark tile at selected location as being a downward right angle slope
        /// </summary>
        public static void CollisionSlopeDown(Map map, Vector2 tileLocation)
        {
            // get the tile in question
            Tile tile = map.GetTile((int)tileLocation.X, (int)tileLocation.Y);

            // identify the collision layer index
            int collisionIndex = tile.Layers.Count - 2;

            tile.Layers[collisionIndex] = (float)TileCollision.SlopeDown;
            tile.CollisionType = TileCollision.SlopeDown;
        }

        /// <summary>
        /// Mark tile at selected location as being an upward right angle slope
        /// </summary>
        public static void CollisionSlopeUp(Map map, Vector2 tileLocation)
        {
            // get the tile in question
            Tile tile = map.GetTile((int)tileLocation.X, (int)tileLocation.Y);

            // identify the collision layer index
            int collisionIndex = tile.Layers.Count - 2;

            tile.Layers[collisionIndex] = (float)TileCollision.SlopeUp;
            tile.CollisionType = TileCollision.SlopeUp;
        }
        */

        /// <summary>
        /// Draw tiles on our map
        /// </summary>
        /// <param name="map">The map</param>
        /// <param name="tileLocation">Location of tile in tile coords</param>
        /// <param name="currentLayer">Current layer</param>
        /// <param name="selectedTile">Selected tile passed from main form</param>
        /// <param name="selectedMultipleTiles">Have we selected multiple tiles?</param>
        /// <param name="selectedStartTile">The starting tile of our range if multiple are selected</param>
        /// <param name="selectedTileRange">The range of selected tiles if multiple are selected</param>
        public static void TileDraw(Map map, Vector2 tileLocation, int currentLayer, SelectedTile selectedTile, bool selectedMultipleTiles , Vector2 selectedStartTile, Vector2 selectedTileRange)
        {
            if ((selectedTile.ID != -1) && (currentLayer != -1))
            {
                // get the tile in question
                Tile tile = map.GetTile((int)tileLocation.X, (int)tileLocation.Y);

                if (selectedMultipleTiles == false)
                {
                    tile.Layers[currentLayer] = selectedTile.ID;
                    tile.SourceRectangles[currentLayer] = selectedTile.SourceRect;
                }
                else
                {
                    int xRange = (int)selectedTileRange.X;
                    int yRange = (int)selectedTileRange.Y;

                    Vector2 clickLocation = tileLocation;

                    // iterate through selected range and set all source rects
                    for (int y = 0; y <= yRange; y++)
                    {
                        for (int x = 0; x <= xRange; x++)
                        {
                            // make sure the tile is within bounds to prevent any weirdness
                            if (((int)clickLocation.X + x < map.Width) && ((int)clickLocation.Y + y < map.Height))
                            {
                                Tile tempTile = map.GetTile((int)clickLocation.X + x, (int)clickLocation.Y + y);

                                int sourceID = (int)(((selectedStartTile.Y + y) * (map.TilesetTextures.ColorMap.Width / map.Tile_Size)) + (selectedStartTile.X + x));

                                // set the tile ID
                                tempTile.Layers[currentLayer] = sourceID;

                                // update source rects
                                tempTile.FindSourceRectangles();
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Fill the specified layer with the specified tile
        /// </summary>
        public static void TileLayerFill(Map map, int currentLayer, SelectedTile selectedTile)
        {
            if ((selectedTile.ID != -1) && (currentLayer != -1))
            {
                for (int y = 0; y < map.Height; y++)
                {
                    for (int x = 0; x < map.Width; x++)
                    {
                        Tile tempTile = map.GetTile(x, y);
                        tempTile.Layers[currentLayer] = selectedTile.ID;
                        tempTile.SourceRectangles[currentLayer] = selectedTile.SourceRect;
                    }
                }
            }
        }

        /// <summary>
        /// Draw an animated tile at the location specified
        /// </summary>
        public static void AnimatedTileDraw(Map map, int currentLayer, AnimatedTile selectedTile, Vector2 tileLocation)
        {
            if ((selectedTile != null) && (currentLayer != -1))
            {
                Vector2 worldPosition = new Vector2(tileLocation.X * map.Tile_Size, tileLocation.Y * map.Tile_Size);
                int tileID = (int)(tileLocation.Y * map.Width) + (int)tileLocation.X;

                // create a copy of the tile
                AnimatedTile newTile = selectedTile.Clone();
                newTile.Layer = currentLayer;
                newTile.ID = tileID;
                newTile.ResourcePath = selectedTile.ResourcePath;
                newTile.WorldPosition = worldPosition;
                newTile.TilePosition = tileLocation;
                newTile.IsPlaced = true;

                // initialize the new tile if needed
                if (!newTile.IsInitialized)
                    newTile.Initialize(selectedTile.TileAnimation.Texture, selectedTile.TileDesc);

                map.AddAnimatedTile(newTile);
            }
        }

        /// <summary>
        /// Fill a layer with the animated tile specified
        /// </summary>
        public static void AnimatedTileLayerFill(Map map, int currentLayer, AnimatedTile selectedTile, int mapTileWidth, int mapTileHeight)
        {
            if ((selectedTile != null) && (currentLayer != -1))
            {
                for (int y = 0; y < mapTileHeight; y++)
                {
                    for (int x = 0; x < mapTileWidth; x++)
                    {
                        Vector2 worldPosition = new Vector2((float)x * map.Tile_Size, (float)y * map.Tile_Size);
                        int tileID = (int)(y * map.Width) + (int)x;

                        // create a copy of the tile
                        AnimatedTile newTile = selectedTile.Clone();
                        newTile.Layer = currentLayer;
                        newTile.ID = tileID;
                        newTile.ResourcePath = selectedTile.ResourcePath;
                        newTile.WorldPosition = worldPosition;
                        newTile.TilePosition = new Vector2((float)x, (float)y);
                        newTile.IsPlaced = true;

                        // initialize the new tile if needed
                        if (!newTile.IsInitialized)
                            newTile.Initialize(selectedTile.TileAnimation.Texture, selectedTile.TileDesc);

                        map.AddAnimatedTile(newTile);
                    }
                }
            }
        }

        /// <summary>
        /// Erase tile at specified location and layer
        /// </summary>
        public static void TileErase(Map map, Vector2 tileLocation, int currentLayer)
        {
            // get the tile in question
            Tile tile = map.GetTile((int)tileLocation.X, (int)tileLocation.Y);

            if (currentLayer != -1)
                tile.Layers[currentLayer] = -1;

            tile.RemoveAnimatedTileAt(currentLayer);
        }

        /// <summary>
        /// Mark specified tile as a hazard
        /// </summary>
        public static void HazardDamage(Map map, Vector2 tileLocation)
        {
            // get the tile in question
            Tile tile = map.GetTile((int)tileLocation.X, (int)tileLocation.Y);

            // identify the hazard layer index
            int hazardIndex = tile.Layers.Count - 3;

            tile.Layers[hazardIndex] = 1;
            tile.IsHazard = true;
        }

        /// <summary>
        /// Mark specified tile as not being a hazard
        /// </summary>
        public static void HazardNone(Map map, Vector2 tileLocation)
        {
            // get the tile in question
            Tile tile = map.GetTile((int)tileLocation.X, (int)tileLocation.Y);

            // identify the hazard layer index
            int hazardIndex = tile.Layers.Count - 3;

            tile.Layers[hazardIndex] = -1;
            tile.IsHazard = false;
        }

        /// <summary>
        /// Mark specified tile as having a terrain type
        /// </summary>
        public static void TerrainSet(Map map, Vector2 tileLocation, int terrainType)
        {
            // get the tile in question
            Tile tile = map.GetTile((int)tileLocation.X, (int)tileLocation.Y);

            // identify the terrain layer index
            int terrainIndex = tile.Layers.Count - 1;

            tile.Layers[terrainIndex] = terrainType;
            tile.TerrainIndex = terrainType;
        }

        /// <summary>
        /// Mark specified tile as not having a terrain type
        /// </summary>
        public static void TerrainNone(Map map, Vector2 tileLocation)
        {
            // get the tile in question
            Tile tile = map.GetTile((int)tileLocation.X, (int)tileLocation.Y);

            // identify the terrain layer index
            int terrainIndex = tile.Layers.Count - 1;

            tile.Layers[terrainIndex] = -1;
            tile.TerrainIndex = -1;
        }

        /// <summary>
        /// Place an entity or spawn point
        /// </summary>
        /// <param name="map">Current map</param>
        /// <param name="entityLayer">EntityLayer object</param>
        /// <param name="selectedEntity">The entity to place</param>
        /// <param name="tileLocation">The location in tile coords</param>
        public static void EntityDraw(Map map, EntityLayer entityLayer, MapEntity selectedEntity, Vector2 tileLocation)
        {
            if (selectedEntity != null)
            {
                Vector2 worldPosition = new Vector2((tileLocation.X * map.Tile_Size) + selectedEntity.Sprite.Origin.X,
                                                     tileLocation.Y * map.Tile_Size);

                entityLayer.Add(selectedEntity, worldPosition, tileLocation);
                entityLayer.Sort();
            }
        }

        /// <summary>
        /// Remove a spawn point or entity
        /// </summary>
        /// <param name="entityLayer">EntityLayer object</param>
        /// <param name="selectionReticle">Selection reticle from our map</param>
        public static void EntityErase(EntityLayer entityLayer, SelectionReticle selectionReticle)
        {
            for (int i = entityLayer.EntityList.Count - 1; i >= 0; i--)
            {
                if (entityLayer.EntityList[i].BoundingRectangle.Intersects(selectionReticle.BoundingRectangle))
                {
                    entityLayer.Remove(i);
                    break;
                }
            }
        }

        /// <summary>
        /// Place a particle emitter
        /// </summary>
        /// <param name="map">Current map</param>
        /// <param name="particleLayer">ParticleLayer object</param>
        /// <param name="selectedEmitter">Selected emitter</param>
        /// <param name="tileLocation">Location in tile coords</param>
        public static void ParticleEmitterDraw(Map map, ParticleLayer particleLayer, ParticleEmitter selectedEmitter, Vector2 tileLocation)
        {
            if (selectedEmitter != null)
            {
                Vector2 worldPosition = new Vector2(tileLocation.X * map.Tile_Size, tileLocation.Y * map.Tile_Size);
                Vector2 correctedWorldPos = new Vector2(worldPosition.X + map.Tile_Size / 2, worldPosition.Y + map.Tile_Size / 2);
                particleLayer.Add(selectedEmitter, correctedWorldPos, tileLocation);
            }
        }

        /// <summary>
        /// Remove a particle emitter
        /// </summary>
        /// <param name="map">Current map</param>
        /// <param name="particleLayer">ParticleLayer object</param>
        /// <param name="tileLocation">Location in tile coords</param>
        public static void ParticleEmitterErase(Map map, ParticleLayer particleLayer, Vector2 tileLocation)
        {
            for (int i = 0; i < particleLayer.EmitterList.Count; i++)
            {
                if (particleLayer.EmitterList[i].TilePosition == tileLocation)
                {
                    particleLayer.Remove(i);
                    break;
                }
            }
        }

        /// <summary>
        /// Draw a portal
        /// </summary>
        /// <param name="map">Current map</param>
        /// <param name="portalSelection">List of rectangles contained in our selection</param>
        /// <param name="inputHandler">Input handler object</param>
        /// <param name="portalInfoList">Current list of PortalInfo data structures</param>
        /// <param name="portalIndex">The index of the portal in the PortalInfo list</param>
        public static void PortalDraw(Map map, MouseSelectionHandler inputHandler, List<PortalInfo> portalInfoList, int portalIndex)
        {
            List<Rectangle> portalSelection = new List<Rectangle>();

            // process selected tiles
            for (int y = 0; y < map.Height; y++)
            {
                for (int x = 0; x < map.Width; x++)
                {
                    Tile tempTile = map.GetTile(x, y);

                    if (inputHandler.MouseRec.Contains(tempTile.MapRectangle.Center))
                    {
                        portalSelection.Add(tempTile.MapRectangle);
                    }
                }
            }

            // declare temp variables
            int tempX = 0;
            int tempY = 0;
            int tempWidth = 0;
            int tempHeight = 0;

            // sort list to find x and width
            portalSelection.Sort(delegate(Rectangle rect1, Rectangle rect2)
            {
                return rect1.X.CompareTo(rect2.X);
            });

            // get x coord and width for our new rectangle
            if (portalSelection.Count > 0)
            {
                tempX = portalSelection[0].X;
                tempWidth = portalSelection[portalSelection.Count - 1].X - tempX + (int)map.Tile_Size;
            }

            // sort list to find y and height
            portalSelection.Sort(delegate(Rectangle rect1, Rectangle rect2)
            {
                return rect1.Y.CompareTo(rect2.Y);
            });

            // get x coord and width for our new rectangle
            if (portalSelection.Count > 0)
            {
                tempY = portalSelection[0].Y;
                tempHeight = portalSelection[portalSelection.Count - 1].Y - tempY + (int)map.Tile_Size;
            }

            // write bounding box to portal
            if ((portalSelection.Count > 0) && (portalIndex >= 0))
            {
                Rectangle tempRect = new Rectangle(tempX, tempY, tempWidth, tempHeight);

                // as we cannot access the elements of the list directly, create a temp copy, modify, and replace it in the list
                PortalInfo tempPortalInfo = portalInfoList[portalIndex];
                tempPortalInfo.boundingBox = tempRect;
                portalInfoList[portalIndex] = tempPortalInfo;
            }
        }
        /// <summary>
        /// Draw an event region
        /// </summary>
        /// <param name="map">Current map</param>
        /// <param name="effectSelection">List of rectangles contained in our selection</param>
        /// <param name="inputHandler">Input handler object</param>
        /// <param name="shaderRegionInfoList">Current list of MapEventInfo data structures</param>
        /// <param name="shaderRegionIndex">The index of the portal in the MapEventInfo list</param>
        public static void EventRegionDraw(Map map, MouseSelectionHandler inputHandler, List<MapEventInfo> mapEventInfoList, int mapEventIndex)
        {
            List<Rectangle> eventSelection = new List<Rectangle>();

            // process selected tiles
            for (int y = 0; y < map.Height; y++)
            {
                for (int x = 0; x < map.Width; x++)
                {
                    Tile tempTile = map.GetTile(x, y);

                    if (inputHandler.MouseRec.Contains(tempTile.MapRectangle.Center))
                    {
                        eventSelection.Add(tempTile.MapRectangle);
                    }
                }
            }

            // declare temp variables
            int tempX = 0;
            int tempY = 0;
            int tempWidth = 0;
            int tempHeight = 0;

            // sort list to find x and width
            eventSelection.Sort(delegate(Rectangle rect1, Rectangle rect2)
            {
                return rect1.X.CompareTo(rect2.X);
            });

            // get x coord and width for our new rectangle
            if (eventSelection.Count > 0)
            {
                tempX = eventSelection[0].X;
                tempWidth = eventSelection[eventSelection.Count - 1].X - tempX + (int)map.Tile_Size;
            }

            // sort list to find y and height
            eventSelection.Sort(delegate(Rectangle rect1, Rectangle rect2)
            {
                return rect1.Y.CompareTo(rect2.Y);
            });

            // get x coord and width for our new rectangle
            if (eventSelection.Count > 0)
            {
                tempY = eventSelection[0].Y;
                tempHeight = eventSelection[eventSelection.Count - 1].Y - tempY + (int)map.Tile_Size;
            }

            // write bounding box to portal
            if ((eventSelection.Count > 0) && (mapEventIndex >= 0))
            {
                Rectangle tempRect = new Rectangle(tempX, tempY, tempWidth, tempHeight);

                // as we cannot access the elements of the list directly, create a temp copy, modify, and replace it in the list
                MapEventInfo tempEventInfo = mapEventInfoList[mapEventIndex];
                tempEventInfo.boundingBox = tempRect;
                mapEventInfoList[mapEventIndex] = tempEventInfo;
            }
        }

        /// <summary>
        /// Draw a shader effect region
        /// </summary>
        /// <param name="map">Current map</param>
        /// <param name="effectSelection">List of rectangles contained in our selection</param>
        /// <param name="inputHandler">Input handler object</param>
        /// <param name="shaderRegionInfoList">Current list of ShaderRegionInfo data structures</param>
        /// <param name="shaderRegionIndex">The index of the portal in the ShaderRegionInfo list</param>
        public static void ShaderRegionDraw(Map map, MouseSelectionHandler inputHandler, List<ShaderRegionInfo> shaderRegionInfoList, int shaderRegionIndex)
        {
            List<Rectangle> effectSelection = new List<Rectangle>();

            // process selected tiles
            for (int y = 0; y < map.Height; y++)
            {
                for (int x = 0; x < map.Width; x++)
                {
                    Tile tempTile = map.GetTile(x, y);

                    if (inputHandler.MouseRec.Contains(tempTile.MapRectangle.Center))
                    {
                        effectSelection.Add(tempTile.MapRectangle);
                    }
                }
            }

            // declare temp variables
            int tempX = 0;
            int tempY = 0;
            int tempWidth = 0;
            int tempHeight = 0;

            // sort list to find x and width
            effectSelection.Sort(delegate(Rectangle rect1, Rectangle rect2)
            {
                return rect1.X.CompareTo(rect2.X);
            });

            // get x coord and width for our new rectangle
            if (effectSelection.Count > 0)
            {
                tempX = effectSelection[0].X;
                tempWidth = effectSelection[effectSelection.Count - 1].X - tempX + (int)map.Tile_Size;
            }

            // sort list to find y and height
            effectSelection.Sort(delegate(Rectangle rect1, Rectangle rect2)
            {
                return rect1.Y.CompareTo(rect2.Y);
            });

            // get x coord and width for our new rectangle
            if (effectSelection.Count > 0)
            {
                tempY = effectSelection[0].Y;
                tempHeight = effectSelection[effectSelection.Count - 1].Y - tempY + (int)map.Tile_Size;
            }

            // write bounding box to portal
            if ((effectSelection.Count > 0) && (shaderRegionIndex >= 0))
            {
                Rectangle tempRect = new Rectangle(tempX, tempY, tempWidth, tempHeight);

                // as we cannot access the elements of the list directly, create a temp copy, modify, and replace it in the list
                ShaderRegionInfo tempShaderRegionInfo = shaderRegionInfoList[shaderRegionIndex];
                tempShaderRegionInfo.boundingBox = tempRect;
                shaderRegionInfoList[shaderRegionIndex] = tempShaderRegionInfo;
            }
        }
#endregion
    }
}