Added Feel plugin

This commit is contained in:
journaliciouz
2025-12-11 14:49:16 +01:00
parent 97dce4aaf6
commit 1942a531d4
2820 changed files with 257786 additions and 9 deletions

View File

@@ -0,0 +1,96 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
using Random = System.Random;
namespace MoreMountains.Tools
{
/// <summary>
/// A collection of helper methods for interacting with Tilemaps
/// </summary>
public class MMTilemap : MonoBehaviour
{
#if MM_PHYSICS2D
/// <summary>
/// Returns a random world position on the specified tilemap/grid combo, filled or not based on the shouldBeFilled flag
/// </summary>
/// <param name="targetTilemap"></param>
/// <param name="grid"></param>
/// <param name="width"></param>
/// <param name="height"></param>
/// <param name="shouldBeFilled"></param>
/// <param name="maxIterations"></param>
/// <returns></returns>
public static Vector2 GetRandomPosition(Tilemap targetTilemap, Grid grid, int width, int height, bool shouldBeFilled = true, int maxIterations = 1000)
{
int iterationsCount = 0;
Vector3Int randomCoordinate = Vector3Int.zero;
while (iterationsCount < maxIterations)
{
randomCoordinate.x = UnityEngine.Random.Range(0, width);
randomCoordinate.y = UnityEngine.Random.Range(0, height);
randomCoordinate += MMTilemapGridRenderer.ComputeOffset(width-1, height-1);
bool hasTile = targetTilemap.HasTile(randomCoordinate);
if (hasTile == shouldBeFilled)
{
return targetTilemap.CellToWorld(randomCoordinate) + (grid.cellSize / 2);
}
iterationsCount++;
}
return Vector2.zero;
}
/// <summary>
/// Returns a random position on the ground floor of the grid
/// </summary>
/// <param name="targetTilemap"></param>
/// <param name="grid"></param>
/// <param name="width"></param>
/// <param name="height"></param>
/// <param name="startingHeight"></param>
/// <param name="xMin"></param>
/// <param name="xMax"></param>
/// <param name="shouldBeFilled"></param>
/// <param name="maxIterations"></param>
/// <returns></returns>
public static Vector2 GetRandomPositionOnGround(Tilemap targetTilemap, Grid grid, int width, int height, int startingHeight, int xMin, int xMax, bool shouldBeFilled = true, int maxIterations = 1000)
{
int iterationsCount = 0;
Vector3Int randomCoordinate = Vector3Int.zero;
while (iterationsCount < maxIterations)
{
randomCoordinate.x = UnityEngine.Random.Range(xMin, xMax);
randomCoordinate.y = startingHeight;
randomCoordinate += MMTilemapGridRenderer.ComputeOffset(width-1, height-1);
int counter = height;
while (counter > 0)
{
bool hasTile = targetTilemap.HasTile(randomCoordinate);
if (hasTile == shouldBeFilled)
{
randomCoordinate.y++;
return targetTilemap.CellToWorld(randomCoordinate) + (grid.cellSize / 2);
}
randomCoordinate.y--;
counter--;
}
iterationsCount++;
}
return Vector2.zero;
}
#endif
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 71bd7b8dc6ab21844b34803a4084a56e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 183370
packageName: Feel
packageVersion: 5.9.1
assetPath: Assets/Feel/MMTools/Accessories/MMTilemaps/MMTilemap.cs
uploadId: 830868

View File

@@ -0,0 +1,48 @@
using UnityEngine;
using UnityEngine.Tilemaps;
namespace MoreMountains.Tools
{
[AddComponentMenu("More Mountains/Tools/Tilemaps/MM Tilemap Boolean")]
public class MMTilemapBoolean : MonoBehaviour
{
#if MM_PHYSICS2D
public Tilemap TilemapToClean;
[MMInspectorButton("BooleanClean")]
public bool BooleanCleanButton;
protected Tilemap _tilemap;
/// <summary>
/// This method will copy the reference tilemap into the one on this gameobject
/// </summary>
public virtual void BooleanClean()
{
if (TilemapToClean == null)
{
return;
}
_tilemap = this.gameObject.GetComponent<Tilemap>();
// we grab all filled positions from the ref tilemap
foreach (Vector3Int pos in _tilemap.cellBounds.allPositionsWithin)
{
Vector3Int localPlace = new Vector3Int(pos.x, pos.y, pos.z);
if (_tilemap.HasTile(localPlace))
{
if (TilemapToClean.HasTile(localPlace))
{
TilemapToClean.SetTile(localPlace, null);
}
}
}
// we clear our tilemap and resize it
_tilemap.RefreshAllTiles();
}
#endif
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: ed5d5aca24f393844931ca9f8c7e05c8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 183370
packageName: Feel
packageVersion: 5.9.1
assetPath: Assets/Feel/MMTools/Accessories/MMTilemaps/MMTilemapBoolean.cs
uploadId: 830868

View File

@@ -0,0 +1,52 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
namespace MoreMountains.Tools
{
/// <summary>
/// A super simple component you can add to a tilemap to get a button to clean it from all tiles
/// </summary>
public class MMTilemapCleaner : MonoBehaviour
{
/// Debug buttons
[MMInspectorButton("Clean")]
public bool CleanButton;
[MMInspectorButton("CleanAllChildren")]
public bool CleanAllButton;
#if MM_PHYSICS2D
protected Tilemap _tilemap;
protected Tilemap[] _tilemaps;
/// <summary>
/// Cleans all tiles on the corresponding tilemap
/// </summary>
public virtual void Clean()
{
_tilemap = this.gameObject.GetComponent<Tilemap>();
if (_tilemap != null)
{
_tilemap.ClearAllTiles();
}
}
/// <summary>
/// Cleans all tiles on all tilemaps that are set as children of this object
/// </summary>
public virtual void CleanAllChildren()
{
_tilemaps = GetComponentsInChildren<Tilemap>();
foreach (Tilemap tilemap in _tilemaps)
{
tilemap.ClearAllTiles();
}
}
#endif
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 158241bba510d154b9d2e7d7ab8d4fd7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 183370
packageName: Feel
packageVersion: 5.9.1
assetPath: Assets/Feel/MMTools/Accessories/MMTilemaps/MMTilemapCleaner.cs
uploadId: 830868

View File

@@ -0,0 +1,192 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
namespace MoreMountains.Tools
{
public class MMTilemapGridRenderer
{
#if MM_PHYSICS2D
/// <summary>
/// Renders the specified grid on the specified tilemap, with optional slow mode (only works at runtime)
/// </summary>
/// <param name="grid"></param>
/// <param name="tilemap"></param>
/// <param name="tile"></param>
/// <param name="slowRender"></param>
/// <param name="slowRenderDuration"></param>
/// <param name="slowRenderTweenType"></param>
/// <param name="slowRenderSupport"></param>
public static void RenderGrid(int[,] grid, MMTilemapGeneratorLayer layer, bool slowRender = false, float slowRenderDuration = 1f,
MMTweenType slowRenderTweenType = null, MonoBehaviour slowRenderSupport = null)
{
if (layer.FusionMode == MMTilemapGeneratorLayer.FusionModes.Normal)
{
ClearTilemap(layer.TargetTilemap);
}
TileBase tile = layer.Tile;
if (layer.FusionMode == MMTilemapGeneratorLayer.FusionModes.Combine)
{
grid = MMGridGenerator.InvertGrid(grid);
tile = null;
}
if (layer.FusionMode == MMTilemapGeneratorLayer.FusionModes.Subtract)
{
grid = MMGridGenerator.InvertGrid(grid);
}
if (!slowRender || !Application.isPlaying)
{
DrawGrid(grid, layer.TargetTilemap, tile, 0, TotalFilledBlocks(grid));
}
else
{
slowRenderSupport.StartCoroutine(SlowRenderGrid(grid, layer.TargetTilemap, tile, slowRenderDuration, slowRenderTweenType, 60));
}
if (!Application.isPlaying && slowRender)
{
Debug.LogWarning("Rendering maps in SlowRender mode is only supported at runtime.");
}
}
/// <summary>
/// Renders a grid chunk by chunk - runtime only
/// </summary>
/// <param name="grid"></param>
/// <param name="tilemap"></param>
/// <param name="tile"></param>
/// <param name="slowRenderDuration"></param>
/// <param name="slowRenderTweenType"></param>
/// <param name="frameRate"></param>
/// <returns></returns>
public static IEnumerator SlowRenderGrid(int[,] grid, Tilemap tilemap, TileBase tile, float slowRenderDuration, MMTweenType slowRenderTweenType, int frameRate)
{
int totalBlocks = TotalFilledBlocks(grid);
totalBlocks = (totalBlocks == 0) ? 1 : totalBlocks;
frameRate = (frameRate == 0) ? 1 : frameRate;
float refreshFrequency = 1f / frameRate;
float startedAt = Time.unscaledTime;
float lastWaitAt = startedAt;
int drawnBlocks = 0;
int lastIndex = 0;
while (Time.unscaledTime - startedAt < slowRenderDuration)
{
while (Time.unscaledTime - lastWaitAt < refreshFrequency)
{
yield return null;
}
int remainingBlocks = totalBlocks - drawnBlocks;
float elapsedTime = Time.unscaledTime - startedAt;
float remainingTime = slowRenderDuration - elapsedTime;
float normalizedProgress = MMMaths.Remap(elapsedTime, 0f, slowRenderDuration, 0f, 1f);
float curveProgress = MMTween.Tween(normalizedProgress, 0f, 1f, 0f, 1f, slowRenderTweenType);
float ratio = 1 - (normalizedProgress - curveProgress);
int blocksToDraw = Mathf.RoundToInt((remainingBlocks / remainingTime) * refreshFrequency * ratio);
lastIndex = DrawGrid(grid, tilemap, tile, lastIndex, blocksToDraw);
drawnBlocks += blocksToDraw;
lastWaitAt = Time.unscaledTime;
}
DrawGrid(grid, tilemap, tile, lastIndex, totalBlocks - lastIndex);
}
/// <summary>
/// Returns the total amount of filled blocks in a grid
/// </summary>
/// <param name="grid"></param>
/// <returns></returns>
public static int TotalFilledBlocks(int[,] grid)
{
int width = grid.GetUpperBound(0);
int height = grid.GetUpperBound(1);
int totalBlocks = 0;
for (int i = 0; i <= width ; i++)
{
for (int j = 0; j <= height; j++)
{
if (grid[i, j] == 1)
{
totalBlocks++;
}
}
}
return totalBlocks;
}
/// <summary>
/// Draws the specified section of a grid on a target tilemap
/// </summary>
/// <param name="grid"></param>
/// <param name="tilemap"></param>
/// <param name="tile"></param>
/// <param name="startIndex"></param>
/// <param name="numberOfTilesToDraw"></param>
/// <returns></returns>
private static int DrawGrid(int[,] grid, Tilemap tilemap, TileBase tile, int startIndex, int numberOfTilesToDraw)
{
int width = grid.GetUpperBound(0);
int height = grid.GetUpperBound(1);
tilemap.RefreshAllTiles();
int counter = 0;
int drawCount = 0;
for (int i = 0; i <= width ; i++)
{
for (int j = 0; j <= height; j++)
{
if (grid[i, j] == 1)
{
if (counter >= startIndex)
{
Vector3Int tilePosition = new Vector3Int(i, j, 0);
tilePosition += ComputeOffset(width, height);
tilemap.SetTile(tilePosition, tile);
drawCount++;
}
if (drawCount > numberOfTilesToDraw)
{
return counter;
}
counter++;
}
}
}
return counter;
}
/// <summary>
/// Determines the offset to apply to a grid to have it centered
/// </summary>
/// <param name="width"></param>
/// <param name="height"></param>
/// <returns></returns>
public static Vector3Int ComputeOffset(int width, int height)
{
Vector3Int offset = new Vector3Int(width + 2, height + 2, 0);
offset = offset - offset/2;
return -offset;
}
/// <summary>
/// Clears and refreshes an entire tilemap
/// </summary>
/// <param name="tilemap"></param>
public static void ClearTilemap(Tilemap tilemap)
{
tilemap.ClearAllTiles();
tilemap.RefreshAllTiles();
}
#endif
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 2c8fc9be87fcf9f4c99405f32483ccd1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 183370
packageName: Feel
packageVersion: 5.9.1
assetPath: Assets/Feel/MMTools/Accessories/MMTilemaps/MMTilemapGridRenderer.cs
uploadId: 830868

View File

@@ -0,0 +1,86 @@
using UnityEngine;
using System.Collections.Generic;
using UnityEngine.Tilemaps;
namespace MoreMountains.Tools
{
#if MM_PHYSICS2D
/// <summary>
/// A class to put on a tilemap so it acts as a shadow/copy of another reference tilemap.
/// Useful for wall shadows for example.
/// Offsetting the tilemap and changing its sorting order etc is done via the regular components
/// </summary>
[ExecuteAlways]
[AddComponentMenu("More Mountains/Tools/Tilemaps/MM Tilemap Shadow")]
[RequireComponent(typeof(Tilemap))]
public class MMTilemapShadow : MonoBehaviour
{
/// the tilemap to copy
public Tilemap ReferenceTilemap;
[MMInspectorButton("UpdateShadows")]
public bool UpdateShadowButton;
protected Tilemap _tilemap;
/// <summary>
/// This method will copy the reference tilemap into the one on this gameobject
/// </summary>
public virtual void UpdateShadows()
{
if (ReferenceTilemap == null)
{
return;
}
_tilemap = this.gameObject.GetComponent<Tilemap>();
Copy(ReferenceTilemap, _tilemap);
}
/// <summary>
/// Copies the source tilemap on the destination tilemap
/// </summary>
/// <param name="source"></param>
/// <param name="destination"></param>
public static void Copy(Tilemap source, Tilemap destination)
{
source.RefreshAllTiles();
destination.RefreshAllTiles();
List<Vector3Int> referenceTilemapPositions = new List<Vector3Int>();
// we grab all filled positions from the ref tilemap
foreach (Vector3Int pos in source.cellBounds.allPositionsWithin)
{
Vector3Int localPlace = new Vector3Int(pos.x, pos.y, pos.z);
if (source.HasTile(localPlace))
{
referenceTilemapPositions.Add(localPlace);
}
}
// we turn our list into an array
Vector3Int[] positions = new Vector3Int[referenceTilemapPositions.Count];
TileBase[] allTiles = new TileBase[referenceTilemapPositions.Count];
int i = 0;
foreach(Vector3Int tilePosition in referenceTilemapPositions)
{
positions[i] = tilePosition;
allTiles[i] = source.GetTile(tilePosition);
i++;
}
// we clear our tilemap and resize it
destination.ClearAllTiles();
destination.RefreshAllTiles();
destination.size = source.size;
destination.origin = source.origin;
destination.ResizeBounds();
// we feed it our positions
destination.SetTiles(positions, allTiles);
}
}
#endif
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 96fdc4f00baddf6498aa5cfe735a2321
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 183370
packageName: Feel
packageVersion: 5.9.1
assetPath: Assets/Feel/MMTools/Accessories/MMTilemaps/MMTilemapShadow.cs
uploadId: 830868