Insanely huge initial commit

This commit is contained in:
2026-02-21 17:04:05 -08:00
parent 9cdd36191a
commit 613d75914a
22525 changed files with 4035207 additions and 0 deletions

View File

@@ -0,0 +1,227 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection.Emit;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Tilemaps;
using Random = UnityEngine.Random;
namespace MoreMountains.Tools
{
/// <summary>
/// This class will fill a tilemap with the data generated by the combination of its layers
/// </summary>
[ExecuteAlways]
public class MMTilemapGenerator : MonoBehaviour
{
[Header("Grid")]
/// The width of the grid, in cells
[Tooltip("The width of the grid, in cells")]
[MMVector("Min","Max")]
public Vector2Int GridWidth = new Vector2Int(50,50);
/// the height of the grid, in cells
[Tooltip("the height of the grid, in cells")]
[MMVector("Min","Max")]
public Vector2Int GridHeight = new Vector2Int(50,50);
[Header("Data")]
/// the list of layers that will be used to generate the tilemap
[Tooltip("the list of layers that will be used to generate the tilemap")]
public MMTilemapGeneratorLayerList Layers;
/// a value between 0 and 1 that will be used by all layers as their random seed. If you generate another map using the same seed, it'll look the same
[Tooltip("a value between 0 and 1 that will be used by all layers as their random seed. If you generate another map using the same seed, it'll look the same")]
public int GlobalSeed = 0;
/// whether or not to randomize the global seed every time a new map is generated
[Tooltip("whether or not to randomize the global seed every time a new map is generated")]
public bool RandomizeGlobalSeed = true;
[Header("Slow Render")]
/// turning this to true will (at runtime only) draw the map progressively. This is really just for fun.
[Tooltip("turning this to true will (at runtime only) draw the map progressively. This is really just for fun.")]
public bool SlowRender = false;
/// the duration of the slow render, in seconds
[Tooltip("the duration of the slow render, in seconds")]
public float SlowRenderDuration = 1f;
/// the tween to use for the slow render
[Tooltip("the tween to use for the slow render")]
public MMTweenType SlowRenderTweenType = new MMTweenType(MMTween.MMTweenCurve.EaseInOutCubic);
protected int[,] _grid;
protected int _width;
protected int _height;
/// <summary>
/// the possible methods that can be used to generate a random grid
/// </summary>
public enum GenerateMethods
{
Full,
Perlin,
PerlinGround,
Random,
RandomWalk,
RandomWalkAvoider,
RandomWalkGround,
Path,
Copy
}
/// <summary>
/// Generates and renders every layer in the data stack
/// </summary>
public virtual void Generate()
{
Random.InitState((int)System.DateTime.Now.Ticks);
if (RandomizeGlobalSeed) { GlobalSeed = Mathf.Abs(Random.Range(int.MinValue, int.MaxValue)); }
foreach (MMTilemapGeneratorLayer layer in Layers)
{
GenerateLayer(layer);
}
}
/// <summary>
/// On reset, we initialize our list
/// </summary>
void Reset()
{
Layers = new MMTilemapGeneratorLayerList(){
new MMTilemapGeneratorLayer()
};
}
/// <summary>
/// Generates a layer grid, and renders it
/// </summary>
/// <param name="layer"></param>
protected virtual void GenerateLayer(MMTilemapGeneratorLayer layer)
{
if (!layer.Active)
{
return;
}
if (layer.TargetTilemap == null) { Debug.LogError("Tilemap Generator : you need to specify a Target Tilemap to paint on."); }
if (layer.Tile == null) { Debug.LogError("Tilemap Generator : you need to specify a Tile to paint with."); }
if (layer.GridWidth == 0) { Debug.LogError("Tilemap Generator : grid width can't be 0."); }
if (layer.GridHeight == 0) { Debug.LogError("Tilemap Generator : grid height can't be 0."); }
float seedFloat = 0f;
float layerSeedFloat = 0f;
float globalSeedFloat = 0f;
UnityEngine.Random.InitState(GlobalSeed);
int width = layer.OverrideGridSize ? layer.GridWidth : UnityEngine.Random.Range(GridWidth.x, GridWidth.y);
int height = layer.OverrideGridSize ? layer.GridHeight : UnityEngine.Random.Range(GridHeight.x, GridHeight.y);
globalSeedFloat = UnityEngine.Random.value;
// random outside of the global seed
if (layer.DoNotUseGlobalSeed)
{
Random.InitState((int)System.DateTime.Now.Ticks);
if (layer.RandomizeSeed)
{
layer.Seed = Mathf.Abs(Random.Range(int.MinValue, int.MaxValue));
}
UnityEngine.Random.InitState(layer.Seed);
layerSeedFloat = UnityEngine.Random.value;
}
int seed = layer.DoNotUseGlobalSeed ? layer.Seed : GlobalSeed;
seedFloat = layer.DoNotUseGlobalSeed ? layerSeedFloat : globalSeedFloat;
switch (layer.GenerateMethod)
{
case GenerateMethods.Full:
_grid = MMGridGeneratorFull.Generate(width, height, layer.FullGenerationFilled);
layer.Grid = _grid;
break;
case GenerateMethods.Perlin:
_grid = MMGridGeneratorPerlinNoise.Generate(width, height, seedFloat);
layer.Grid = _grid;
break;
case GenerateMethods.PerlinGround:
_grid = MMGridGeneratorPerlinNoiseGround.Generate(width, height, seedFloat);
layer.Grid = _grid;
break;
case GenerateMethods.Random:
_grid = MMGridGeneratorRandom.Generate(width, height, seed, layer.RandomFillPercentage);
layer.Grid = _grid;
break;
case GenerateMethods.RandomWalk:
_grid = MMGridGeneratorRandomWalk.Generate(width, height, seed, layer.RandomWalkPercent, layer.RandomWalkStartingPoint, layer.RandomWalkMaxIterations);
layer.Grid = _grid;
break;
case GenerateMethods.RandomWalkAvoider:
int[,] obstacleGrid = MMGridGenerator.TilemapToGrid(layer.RandomWalkAvoiderObstaclesTilemap, width, height);
_grid = MMGridGeneratorRandomWalkAvoider.Generate(width, height, seed, layer.RandomWalkAvoiderPercent, layer.RandomWalkAvoiderStartingPoint, obstacleGrid, layer.RandomWalkAvoiderObstaclesDistance, layer.RandomWalkAvoiderMaxIterations);
layer.Grid = _grid;
break;
case GenerateMethods.RandomWalkGround:
_grid = MMGridGeneratorRandomWalkGround.Generate(width, height, seed,
layer.RandomWalkGroundMinHeightDifference, layer.RandomWalkGroundMaxHeightDifference,
layer.RandomWalkGroundMinFlatDistance, layer.RandomWalkGroundMaxFlatDistance, layer.RandomWalkGroundMaxHeight);
layer.Grid = _grid;
break;
case GenerateMethods.Path:
_grid = MMGridGeneratorPath.Generate(width, height, seed, layer.PathDirection, layer.PathStartPosition, layer.PathMinWidth,
layer.PathMaxWidth, layer.PathDirectionChangeDistance, layer.PathWidthChangePercentage,
layer.PathDirectionChangePercentage);
layer.Grid = _grid;
break;
case GenerateMethods.Copy:
layer.TargetTilemap.ClearAllTiles();
DelayedCopy(layer);
break;
}
if (layer.Smooth) { _grid = MMGridGenerator.SmoothenGrid(_grid); }
if (layer.InvertGrid) { _grid = MMGridGenerator.InvertGrid(_grid); }
_grid = MMGridGenerator.BindGrid(_grid, layer.BoundsTop, layer.BoundsBottom, layer.BoundsLeft, layer.BoundsRight);
_grid = MMGridGenerator.ApplySafeSpots(_grid, layer.SafeSpots);
RenderGrid(layer);
}
/// <summary>
/// Copies the tilemap's content after a delay because Unity.
/// </summary>
/// <param name="layer"></param>
async static void DelayedCopy(MMTilemapGeneratorLayer layer)
{
await Task.Delay(500);
MMTilemapShadow.Copy(layer.CopyTilemap, layer.TargetTilemap);
}
/// <summary>
/// Renders the grid with the selected modes to the specified target tilemap
/// </summary>
/// <param name="layer"></param>
protected virtual void RenderGrid(MMTilemapGeneratorLayer layer)
{
MMTilemapGridRenderer.RenderGrid(_grid, layer, SlowRender, SlowRenderDuration, SlowRenderTweenType,this);
}
/// <summary>
/// Sets default values for all layers
/// </summary>
protected virtual void OnValidate()
{
if ((Layers == null) || (Layers.Count <= 0))
{
return;
}
foreach (MMTilemapGeneratorLayer layer in Layers)
{
layer.SetDefaults();
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1554ad3bc2245e64bbf7cf0a29ed7fa0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,291 @@
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;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 01608833a8be3af4587b87e116bffc68
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: