|
|
|
|
using System;
|
|
|
|
|
using System.Collections;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
using UnityEngine.Tilemaps;
|
|
|
|
|
|
|
|
|
|
namespace MoreMountains.Tools
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// A class used to display a reoderable list of MMTilemapGeneratorLayers
|
|
|
|
|
/// </summary>
|
|
|
|
|
[System.Serializable]
|
|
|
|
|
public class MMTilemapGeneratorLayerList : MMReorderableArray<MMTilemapGeneratorLayer>
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// A class used to store and edit the data of MMTilemapGenerator layers, which you can use and combine
|
|
|
|
|
/// to generate unique and random grids
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Serializable]
|
|
|
|
|
public class MMTilemapGeneratorLayer
|
|
|
|
|
{
|
|
|
|
|
/// the grid generated by this layer
|
|
|
|
|
public int[,] Grid { get; set; }
|
|
|
|
|
|
|
|
|
|
/// the various modes of fusion you can use on this layer.
|
|
|
|
|
/// Fusion modes will be applied on layers from top to bottom (the last to speak wins)
|
|
|
|
|
/// Normal : just generates a grid, default mode
|
|
|
|
|
/// NormalNoClear : generates a grid, but doesn't clear it first
|
|
|
|
|
/// Intersect : when painting on a target grid that already has content, will only keep the resulting intersection
|
|
|
|
|
/// Combine : adds the result of this grid to the existing target
|
|
|
|
|
/// Subtract : removes the result of this grid from the existing target
|
|
|
|
|
public enum FusionModes { Normal, NormalNoClear, Intersect, Combine, Subtract }
|
|
|
|
|
|
|
|
|
|
/// the name of this layer, doesn't do anything, just used to organize things
|
|
|
|
|
[Tooltip("the name of this layer, doesn't do anything, just used to organize things")]
|
|
|
|
|
public string Name = "Layer";
|
|
|
|
|
/// whether this layer should be taken into account when generating the final grid
|
|
|
|
|
[Tooltip("whether this layer should be taken into account when generating the final grid")]
|
|
|
|
|
public bool Active = true;
|
|
|
|
|
|
|
|
|
|
[Header("Tilemaps")]
|
|
|
|
|
/// the tilemap on which to paint tiles
|
|
|
|
|
[Tooltip("the tilemap on which to paint tiles")]
|
|
|
|
|
public Tilemap TargetTilemap;
|
|
|
|
|
/// the tile to use to paint on the tilemap
|
|
|
|
|
[Tooltip("the tile to use to paint on the tilemap")]
|
|
|
|
|
public TileBase Tile;
|
|
|
|
|
|
|
|
|
|
[Header("Grid")]
|
|
|
|
|
/// whether or not this layer should paint a grid of a different size than the global one
|
|
|
|
|
[Tooltip("whether or not this layer should paint a grid of a different size than the global one")]
|
|
|
|
|
public bool OverrideGridSize = false;
|
|
|
|
|
/// the new value of the grid width
|
|
|
|
|
[Tooltip("the new value of the grid width")]
|
|
|
|
|
[MMCondition("OverrideGridSize", true)]
|
|
|
|
|
public int GridWidth = 50;
|
|
|
|
|
/// the new value of the grid height
|
|
|
|
|
[Tooltip("the new value of the grid height")]
|
|
|
|
|
[MMCondition("OverrideGridSize", true)]
|
|
|
|
|
public int GridHeight = 50;
|
|
|
|
|
|
|
|
|
|
[Header("Method")]
|
|
|
|
|
/// the algorithm to use to generate this layer's grid
|
|
|
|
|
[Tooltip("the algorithm to use to generate this layer's grid :\n" +
|
|
|
|
|
"Full : will fill or empty the grid\n" +
|
|
|
|
|
"Perlin : uses perlin noise to randomly fill the grid\n" +
|
|
|
|
|
"Perling Ground : uses perlin noise to generate a ground surface\n" +
|
|
|
|
|
"Random Walk : starts at point A then moves randomly, carving a path\n" +
|
|
|
|
|
"Random Walk Avoider : same, but avoids obstacles\n" +
|
|
|
|
|
"Path : starts at Point A, and carves a path in the selected direction\n" +
|
|
|
|
|
"Copy : copies another tilemap to generate a grid")]
|
|
|
|
|
public MMTilemapGenerator.GenerateMethods GenerateMethod = MMTilemapGenerator.GenerateMethods.Perlin;
|
|
|
|
|
/// if this is true, global seed won't be used for this layer
|
|
|
|
|
[Tooltip("if this is true, global seed won't be used for this layer")]
|
|
|
|
|
public bool DoNotUseGlobalSeed = false;
|
|
|
|
|
/// whether or not to randomize this layer's seed when pressing Generate
|
|
|
|
|
[Tooltip("whether or not to randomize this layer's seed when pressing Generate")]
|
|
|
|
|
[MMCondition("DoNotUseGlobalSeed", true)]
|
|
|
|
|
public bool RandomizeSeed = true;
|
|
|
|
|
/// the dedicated seed of this layer, when not using the global one
|
|
|
|
|
[Tooltip("the dedicated seed of this layer, when not using the global one")]
|
|
|
|
|
[MMCondition("DoNotUseGlobalSeed", true)]
|
|
|
|
|
public int Seed = 1;
|
|
|
|
|
|
|
|
|
|
[Header("PostProcessing")]
|
|
|
|
|
/// whether or not to smoothen the resulting grid, gets rid of spikes/isolated points
|
|
|
|
|
[Tooltip("whether or not to smoothen the resulting grid, gets rid of spikes/isolated points")]
|
|
|
|
|
public bool Smooth = false;
|
|
|
|
|
/// whether or not to invert the grid to get the opposite result (filled becomes empty, empty becomes filled)
|
|
|
|
|
[Tooltip("whether or not to invert the grid to get the opposite result (filled becomes empty, empty becomes filled)")]
|
|
|
|
|
public bool InvertGrid = false;
|
|
|
|
|
/// The selected fusion mode
|
|
|
|
|
[Tooltip("the various modes of fusion you can use on this layer.\n" +
|
|
|
|
|
"Fusion modes will be applied on layers from top to bottom (the last to speak wins)\n" +
|
|
|
|
|
"Normal : just generates a grid, default mode\n" +
|
|
|
|
|
"NormalNoClear : generates a grid, but doesn't clear it first\n" +
|
|
|
|
|
"Intersect : when painting on a target grid that already has content, will only keep the resulting intersection\n" +
|
|
|
|
|
"Combine : adds the result of this grid to the existing target\n" +
|
|
|
|
|
"Subtract : removes the result of this grid from the existing target")]
|
|
|
|
|
public FusionModes FusionMode = FusionModes.Normal;
|
|
|
|
|
|
|
|
|
|
[Header("Settings")]
|
|
|
|
|
|
|
|
|
|
// full
|
|
|
|
|
/// in full mode, whether the grid should be full or empty
|
|
|
|
|
[Tooltip("in full mode, whether the grid should be full or empty")]
|
|
|
|
|
[MMEnumCondition("GenerateMethod", (int)MMTilemapGenerator.GenerateMethods.Full)]
|
|
|
|
|
public bool FullGenerationFilled = true;
|
|
|
|
|
|
|
|
|
|
// random
|
|
|
|
|
/// in random mode, the percentage of the grid to fill
|
|
|
|
|
[Tooltip("in random mode, the percentage of the grid to fill")]
|
|
|
|
|
[MMEnumCondition("GenerateMethod", (int)MMTilemapGenerator.GenerateMethods.Random)]
|
|
|
|
|
public int RandomFillPercentage = 50;
|
|
|
|
|
|
|
|
|
|
// random walk ground
|
|
|
|
|
/// in random walk ground mode,the minimum height difference between two steps
|
|
|
|
|
[Tooltip("in random walk ground mode,the minimum height difference between two steps")]
|
|
|
|
|
[MMEnumCondition("GenerateMethod", (int)MMTilemapGenerator.GenerateMethods.RandomWalkGround)]
|
|
|
|
|
public int RandomWalkGroundMinHeightDifference = 1;
|
|
|
|
|
/// in random walk ground mode,the maximum height difference between two steps
|
|
|
|
|
[Tooltip("in random walk ground mode,the maximum height difference between two steps")]
|
|
|
|
|
[MMEnumCondition("GenerateMethod", (int)MMTilemapGenerator.GenerateMethods.RandomWalkGround)]
|
|
|
|
|
public int RandomWalkGroundMaxHeightDifference = 3;
|
|
|
|
|
/// in random walk ground mode, the minimum distance that should remain flat
|
|
|
|
|
[Tooltip("in random walk ground mode, the minimum distance that should remain flat")]
|
|
|
|
|
[MMEnumCondition("GenerateMethod", (int)MMTilemapGenerator.GenerateMethods.RandomWalkGround)]
|
|
|
|
|
public int RandomWalkGroundMinFlatDistance = 1;
|
|
|
|
|
/// in random walk ground mode, the maximum distance that should remain flat
|
|
|
|
|
[Tooltip("in random walk ground mode, the maximum distance that should remain flat")]
|
|
|
|
|
[MMEnumCondition("GenerateMethod", (int)MMTilemapGenerator.GenerateMethods.RandomWalkGround)]
|
|
|
|
|
public int RandomWalkGroundMaxFlatDistance = 3;
|
|
|
|
|
/// in random walk ground mode, the maximum height of the tallest platfrom, from the bottom of the grid
|
|
|
|
|
[Tooltip("in random walk ground mode, the maximum height of the tallest platfrom, from the bottom of the grid")]
|
|
|
|
|
[MMEnumCondition("GenerateMethod", (int)MMTilemapGenerator.GenerateMethods.RandomWalkGround)]
|
|
|
|
|
public int RandomWalkGroundMaxHeight = 3;
|
|
|
|
|
|
|
|
|
|
// random walk
|
|
|
|
|
/// in random walk mode, the percentage of the map the walker should try filling
|
|
|
|
|
[Tooltip("in random walk mode, the percentage of the map the walker should try filling")]
|
|
|
|
|
[MMEnumCondition("GenerateMethod", (int)MMTilemapGenerator.GenerateMethods.RandomWalk)]
|
|
|
|
|
public int RandomWalkPercent = 50;
|
|
|
|
|
/// in random walk mode,the point at which the walker starts, in grid coordinates
|
|
|
|
|
[Tooltip("in random walk mode,the point at which the walker starts, in grid coordinates")]
|
|
|
|
|
[MMEnumCondition("GenerateMethod", (int)MMTilemapGenerator.GenerateMethods.RandomWalk)]
|
|
|
|
|
public Vector2Int RandomWalkStartingPoint = Vector2Int.zero;
|
|
|
|
|
/// in random walk mode, the max amount of iterations to run the random on
|
|
|
|
|
[Tooltip("in random walk mode, the max amount of iterations to run the random on")]
|
|
|
|
|
[MMEnumCondition("GenerateMethod", (int)MMTilemapGenerator.GenerateMethods.RandomWalk)]
|
|
|
|
|
public int RandomWalkMaxIterations = 1500;
|
|
|
|
|
|
|
|
|
|
// random walk avoider
|
|
|
|
|
/// in random walk avoider mode, the percentage of the grid the walker should try filling
|
|
|
|
|
[Tooltip("in random walk avoider mode, the percentage of the grid the walker should try filling")]
|
|
|
|
|
[MMEnumCondition("GenerateMethod", (int)MMTilemapGenerator.GenerateMethods.RandomWalkAvoider)]
|
|
|
|
|
public int RandomWalkAvoiderPercent = 50;
|
|
|
|
|
/// in random walk avoider mode, the point in grid units at which the walker starts
|
|
|
|
|
[Tooltip("in random walk avoider mode, the point in grid units at which the walker starts")]
|
|
|
|
|
[MMEnumCondition("GenerateMethod", (int)MMTilemapGenerator.GenerateMethods.RandomWalkAvoider)]
|
|
|
|
|
public Vector2Int RandomWalkAvoiderStartingPoint = Vector2Int.zero;
|
|
|
|
|
/// in random walk avoider mode, the tilemap containing the data the walker will try to avoid
|
|
|
|
|
[Tooltip("in random walk avoider mode, the tilemap containing the data the walker will try to avoid")]
|
|
|
|
|
[MMEnumCondition("GenerateMethod", (int)MMTilemapGenerator.GenerateMethods.RandomWalkAvoider)]
|
|
|
|
|
public Tilemap RandomWalkAvoiderObstaclesTilemap;
|
|
|
|
|
/// in random walk avoider mode,the distance at which the walker should try to stay away from obstacles
|
|
|
|
|
[Tooltip("in random walk avoider mode,the distance at which the walker should try to stay away from obstacles")]
|
|
|
|
|
[MMEnumCondition("GenerateMethod", (int)MMTilemapGenerator.GenerateMethods.RandomWalkAvoider)]
|
|
|
|
|
public int RandomWalkAvoiderObstaclesDistance = 1;
|
|
|
|
|
/// in random walk avoider mode,the max amount of iterations this algorithm will iterate on
|
|
|
|
|
[Tooltip("in random walk avoider mode,the max amount of iterations this algorithm will iterate on")]
|
|
|
|
|
[MMEnumCondition("GenerateMethod", (int)MMTilemapGenerator.GenerateMethods.RandomWalkAvoider)]
|
|
|
|
|
public int RandomWalkAvoiderMaxIterations = 100;
|
|
|
|
|
|
|
|
|
|
// path
|
|
|
|
|
/// in path mode, the start position of the path
|
|
|
|
|
[Tooltip("in path mode, the start position of the path")]
|
|
|
|
|
[MMEnumCondition("GenerateMethod", (int) MMTilemapGenerator.GenerateMethods.Path)]
|
|
|
|
|
public Vector2Int PathStartPosition = Vector2Int.zero;
|
|
|
|
|
/// in path mode, the direction the path should follow
|
|
|
|
|
[Tooltip("in path mode, the direction the path should follow")]
|
|
|
|
|
[MMEnumCondition("GenerateMethod", (int) MMTilemapGenerator.GenerateMethods.Path)]
|
|
|
|
|
public MMGridGeneratorPath.Directions PathDirection = MMGridGeneratorPath.Directions.BottomToTop;
|
|
|
|
|
/// in path mode, the minimum width of the path
|
|
|
|
|
[Tooltip("in path mode, the minimum width of the path")]
|
|
|
|
|
[MMEnumCondition("GenerateMethod", (int) MMTilemapGenerator.GenerateMethods.Path)]
|
|
|
|
|
public int PathMinWidth = 2;
|
|
|
|
|
/// in path mode, the maximum width of the path
|
|
|
|
|
[Tooltip("in path mode, the maximum width of the path")]
|
|
|
|
|
[MMEnumCondition("GenerateMethod", (int) MMTilemapGenerator.GenerateMethods.Path)]
|
|
|
|
|
public int PathMaxWidth = 4;
|
|
|
|
|
/// in path mode, the maximum number of units the path can change direction
|
|
|
|
|
[Tooltip("in path mode, the maximum number of units the path can change direction")]
|
|
|
|
|
[MMEnumCondition("GenerateMethod", (int) MMTilemapGenerator.GenerateMethods.Path)]
|
|
|
|
|
public int PathDirectionChangeDistance = 2;
|
|
|
|
|
/// in path mode, the chance (in percent) for the path to change width at every step
|
|
|
|
|
[Tooltip("in path mode, the chance (in percent) for the path to change width at every step")]
|
|
|
|
|
[MMEnumCondition("GenerateMethod", (int) MMTilemapGenerator.GenerateMethods.Path)]
|
|
|
|
|
public int PathWidthChangePercentage = 50;
|
|
|
|
|
/// in path mode, the chance percentage that the path will take a new direction
|
|
|
|
|
[Tooltip("in path mode, the chance percentage that the path will take a new direction")]
|
|
|
|
|
[MMEnumCondition("GenerateMethod", (int) MMTilemapGenerator.GenerateMethods.Path)]
|
|
|
|
|
public int PathDirectionChangePercentage = 50;
|
|
|
|
|
|
|
|
|
|
// copy
|
|
|
|
|
/// in copy mode, the tilemap to copy
|
|
|
|
|
[Tooltip("in copy mode, the tilemap to copy")]
|
|
|
|
|
[MMEnumCondition("GenerateMethod", (int) MMTilemapGenerator.GenerateMethods.Copy)]
|
|
|
|
|
public Tilemap CopyTilemap;
|
|
|
|
|
|
|
|
|
|
[Header("Bounds")]
|
|
|
|
|
/// whether or not to force a wall on the grid's top
|
|
|
|
|
[Tooltip("whether or not to force a wall on the grid's top")]
|
|
|
|
|
public bool BoundsTop = false;
|
|
|
|
|
/// whether or not to force a wall on the grid's bottom
|
|
|
|
|
[Tooltip("whether or not to force a wall on the grid's bottom")]
|
|
|
|
|
public bool BoundsBottom = false;
|
|
|
|
|
/// whether or not to force a wall on the grid's left
|
|
|
|
|
[Tooltip("whether or not to force a wall on the grid's left")]
|
|
|
|
|
public bool BoundsLeft = false;
|
|
|
|
|
/// whether or not to force a wall on the grid's right
|
|
|
|
|
[Tooltip("whether or not to force a wall on the grid's right")]
|
|
|
|
|
public bool BoundsRight = false;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// A struct used to store safe spots dimensions
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Serializable]
|
|
|
|
|
public struct MMTilemapGeneratorLayerSafeSpot
|
|
|
|
|
{
|
|
|
|
|
public Vector2Int Start;
|
|
|
|
|
public Vector2Int End;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Header("Safe Spots")]
|
|
|
|
|
/// a list of "safe spots" : defined by their start and end coordinates, these areas will be left empty
|
|
|
|
|
[Tooltip("a list of 'safe spots' : defined by their start and end coordinates, these areas will be left empty")]
|
|
|
|
|
public List<MMTilemapGeneratorLayerSafeSpot> SafeSpots;
|
|
|
|
|
|
|
|
|
|
[HideInInspector]
|
|
|
|
|
/// this is only used to initialize the default values in the inspector
|
|
|
|
|
public bool Initialized = false;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// This method will set default values, because Unity.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public virtual void SetDefaults()
|
|
|
|
|
{
|
|
|
|
|
if (!Initialized)
|
|
|
|
|
{
|
|
|
|
|
GridWidth = 50;
|
|
|
|
|
GridHeight = 50;
|
|
|
|
|
GenerateMethod = MMTilemapGenerator.GenerateMethods.Perlin;
|
|
|
|
|
RandomizeSeed = true;
|
|
|
|
|
DoNotUseGlobalSeed = false;
|
|
|
|
|
FusionMode = FusionModes.Normal;
|
|
|
|
|
Seed = 123456789;
|
|
|
|
|
Smooth = false;
|
|
|
|
|
InvertGrid = false;
|
|
|
|
|
FullGenerationFilled = true;
|
|
|
|
|
RandomFillPercentage = 50;
|
|
|
|
|
RandomWalkGroundMinHeightDifference = 1;
|
|
|
|
|
RandomWalkGroundMaxHeightDifference = 3;
|
|
|
|
|
RandomWalkGroundMinFlatDistance = 1;
|
|
|
|
|
RandomWalkGroundMaxFlatDistance = 3;
|
|
|
|
|
RandomWalkGroundMaxHeight = 8;
|
|
|
|
|
RandomWalkPercent = 50;
|
|
|
|
|
RandomWalkStartingPoint = Vector2Int.zero;
|
|
|
|
|
RandomWalkMaxIterations = 1500;
|
|
|
|
|
PathMinWidth = 2;
|
|
|
|
|
PathMaxWidth = 4;
|
|
|
|
|
PathDirectionChangeDistance = 2;
|
|
|
|
|
PathWidthChangePercentage = 50;
|
|
|
|
|
PathDirectionChangePercentage = 50;
|
|
|
|
|
RandomWalkAvoiderPercent = 50;
|
|
|
|
|
RandomWalkAvoiderStartingPoint = Vector2Int.zero;
|
|
|
|
|
RandomWalkAvoiderObstaclesTilemap = null;
|
|
|
|
|
RandomWalkAvoiderObstaclesDistance = 1;
|
|
|
|
|
RandomWalkAvoiderMaxIterations = 100;
|
|
|
|
|
BoundsTop = false;
|
|
|
|
|
BoundsBottom = false;
|
|
|
|
|
BoundsLeft = false;
|
|
|
|
|
BoundsRight = false;
|
|
|
|
|
PathStartPosition = Vector2Int.zero;
|
|
|
|
|
PathDirection = MMGridGeneratorPath.Directions.BottomToTop;
|
|
|
|
|
Initialized = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|