Initial Commit
This commit is contained in:
commit
ee5c2f922d
2255 changed files with 547750 additions and 0 deletions
8
Assets/Scripts/UI/Tilemap/Brushes/Coordinate Brush.meta
Normal file
8
Assets/Scripts/UI/Tilemap/Brushes/Coordinate Brush.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2787f7307aeaaf348a734c189cdb4676
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 37b07ea36b1cbaa41aeda520548feef2
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 527c1efaf8221b245b125c414bc61c37
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor
|
||||
{
|
||||
[CustomGridBrush(true, false, false, "Coordinate Brush")]
|
||||
public class CoordinateBrush : UnityEditor.Tilemaps.GridBrush {
|
||||
public int z = 0;
|
||||
|
||||
public override void Paint(GridLayout grid, GameObject brushTarget, Vector3Int position)
|
||||
{
|
||||
var zPosition = new Vector3Int(position.x, position.y, z);
|
||||
base.Paint(grid, brushTarget, zPosition);
|
||||
}
|
||||
|
||||
public override void Erase(GridLayout grid, GameObject brushTarget, Vector3Int position)
|
||||
{
|
||||
var zPosition = new Vector3Int(position.x, position.y, z);
|
||||
base.Erase(grid, brushTarget, zPosition);
|
||||
}
|
||||
|
||||
public override void FloodFill(GridLayout grid, GameObject brushTarget, Vector3Int position)
|
||||
{
|
||||
var zPosition = new Vector3Int(position.x, position.y, z);
|
||||
base.FloodFill(grid, brushTarget, zPosition);
|
||||
}
|
||||
|
||||
public override void BoxFill(GridLayout gridLayout, GameObject brushTarget, BoundsInt position)
|
||||
{
|
||||
var zPosition = new Vector3Int(position.x, position.y, z);
|
||||
position.position = zPosition;
|
||||
base.BoxFill(gridLayout, brushTarget, position);
|
||||
}
|
||||
|
||||
[MenuItem("Assets/Create/Coordinate Brush")]
|
||||
public static void CreateBrush()
|
||||
{
|
||||
string path = EditorUtility.SaveFilePanelInProject("Save Coordinate Brush", "New Coordinate Brush", "asset", "Save Coordinate Brush", "Assets");
|
||||
|
||||
if (path == "")
|
||||
return;
|
||||
|
||||
AssetDatabase.CreateAsset(ScriptableObject.CreateInstance<CoordinateBrush>(), path);
|
||||
}
|
||||
}
|
||||
|
||||
[CustomEditor(typeof(CoordinateBrush))]
|
||||
public class CoordinateBrushEditor : UnityEditor.Tilemaps.GridBrushEditor
|
||||
{
|
||||
private CoordinateBrush coordinateBrush { get { return target as CoordinateBrush; } }
|
||||
|
||||
public override void PaintPreview(GridLayout grid, GameObject brushTarget, Vector3Int position)
|
||||
{
|
||||
var zPosition = new Vector3Int(position.x, position.y, coordinateBrush.z);
|
||||
base.PaintPreview(grid, brushTarget, zPosition);
|
||||
}
|
||||
|
||||
public override void OnPaintSceneGUI(GridLayout grid, GameObject brushTarget, BoundsInt position, GridBrushBase.Tool tool, bool executing)
|
||||
{
|
||||
base.OnPaintSceneGUI(grid, brushTarget, position, tool, executing);
|
||||
if (coordinateBrush.z != 0)
|
||||
{
|
||||
var zPosition = new Vector3Int(position.min.x, position.min.y, coordinateBrush.z);
|
||||
BoundsInt newPosition = new BoundsInt(zPosition, position.size);
|
||||
Vector3[] cellLocals = new Vector3[]
|
||||
{
|
||||
grid.CellToLocal(new Vector3Int(newPosition.min.x, newPosition.min.y, newPosition.min.z)),
|
||||
grid.CellToLocal(new Vector3Int(newPosition.max.x, newPosition.min.y, newPosition.min.z)),
|
||||
grid.CellToLocal(new Vector3Int(newPosition.max.x, newPosition.max.y, newPosition.min.z)),
|
||||
grid.CellToLocal(new Vector3Int(newPosition.min.x, newPosition.max.y, newPosition.min.z))
|
||||
};
|
||||
|
||||
Handles.color = Color.blue;
|
||||
int i = 0;
|
||||
for (int j = cellLocals.Length - 1; i < cellLocals.Length; j = i++)
|
||||
{
|
||||
Handles.DrawLine(cellLocals[j], cellLocals[i]);
|
||||
}
|
||||
}
|
||||
|
||||
var labelText = "Pos: " + new Vector3Int(position.x, position.y, coordinateBrush.z);
|
||||
if (position.size.x > 1 || position.size.y > 1) {
|
||||
labelText += " Size: " + new Vector2Int(position.size.x, position.size.y);
|
||||
}
|
||||
|
||||
Handles.Label(grid.CellToWorld(new Vector3Int(position.x, position.y, coordinateBrush.z)), labelText);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d283e353fe1f4c34f8ac458281740fb4
|
||||
timeCreated: 1499149770
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Scripts/UI/Tilemap/Brushes/GameObject Brush.meta
Normal file
8
Assets/Scripts/UI/Tilemap/Brushes/GameObject Brush.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 381ad9fa709caf04197e5a8b24a7d6b2
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
fileFormatVersion: 2
|
||||
guid: becdef7ff3038f844a171e247f575688
|
||||
folderAsset: yes
|
||||
timeCreated: 1501789865
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 62c56be364c00f14ba85c5d3f280447c
|
||||
folderAsset: yes
|
||||
timeCreated: 1501789982
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,489 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Tilemaps;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace UnityEditor
|
||||
{
|
||||
[CustomGridBrush(true, false, false, "GameObject Brush")]
|
||||
public class GameObjectBrush : GridBrushBase
|
||||
{
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
private BrushCell[] m_Cells;
|
||||
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
private Vector3Int m_Size;
|
||||
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
private Vector3Int m_Pivot;
|
||||
|
||||
public Vector3Int size { get { return m_Size; } set { m_Size = value; SizeUpdated(); } }
|
||||
public Vector3Int pivot { get { return m_Pivot; } set { m_Pivot = value; } }
|
||||
public BrushCell[] cells { get { return m_Cells; } }
|
||||
public int cellCount { get { return m_Cells != null ? m_Cells.Length : 0; } }
|
||||
|
||||
public GameObjectBrush()
|
||||
{
|
||||
Init(Vector3Int.one, Vector3Int.zero);
|
||||
SizeUpdated();
|
||||
}
|
||||
|
||||
public void Init(Vector3Int size)
|
||||
{
|
||||
Init(size, Vector3Int.zero);
|
||||
SizeUpdated();
|
||||
}
|
||||
|
||||
public void Init(Vector3Int size, Vector3Int pivot)
|
||||
{
|
||||
m_Size = size;
|
||||
m_Pivot = pivot;
|
||||
SizeUpdated();
|
||||
}
|
||||
|
||||
public override void Paint(GridLayout gridLayout, GameObject brushTarget, Vector3Int position)
|
||||
{
|
||||
// Do not allow editing palettes
|
||||
if (brushTarget.layer == 31)
|
||||
return;
|
||||
|
||||
Vector3Int min = position - pivot;
|
||||
BoundsInt bounds = new BoundsInt(min, m_Size);
|
||||
BoxFill(gridLayout, brushTarget, bounds);
|
||||
}
|
||||
|
||||
private void PaintCell(GridLayout grid, Vector3Int position, Transform parent, BrushCell cell)
|
||||
{
|
||||
if (cell.gameObject != null)
|
||||
{
|
||||
SetSceneCell(grid, parent, position, cell.gameObject, cell.offset, cell.scale, cell.orientation);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Erase(GridLayout gridLayout, GameObject brushTarget, Vector3Int position)
|
||||
{
|
||||
// Do not allow editing palettes
|
||||
if (brushTarget.layer == 31)
|
||||
return;
|
||||
|
||||
Vector3Int min = position - pivot;
|
||||
BoundsInt bounds = new BoundsInt(min, m_Size);
|
||||
BoxErase(gridLayout, brushTarget, bounds);
|
||||
}
|
||||
|
||||
private void EraseCell(GridLayout grid, Vector3Int position, Transform parent)
|
||||
{
|
||||
ClearSceneCell(grid, parent, position);
|
||||
}
|
||||
|
||||
public override void BoxFill(GridLayout gridLayout, GameObject brushTarget, BoundsInt position)
|
||||
{
|
||||
// Do not allow editing palettes
|
||||
if (brushTarget.layer == 31)
|
||||
return;
|
||||
|
||||
if (brushTarget == null)
|
||||
return;
|
||||
|
||||
foreach (Vector3Int location in position.allPositionsWithin)
|
||||
{
|
||||
Vector3Int local = location - position.min;
|
||||
BrushCell cell = m_Cells[GetCellIndexWrapAround(local.x, local.y, local.z)];
|
||||
PaintCell(gridLayout, location, brushTarget.transform, cell);
|
||||
}
|
||||
}
|
||||
|
||||
public override void BoxErase(GridLayout gridLayout, GameObject brushTarget, BoundsInt position)
|
||||
{
|
||||
// Do not allow editing palettes
|
||||
if (brushTarget.layer == 31)
|
||||
return;
|
||||
|
||||
if (brushTarget == null)
|
||||
return;
|
||||
|
||||
foreach (Vector3Int location in position.allPositionsWithin)
|
||||
{
|
||||
EraseCell(gridLayout, location, brushTarget.transform);
|
||||
}
|
||||
}
|
||||
|
||||
public override void FloodFill(GridLayout gridLayout, GameObject brushTarget, Vector3Int position)
|
||||
{
|
||||
Debug.LogWarning("FloodFill not supported");
|
||||
}
|
||||
|
||||
public override void Rotate(RotationDirection direction, Grid.CellLayout layout)
|
||||
{
|
||||
Vector3Int oldSize = m_Size;
|
||||
BrushCell[] oldCells = m_Cells.Clone() as BrushCell[];
|
||||
size = new Vector3Int(oldSize.y, oldSize.x, oldSize.z);
|
||||
BoundsInt oldBounds = new BoundsInt(Vector3Int.zero, oldSize);
|
||||
|
||||
foreach (Vector3Int oldPos in oldBounds.allPositionsWithin)
|
||||
{
|
||||
int newX = direction == RotationDirection.Clockwise ? oldSize.y - oldPos.y - 1 : oldPos.y;
|
||||
int newY = direction == RotationDirection.Clockwise ? oldPos.x : oldSize.x - oldPos.x - 1;
|
||||
int toIndex = GetCellIndex(newX, newY, oldPos.z);
|
||||
int fromIndex = GetCellIndex(oldPos.x, oldPos.y, oldPos.z, oldSize.x, oldSize.y, oldSize.z);
|
||||
m_Cells[toIndex] = oldCells[fromIndex];
|
||||
}
|
||||
|
||||
int newPivotX = direction == RotationDirection.Clockwise ? oldSize.y - pivot.y - 1 : pivot.y;
|
||||
int newPivotY = direction == RotationDirection.Clockwise ? pivot.x : oldSize.x - pivot.x - 1;
|
||||
pivot = new Vector3Int(newPivotX, newPivotY, pivot.z);
|
||||
|
||||
Matrix4x4 rotation = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0f, 0f, direction == RotationDirection.Clockwise ? 90f : -90f), Vector3.one);
|
||||
Quaternion orientation = Quaternion.Euler(0f, 0f, direction == RotationDirection.Clockwise ? 90f : -90f);
|
||||
foreach (BrushCell cell in m_Cells)
|
||||
{
|
||||
cell.offset = rotation * cell.offset;
|
||||
cell.orientation = cell.orientation * orientation;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Flip(FlipAxis flip, Grid.CellLayout layout)
|
||||
{
|
||||
if (flip == FlipAxis.X)
|
||||
FlipX();
|
||||
else
|
||||
FlipY();
|
||||
}
|
||||
|
||||
public override void Pick(GridLayout gridLayout, GameObject brushTarget, BoundsInt position, Vector3Int pickStart)
|
||||
{
|
||||
// Do not allow editing palettes
|
||||
if (brushTarget.layer == 31)
|
||||
return;
|
||||
|
||||
Reset();
|
||||
UpdateSizeAndPivot(new Vector3Int(position.size.x, position.size.y, 1), new Vector3Int(pickStart.x, pickStart.y, 0));
|
||||
|
||||
foreach (Vector3Int pos in position.allPositionsWithin)
|
||||
{
|
||||
Vector3Int brushPosition = new Vector3Int(pos.x - position.x, pos.y - position.y, 0);
|
||||
PickCell(pos, brushPosition, gridLayout, brushTarget.transform);
|
||||
}
|
||||
}
|
||||
|
||||
private void PickCell(Vector3Int position, Vector3Int brushPosition, GridLayout grid, Transform parent)
|
||||
{
|
||||
if (parent != null)
|
||||
{
|
||||
Vector3 cellCenter = grid.LocalToWorld(grid.CellToLocalInterpolated(position + new Vector3(.5f, .5f, .5f)));
|
||||
GameObject go = GetObjectInCell(grid, parent, position);
|
||||
|
||||
if (go != null)
|
||||
{
|
||||
Object prefab = PrefabUtility.GetCorrespondingObjectFromSource(go);
|
||||
|
||||
if (prefab)
|
||||
{
|
||||
SetGameObject(brushPosition, (GameObject) prefab);
|
||||
}
|
||||
else
|
||||
{
|
||||
GameObject newInstance = Instantiate(go);
|
||||
newInstance.hideFlags = HideFlags.HideAndDontSave;
|
||||
SetGameObject(brushPosition, newInstance);
|
||||
}
|
||||
|
||||
SetOffset(brushPosition, go.transform.position - cellCenter);
|
||||
SetScale(brushPosition, go.transform.localScale);
|
||||
SetOrientation(brushPosition, go.transform.localRotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void MoveStart(GridLayout gridLayout, GameObject brushTarget, BoundsInt position)
|
||||
{
|
||||
// Do not allow editing palettes
|
||||
if (brushTarget.layer == 31)
|
||||
return;
|
||||
|
||||
Reset();
|
||||
UpdateSizeAndPivot(new Vector3Int(position.size.x, position.size.y, 1), Vector3Int.zero);
|
||||
|
||||
if (brushTarget != null)
|
||||
{
|
||||
foreach (Vector3Int pos in position.allPositionsWithin)
|
||||
{
|
||||
Vector3Int brushPosition = new Vector3Int(pos.x - position.x, pos.y - position.y, 0);
|
||||
PickCell(pos, brushPosition, gridLayout, brushTarget.transform);
|
||||
ClearSceneCell(gridLayout, brushTarget.transform, brushPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void MoveEnd(GridLayout gridLayout, GameObject brushTarget, BoundsInt position)
|
||||
{
|
||||
// Do not allow editing palettes
|
||||
if (brushTarget.layer == 31)
|
||||
return;
|
||||
|
||||
Paint(gridLayout, brushTarget, position.min);
|
||||
Reset();
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
foreach (var cell in m_Cells)
|
||||
{
|
||||
if (cell.gameObject != null && !EditorUtility.IsPersistent(cell.gameObject))
|
||||
{
|
||||
DestroyImmediate(cell.gameObject);
|
||||
}
|
||||
}
|
||||
UpdateSizeAndPivot(Vector3Int.one, Vector3Int.zero);
|
||||
}
|
||||
|
||||
private void FlipX()
|
||||
{
|
||||
BrushCell[] oldCells = m_Cells.Clone() as BrushCell[];
|
||||
BoundsInt oldBounds = new BoundsInt(Vector3Int.zero, m_Size);
|
||||
|
||||
foreach (Vector3Int oldPos in oldBounds.allPositionsWithin)
|
||||
{
|
||||
int newX = m_Size.x - oldPos.x - 1;
|
||||
int toIndex = GetCellIndex(newX, oldPos.y, oldPos.z);
|
||||
int fromIndex = GetCellIndex(oldPos);
|
||||
m_Cells[toIndex] = oldCells[fromIndex];
|
||||
}
|
||||
|
||||
int newPivotX = m_Size.x - pivot.x - 1;
|
||||
pivot = new Vector3Int(newPivotX, pivot.y, pivot.z);
|
||||
Matrix4x4 flip = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(-1f, 1f, 1f));
|
||||
Quaternion orientation = Quaternion.Euler(0f, 0f, -180f);
|
||||
|
||||
foreach (BrushCell cell in m_Cells)
|
||||
{
|
||||
Vector3 oldOffset = cell.offset;
|
||||
cell.offset = flip * oldOffset;
|
||||
cell.orientation = cell.orientation*orientation;
|
||||
}
|
||||
}
|
||||
|
||||
private void FlipY()
|
||||
{
|
||||
BrushCell[] oldCells = m_Cells.Clone() as BrushCell[];
|
||||
BoundsInt oldBounds = new BoundsInt(Vector3Int.zero, m_Size);
|
||||
|
||||
foreach (Vector3Int oldPos in oldBounds.allPositionsWithin)
|
||||
{
|
||||
int newY = m_Size.y - oldPos.y - 1;
|
||||
int toIndex = GetCellIndex(oldPos.x, newY, oldPos.z);
|
||||
int fromIndex = GetCellIndex(oldPos);
|
||||
m_Cells[toIndex] = oldCells[fromIndex];
|
||||
}
|
||||
|
||||
int newPivotY = m_Size.y - pivot.y - 1;
|
||||
pivot = new Vector3Int(pivot.x, newPivotY, pivot.z);
|
||||
Matrix4x4 flip = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(1f, -1f, 1f));
|
||||
Quaternion orientation = Quaternion.Euler(0f, 0f, -180f);
|
||||
foreach (BrushCell cell in m_Cells)
|
||||
{
|
||||
Vector3 oldOffset = cell.offset;
|
||||
cell.offset = flip * oldOffset;
|
||||
cell.orientation = cell.orientation * orientation;
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateSizeAndPivot(Vector3Int size, Vector3Int pivot)
|
||||
{
|
||||
m_Size = size;
|
||||
m_Pivot = pivot;
|
||||
SizeUpdated();
|
||||
}
|
||||
|
||||
public void SetGameObject(Vector3Int position, GameObject go)
|
||||
{
|
||||
if (ValidateCellPosition(position))
|
||||
m_Cells[GetCellIndex(position)].gameObject = go;
|
||||
}
|
||||
|
||||
public void SetOffset(Vector3Int position, Vector3 offset)
|
||||
{
|
||||
if (ValidateCellPosition(position))
|
||||
m_Cells[GetCellIndex(position)].offset = offset;
|
||||
}
|
||||
|
||||
public void SetOrientation(Vector3Int position, Quaternion orientation)
|
||||
{
|
||||
if (ValidateCellPosition(position))
|
||||
m_Cells[GetCellIndex(position)].orientation = orientation;
|
||||
}
|
||||
|
||||
public void SetScale(Vector3Int position, Vector3 scale)
|
||||
{
|
||||
if (ValidateCellPosition(position))
|
||||
m_Cells[GetCellIndex(position)].scale = scale;
|
||||
}
|
||||
|
||||
public int GetCellIndex(Vector3Int brushPosition)
|
||||
{
|
||||
return GetCellIndex(brushPosition.x, brushPosition.y, brushPosition.z);
|
||||
}
|
||||
|
||||
public int GetCellIndex(int x, int y, int z)
|
||||
{
|
||||
return x + m_Size.x * y + m_Size.x * m_Size.y * z;
|
||||
}
|
||||
|
||||
public int GetCellIndex(int x, int y, int z, int sizex, int sizey, int sizez)
|
||||
{
|
||||
return x + sizex * y + sizex * sizey * z;
|
||||
}
|
||||
|
||||
public int GetCellIndexWrapAround(int x, int y, int z)
|
||||
{
|
||||
return (x % m_Size.x) + m_Size.x * (y % m_Size.y) + m_Size.x * m_Size.y * (z % m_Size.z);
|
||||
}
|
||||
|
||||
private static GameObject GetObjectInCell(GridLayout grid, Transform parent, Vector3Int position)
|
||||
{
|
||||
int childCount = parent.childCount;
|
||||
Vector3 min = grid.LocalToWorld(grid.CellToLocalInterpolated(position));
|
||||
Vector3 max = grid.LocalToWorld(grid.CellToLocalInterpolated(position + Vector3Int.one));
|
||||
|
||||
// Infinite bounds on Z for 2D convenience
|
||||
min = new Vector3(min.x, min.y, float.MinValue);
|
||||
max = new Vector3(max.x, max.y, float.MaxValue);
|
||||
|
||||
Bounds bounds = new Bounds((max + min) * .5f, max - min);
|
||||
|
||||
for (int i = 0; i < childCount; i++)
|
||||
{
|
||||
Transform child = parent.GetChild(i);
|
||||
if (bounds.Contains(child.position))
|
||||
return child.gameObject;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private bool ValidateCellPosition(Vector3Int position)
|
||||
{
|
||||
var valid =
|
||||
position.x >= 0 && position.x < size.x &&
|
||||
position.y >= 0 && position.y < size.y &&
|
||||
position.z >= 0 && position.z < size.z;
|
||||
if (!valid)
|
||||
throw new ArgumentException(string.Format("Position {0} is an invalid cell position. Valid range is between [{1}, {2}).", position, Vector3Int.zero, size));
|
||||
return valid;
|
||||
}
|
||||
|
||||
private void SizeUpdated()
|
||||
{
|
||||
m_Cells = new BrushCell[m_Size.x * m_Size.y * m_Size.z];
|
||||
BoundsInt bounds = new BoundsInt(Vector3Int.zero, m_Size);
|
||||
foreach (Vector3Int pos in bounds.allPositionsWithin)
|
||||
{
|
||||
m_Cells[GetCellIndex(pos)] = new BrushCell();
|
||||
}
|
||||
}
|
||||
|
||||
private static void SetSceneCell(GridLayout grid, Transform parent, Vector3Int position, GameObject go, Vector3 offset, Vector3 scale, Quaternion orientation)
|
||||
{
|
||||
if (parent == null || go == null)
|
||||
return;
|
||||
|
||||
GameObject instance = null;
|
||||
if (PrefabUtility.GetPrefabType(go) == PrefabType.Prefab)
|
||||
{
|
||||
instance = (GameObject) PrefabUtility.InstantiatePrefab(go);
|
||||
}
|
||||
else
|
||||
{
|
||||
instance = Instantiate(go);
|
||||
instance.hideFlags = HideFlags.None;
|
||||
instance.name = go.name;
|
||||
}
|
||||
|
||||
Undo.RegisterCreatedObjectUndo(instance, "Paint GameObject");
|
||||
instance.transform.SetParent(parent);
|
||||
instance.transform.position = grid.LocalToWorld(grid.CellToLocalInterpolated(new Vector3Int(position.x, position.y, position.z) + new Vector3(.5f, .5f, .5f)));
|
||||
instance.transform.localRotation = orientation;
|
||||
instance.transform.localScale = scale;
|
||||
instance.transform.Translate(offset);
|
||||
}
|
||||
|
||||
private static void ClearSceneCell(GridLayout grid, Transform parent, Vector3Int position)
|
||||
{
|
||||
if (parent == null)
|
||||
return;
|
||||
|
||||
GameObject erased = GetObjectInCell(grid, parent, new Vector3Int(position.x, position.y, position.z));
|
||||
if (erased != null)
|
||||
Undo.DestroyObjectImmediate(erased);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
int hash = 0;
|
||||
unchecked
|
||||
{
|
||||
foreach (var cell in cells)
|
||||
{
|
||||
hash = hash * 33 + cell.GetHashCode();
|
||||
}
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class BrushCell
|
||||
{
|
||||
public GameObject gameObject { get { return m_GameObject; } set { m_GameObject = value; } }
|
||||
public Vector3 offset { get { return m_Offset; } set { m_Offset = value; } }
|
||||
public Vector3 scale { get { return m_Scale; } set { m_Scale = value; } }
|
||||
public Quaternion orientation { get { return m_Orientation; } set { m_Orientation = value; } }
|
||||
|
||||
[SerializeField]
|
||||
private GameObject m_GameObject;
|
||||
[SerializeField]
|
||||
Vector3 m_Offset = Vector3.zero;
|
||||
[SerializeField]
|
||||
Vector3 m_Scale = Vector3.one;
|
||||
[SerializeField]
|
||||
Quaternion m_Orientation = Quaternion.identity;
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
int hash = 0;
|
||||
unchecked
|
||||
{
|
||||
hash = gameObject != null ? gameObject.GetInstanceID() : 0;
|
||||
hash = hash * 33 + m_Offset.GetHashCode();
|
||||
hash = hash * 33 + m_Scale.GetHashCode();
|
||||
hash = hash * 33 + m_Orientation.GetHashCode();
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[CustomEditor(typeof(GameObjectBrush))]
|
||||
public class GameObjectBrushEditor : UnityEditor.Tilemaps.GridBrushEditorBase
|
||||
{
|
||||
public GameObjectBrush brush { get { return target as GameObjectBrush; } }
|
||||
|
||||
public override void OnPaintSceneGUI(GridLayout gridLayout, GameObject brushTarget, BoundsInt position, GridBrushBase.Tool tool, bool executing)
|
||||
{
|
||||
BoundsInt gizmoRect = position;
|
||||
|
||||
if (tool == GridBrushBase.Tool.Paint || tool == GridBrushBase.Tool.Erase)
|
||||
gizmoRect = new BoundsInt(position.min - brush.pivot, brush.size);
|
||||
|
||||
base.OnPaintSceneGUI(gridLayout, brushTarget, gizmoRect, tool, executing);
|
||||
}
|
||||
|
||||
public override void OnPaintInspectorGUI()
|
||||
{
|
||||
GUILayout.Label("Pick, paint and erase GameObject(s) in the scene.");
|
||||
GUILayout.Label("Limited to children of the currently selected GameObject.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0abded712ad706044a53ef292972edbb
|
||||
timeCreated: 1501700935
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
10
Assets/Scripts/UI/Tilemap/Brushes/Line Brush.meta
Normal file
10
Assets/Scripts/UI/Tilemap/Brushes/Line Brush.meta
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ddf6fb480373a4b4babf2bd106dd48d8
|
||||
folderAsset: yes
|
||||
timeCreated: 1499149753
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
10
Assets/Scripts/UI/Tilemap/Brushes/Line Brush/Scripts.meta
Normal file
10
Assets/Scripts/UI/Tilemap/Brushes/Line Brush/Scripts.meta
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6a7de8b7c9f16a54abb1f4e4b4dda454
|
||||
folderAsset: yes
|
||||
timeCreated: 1499149780
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a4ce1d57936070949bdd366b4d13335f
|
||||
folderAsset: yes
|
||||
timeCreated: 1499149785
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,209 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Tilemaps;
|
||||
using System.Linq;
|
||||
|
||||
namespace UnityEditor
|
||||
{
|
||||
[CustomGridBrush(true, false, false, "Line Brush")]
|
||||
public class LineBrush : UnityEditor.Tilemaps.GridBrush
|
||||
{
|
||||
public bool lineStartActive = false;
|
||||
public bool fillGaps = false;
|
||||
public Vector3Int lineStart = Vector3Int.zero;
|
||||
|
||||
public override void Paint(GridLayout grid, GameObject brushTarget, Vector3Int position)
|
||||
{
|
||||
if (lineStartActive)
|
||||
{
|
||||
Vector2Int startPos = new Vector2Int(lineStart.x, lineStart.y);
|
||||
Vector2Int endPos = new Vector2Int(position.x, position.y);
|
||||
if (startPos == endPos)
|
||||
base.Paint(grid, brushTarget, position);
|
||||
else
|
||||
{
|
||||
foreach (var point in GetPointsOnLine(startPos, endPos, fillGaps))
|
||||
{
|
||||
Vector3Int paintPos = new Vector3Int(point.x, point.y, position.z);
|
||||
base.Paint(grid, brushTarget, paintPos);
|
||||
}
|
||||
}
|
||||
lineStartActive = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
lineStart = position;
|
||||
lineStartActive = true;
|
||||
}
|
||||
}
|
||||
|
||||
[MenuItem("Assets/Create/Line Brush")]
|
||||
public static void CreateBrush()
|
||||
{
|
||||
string path = EditorUtility.SaveFilePanelInProject("Save Line Brush", "New Line Brush", "asset", "Save Line Brush", "Assets");
|
||||
|
||||
if (path == "")
|
||||
return;
|
||||
|
||||
AssetDatabase.CreateAsset(ScriptableObject.CreateInstance<LineBrush>(), path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Added option to fill gaps for continuous lines.
|
||||
/// </summary>
|
||||
public static IEnumerable<Vector2Int> GetPointsOnLine(Vector2Int startPos, Vector2Int endPos, bool fillGaps)
|
||||
{
|
||||
var points = GetPointsOnLine(startPos, endPos);
|
||||
if (fillGaps)
|
||||
{
|
||||
var rise = endPos.y - startPos.y;
|
||||
var run = endPos.x - startPos.x;
|
||||
|
||||
if (rise != 0 || run != 0)
|
||||
{
|
||||
var extraStart = startPos;
|
||||
var extraEnd = endPos;
|
||||
|
||||
|
||||
if (Mathf.Abs(rise) >= Mathf.Abs(run))
|
||||
{
|
||||
// up
|
||||
if (rise > 0)
|
||||
{
|
||||
extraStart.y += 1;
|
||||
extraEnd.y += 1;
|
||||
}
|
||||
// down
|
||||
else // rise < 0
|
||||
{
|
||||
|
||||
extraStart.y -= 1;
|
||||
extraEnd.y -= 1;
|
||||
}
|
||||
}
|
||||
else // Mathf.Abs(rise) < Mathf.Abs(run)
|
||||
{
|
||||
|
||||
// right
|
||||
if (run > 0)
|
||||
{
|
||||
extraStart.x += 1;
|
||||
extraEnd.x += 1;
|
||||
}
|
||||
// left
|
||||
else // run < 0
|
||||
{
|
||||
extraStart.x -= 1;
|
||||
extraEnd.x -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
var extraPoints = GetPointsOnLine(extraStart, extraEnd);
|
||||
extraPoints = extraPoints.Except(new[] { extraEnd });
|
||||
points = points.Union(extraPoints);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return points;
|
||||
}
|
||||
|
||||
// http://ericw.ca/notes/bresenhams-line-algorithm-in-csharp.html
|
||||
public static IEnumerable<Vector2Int> GetPointsOnLine(Vector2Int p1, Vector2Int p2)
|
||||
{
|
||||
int x0 = p1.x;
|
||||
int y0 = p1.y;
|
||||
int x1 = p2.x;
|
||||
int y1 = p2.y;
|
||||
|
||||
bool steep = Math.Abs(y1 - y0) > Math.Abs(x1 - x0);
|
||||
if (steep)
|
||||
{
|
||||
int t;
|
||||
t = x0; // swap x0 and y0
|
||||
x0 = y0;
|
||||
y0 = t;
|
||||
t = x1; // swap x1 and y1
|
||||
x1 = y1;
|
||||
y1 = t;
|
||||
}
|
||||
if (x0 > x1)
|
||||
{
|
||||
int t;
|
||||
t = x0; // swap x0 and x1
|
||||
x0 = x1;
|
||||
x1 = t;
|
||||
t = y0; // swap y0 and y1
|
||||
y0 = y1;
|
||||
y1 = t;
|
||||
}
|
||||
int dx = x1 - x0;
|
||||
int dy = Math.Abs(y1 - y0);
|
||||
int error = dx / 2;
|
||||
int ystep = (y0 < y1) ? 1 : -1;
|
||||
int y = y0;
|
||||
for (int x = x0; x <= x1; x++)
|
||||
{
|
||||
yield return new Vector2Int((steep ? y : x), (steep ? x : y));
|
||||
error = error - dy;
|
||||
if (error < 0)
|
||||
{
|
||||
y += ystep;
|
||||
error += dx;
|
||||
}
|
||||
}
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
|
||||
[CustomEditor(typeof(LineBrush))]
|
||||
public class LineBrushEditor : UnityEditor.Tilemaps.GridBrushEditor
|
||||
{
|
||||
private LineBrush lineBrush { get { return target as LineBrush; } }
|
||||
|
||||
public override void OnPaintSceneGUI(GridLayout grid, GameObject brushTarget, BoundsInt position, GridBrushBase.Tool tool, bool executing)
|
||||
{
|
||||
base.OnPaintSceneGUI(grid, brushTarget, position, tool, executing);
|
||||
if (lineBrush.lineStartActive)
|
||||
{
|
||||
Tilemap tilemap = brushTarget.GetComponent<Tilemap>();
|
||||
if (tilemap != null)
|
||||
tilemap.ClearAllEditorPreviewTiles();
|
||||
|
||||
// Draw preview tiles for tilemap
|
||||
Vector2Int startPos = new Vector2Int(lineBrush.lineStart.x, lineBrush.lineStart.y);
|
||||
Vector2Int endPos = new Vector2Int(position.x, position.y);
|
||||
if (startPos == endPos)
|
||||
PaintPreview(grid, brushTarget, position.min);
|
||||
else
|
||||
{
|
||||
foreach (var point in LineBrush.GetPointsOnLine(startPos, endPos, lineBrush.fillGaps))
|
||||
{
|
||||
Vector3Int paintPos = new Vector3Int(point.x, point.y, position.z);
|
||||
PaintPreview(grid, brushTarget, paintPos);
|
||||
}
|
||||
}
|
||||
|
||||
if (Event.current.type == EventType.Repaint)
|
||||
{
|
||||
var min = lineBrush.lineStart;
|
||||
var max = lineBrush.lineStart + position.size;
|
||||
|
||||
// Draws a box on the picked starting position
|
||||
GL.PushMatrix();
|
||||
GL.MultMatrix(GUI.matrix);
|
||||
GL.Begin(GL.LINES);
|
||||
Handles.color = Color.blue;
|
||||
Handles.DrawLine(new Vector3(min.x, min.y, min.z), new Vector3(max.x, min.y, min.z));
|
||||
Handles.DrawLine(new Vector3(max.x, min.y, min.z), new Vector3(max.x, max.y, min.z));
|
||||
Handles.DrawLine(new Vector3(max.x, max.y, min.z), new Vector3(min.x, max.y, min.z));
|
||||
Handles.DrawLine(new Vector3(min.x, max.y, min.z), new Vector3(min.x, min.y, min.z));
|
||||
GL.End();
|
||||
GL.PopMatrix();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6210598a979f8724a8dac4531c428889
|
||||
timeCreated: 1499149789
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
10
Assets/Scripts/UI/Tilemap/Brushes/Prefab Brush.meta
Normal file
10
Assets/Scripts/UI/Tilemap/Brushes/Prefab Brush.meta
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9b73c833515e70440a2222f774104211
|
||||
folderAsset: yes
|
||||
timeCreated: 1501789833
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
10
Assets/Scripts/UI/Tilemap/Brushes/Prefab Brush/Scripts.meta
Normal file
10
Assets/Scripts/UI/Tilemap/Brushes/Prefab Brush/Scripts.meta
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 090e78558c17f064eae502998e2f22fb
|
||||
folderAsset: yes
|
||||
timeCreated: 1501789849
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 642e946f97259c640b3a047a57944ed9
|
||||
folderAsset: yes
|
||||
timeCreated: 1501789995
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor
|
||||
{
|
||||
[CreateAssetMenu]
|
||||
[CustomGridBrush(false, true, false, "Prefab Brush")]
|
||||
public class PrefabBrush : GridBrushBase
|
||||
{
|
||||
private const float k_PerlinOffset = 100000f;
|
||||
public GameObject[] m_Prefabs;
|
||||
public float m_PerlinScale = 0.5f;
|
||||
public int m_Z;
|
||||
|
||||
public override void Paint(GridLayout grid, GameObject brushTarget, Vector3Int position)
|
||||
{
|
||||
// Do not allow editing palettes
|
||||
if (brushTarget.layer == 31)
|
||||
return;
|
||||
|
||||
int index = Mathf.Clamp(Mathf.FloorToInt(GetPerlinValue(position, m_PerlinScale, k_PerlinOffset)*m_Prefabs.Length), 0, m_Prefabs.Length - 1);
|
||||
GameObject prefab = m_Prefabs[index];
|
||||
GameObject instance = (GameObject) PrefabUtility.InstantiatePrefab(prefab);
|
||||
if (instance != null)
|
||||
{
|
||||
Undo.MoveGameObjectToScene(instance, brushTarget.scene, "Paint Prefabs");
|
||||
Undo.RegisterCreatedObjectUndo((Object)instance, "Paint Prefabs");
|
||||
instance.transform.SetParent(brushTarget.transform);
|
||||
instance.transform.position = grid.LocalToWorld(grid.CellToLocalInterpolated(new Vector3Int(position.x, position.y, m_Z) + new Vector3(.5f, .5f, .5f)));
|
||||
}
|
||||
}
|
||||
|
||||
public override void Erase(GridLayout grid, GameObject brushTarget, Vector3Int position)
|
||||
{
|
||||
// Do not allow editing palettes
|
||||
if (brushTarget.layer == 31)
|
||||
return;
|
||||
|
||||
Transform erased = GetObjectInCell(grid, brushTarget.transform, new Vector3Int(position.x, position.y, m_Z));
|
||||
if (erased != null)
|
||||
Undo.DestroyObjectImmediate(erased.gameObject);
|
||||
}
|
||||
|
||||
private static Transform GetObjectInCell(GridLayout grid, Transform parent, Vector3Int position)
|
||||
{
|
||||
int childCount = parent.childCount;
|
||||
Vector3 min = grid.LocalToWorld(grid.CellToLocalInterpolated(position));
|
||||
Vector3 max = grid.LocalToWorld(grid.CellToLocalInterpolated(position + Vector3Int.one));
|
||||
Bounds bounds = new Bounds((max + min)*.5f, max - min);
|
||||
|
||||
for (int i = 0; i < childCount; i++)
|
||||
{
|
||||
Transform child = parent.GetChild(i);
|
||||
if (bounds.Contains(child.position))
|
||||
return child;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static float GetPerlinValue(Vector3Int position, float scale, float offset)
|
||||
{
|
||||
return Mathf.PerlinNoise((position.x + offset)*scale, (position.y + offset)*scale);
|
||||
}
|
||||
}
|
||||
|
||||
[CustomEditor(typeof(PrefabBrush))]
|
||||
public class PrefabBrushEditor : UnityEditor.Tilemaps.GridBrushEditorBase
|
||||
{
|
||||
private PrefabBrush prefabBrush { get { return target as PrefabBrush; } }
|
||||
|
||||
private SerializedProperty m_Prefabs;
|
||||
private SerializedObject m_SerializedObject;
|
||||
|
||||
protected void OnEnable()
|
||||
{
|
||||
m_SerializedObject = new SerializedObject(target);
|
||||
m_Prefabs = m_SerializedObject.FindProperty("m_Prefabs");
|
||||
}
|
||||
|
||||
public override void OnPaintInspectorGUI()
|
||||
{
|
||||
m_SerializedObject.UpdateIfRequiredOrScript();
|
||||
prefabBrush.m_PerlinScale = EditorGUILayout.Slider("Perlin Scale", prefabBrush.m_PerlinScale, 0.001f, 0.999f);
|
||||
prefabBrush.m_Z = EditorGUILayout.IntField("Position Z", prefabBrush.m_Z);
|
||||
|
||||
EditorGUILayout.PropertyField(m_Prefabs, true);
|
||||
m_SerializedObject.ApplyModifiedPropertiesWithoutUndo();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2d5751a2c961df945a34295ccf5e576d
|
||||
timeCreated: 1501681786
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
10
Assets/Scripts/UI/Tilemap/Brushes/Random Brush.meta
Normal file
10
Assets/Scripts/UI/Tilemap/Brushes/Random Brush.meta
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8dee42ba30f712246852f41830cedbef
|
||||
folderAsset: yes
|
||||
timeCreated: 1499223176
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
10
Assets/Scripts/UI/Tilemap/Brushes/Random Brush/Scripts.meta
Normal file
10
Assets/Scripts/UI/Tilemap/Brushes/Random Brush/Scripts.meta
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d352e5b4c56a76e4d99fc48256bbc67e
|
||||
folderAsset: yes
|
||||
timeCreated: 1499223198
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 762d145b6139de6478fcc2998702d839
|
||||
folderAsset: yes
|
||||
timeCreated: 1499223228
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Tilemaps;
|
||||
|
||||
namespace UnityEditor
|
||||
{
|
||||
[CustomGridBrush(false, true, false, "Random Brush")]
|
||||
public class RandomBrush : UnityEditor.Tilemaps.GridBrush
|
||||
{
|
||||
public TileBase[] randomTiles;
|
||||
|
||||
public override void Paint(GridLayout grid, GameObject brushTarget, Vector3Int position)
|
||||
{
|
||||
if (randomTiles != null && randomTiles.Length > 0)
|
||||
{
|
||||
if (brushTarget == null)
|
||||
return;
|
||||
|
||||
var tilemap = brushTarget.GetComponent<Tilemap>();
|
||||
if (tilemap == null)
|
||||
return;
|
||||
|
||||
Vector3Int min = position - pivot;
|
||||
BoundsInt bounds = new BoundsInt(min, size);
|
||||
foreach (Vector3Int location in bounds.allPositionsWithin)
|
||||
{
|
||||
var randomTile = randomTiles[(int) (randomTiles.Length * UnityEngine.Random.value)];
|
||||
tilemap.SetTile(location, randomTile);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
base.Paint(grid, brushTarget, position);
|
||||
}
|
||||
}
|
||||
|
||||
[MenuItem("Assets/Create/Random Brush")]
|
||||
public static void CreateBrush()
|
||||
{
|
||||
string path = EditorUtility.SaveFilePanelInProject("Save Random Brush", "New Random Brush", "asset", "Save Random Brush", "Assets");
|
||||
|
||||
if (path == "")
|
||||
return;
|
||||
|
||||
AssetDatabase.CreateAsset(ScriptableObject.CreateInstance<RandomBrush>(), path);
|
||||
}
|
||||
}
|
||||
|
||||
[CustomEditor(typeof(RandomBrush))]
|
||||
public class RandomBrushEditor : UnityEditor.Tilemaps.GridBrushEditor
|
||||
{
|
||||
private RandomBrush randomBrush { get { return target as RandomBrush; } }
|
||||
private GameObject lastBrushTarget;
|
||||
|
||||
public override void PaintPreview(GridLayout grid, GameObject brushTarget, Vector3Int position)
|
||||
{
|
||||
if (randomBrush.randomTiles != null && randomBrush.randomTiles.Length > 0)
|
||||
{
|
||||
base.PaintPreview(grid, null, position);
|
||||
|
||||
if (brushTarget == null)
|
||||
return;
|
||||
|
||||
var tilemap = brushTarget.GetComponent<Tilemap>();
|
||||
if (tilemap == null)
|
||||
return;
|
||||
|
||||
Vector3Int min = position - randomBrush.pivot;
|
||||
BoundsInt bounds = new BoundsInt(min, randomBrush.size);
|
||||
foreach (Vector3Int location in bounds.allPositionsWithin)
|
||||
{
|
||||
var randomTile = randomBrush.randomTiles[(int) (randomBrush.randomTiles.Length * UnityEngine.Random.value)];
|
||||
tilemap.SetEditorPreviewTile(location, randomTile);
|
||||
}
|
||||
|
||||
lastBrushTarget = brushTarget;
|
||||
}
|
||||
else
|
||||
{
|
||||
base.PaintPreview(grid, brushTarget, position);
|
||||
}
|
||||
}
|
||||
|
||||
public override void ClearPreview()
|
||||
{
|
||||
if (lastBrushTarget != null)
|
||||
{
|
||||
var tilemap = lastBrushTarget.GetComponent<Tilemap>();
|
||||
if (tilemap == null)
|
||||
return;
|
||||
|
||||
tilemap.ClearAllEditorPreviewTiles();
|
||||
|
||||
lastBrushTarget = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
base.ClearPreview();
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnPaintInspectorGUI()
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
int count = EditorGUILayout.IntField("Number of Tiles", randomBrush.randomTiles != null ? randomBrush.randomTiles.Length : 0);
|
||||
if (count < 0)
|
||||
count = 0;
|
||||
if (randomBrush.randomTiles == null || randomBrush.randomTiles.Length != count)
|
||||
{
|
||||
Array.Resize<TileBase>(ref randomBrush.randomTiles, count);
|
||||
}
|
||||
|
||||
if (count == 0)
|
||||
return;
|
||||
|
||||
EditorGUILayout.LabelField("Place random tiles.");
|
||||
EditorGUILayout.Space();
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
randomBrush.randomTiles[i] = (TileBase) EditorGUILayout.ObjectField("Tile " + (i+1), randomBrush.randomTiles[i], typeof(TileBase), false, null);
|
||||
}
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
EditorUtility.SetDirty(randomBrush);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d80edd6caba93514eb01722041fe50b4
|
||||
timeCreated: 1499223220
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
10
Assets/Scripts/UI/Tilemap/Brushes/Tint Brush Smooth.meta
Normal file
10
Assets/Scripts/UI/Tilemap/Brushes/Tint Brush Smooth.meta
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 73ffdc5b54c50214e9899760b98f5754
|
||||
folderAsset: yes
|
||||
timeCreated: 1502798557
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3d5759c37f6ead941b87383dcb19bff3
|
||||
folderAsset: yes
|
||||
timeCreated: 1502798569
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7402f20de7e8fc34c9cfcbc965122710
|
||||
folderAsset: yes
|
||||
timeCreated: 1502800377
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Tilemaps;
|
||||
|
||||
namespace UnityEditor
|
||||
{
|
||||
[CustomGridBrush(false, false, false, "Tint Brush (Smooth)")]
|
||||
public class TintBrushSmooth : GridBrushBase
|
||||
{
|
||||
private TintTextureGenerator generator
|
||||
{
|
||||
get
|
||||
{
|
||||
TintTextureGenerator generator = FindObjectOfType<TintTextureGenerator>();
|
||||
if (generator == null)
|
||||
{
|
||||
// Note: Code assumes only one grid in scene
|
||||
Grid grid = FindObjectOfType<Grid>();
|
||||
if (grid != null)
|
||||
{
|
||||
generator = grid.gameObject.AddComponent<TintTextureGenerator>();
|
||||
}
|
||||
}
|
||||
return generator;
|
||||
}
|
||||
}
|
||||
|
||||
public Color m_Color = Color.white;
|
||||
|
||||
public override void Paint(GridLayout grid, GameObject brushTarget, Vector3Int position)
|
||||
{
|
||||
// Do not allow editing palettes
|
||||
if (brushTarget.layer == 31)
|
||||
return;
|
||||
|
||||
TintTextureGenerator generator = GetGenerator(grid);
|
||||
if (generator != null)
|
||||
{
|
||||
generator.SetColor(grid as Grid, position, m_Color);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Erase(GridLayout grid, GameObject brushTarget, Vector3Int position)
|
||||
{
|
||||
// Do not allow editing palettes
|
||||
if (brushTarget.layer == 31)
|
||||
return;
|
||||
|
||||
TintTextureGenerator generator = GetGenerator(grid);
|
||||
if (generator != null)
|
||||
{
|
||||
generator.SetColor(grid as Grid, position, Color.white);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Pick(GridLayout grid, GameObject brushTarget, BoundsInt position, Vector3Int pivot)
|
||||
{
|
||||
// Do not allow editing palettes
|
||||
if (brushTarget.layer == 31)
|
||||
return;
|
||||
|
||||
TintTextureGenerator generator = GetGenerator(grid);
|
||||
if (generator != null)
|
||||
{
|
||||
m_Color = generator.GetColor(grid as Grid, position.min);
|
||||
}
|
||||
}
|
||||
|
||||
private TintTextureGenerator GetGenerator(GridLayout grid)
|
||||
{
|
||||
TintTextureGenerator generator = FindObjectOfType<TintTextureGenerator>();
|
||||
if (generator == null)
|
||||
{
|
||||
if (grid != null)
|
||||
{
|
||||
generator = grid.gameObject.AddComponent<TintTextureGenerator>();
|
||||
}
|
||||
}
|
||||
return generator;
|
||||
}
|
||||
}
|
||||
|
||||
[CustomEditor(typeof(TintBrushSmooth))]
|
||||
public class TintBrushSmoothEditor : UnityEditor.Tilemaps.GridBrushEditorBase
|
||||
{
|
||||
public override GameObject[] validTargets
|
||||
{
|
||||
get
|
||||
{
|
||||
return GameObject.FindObjectsOfType<Tilemap>().Select(x => x.gameObject).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnPaintInspectorGUI()
|
||||
{
|
||||
base.OnPaintInspectorGUI();
|
||||
GUILayout.Label("Note: Tilemap needs to use TintedTilemap.shader!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ed363ce3b4856fa408111529bc784318
|
||||
timeCreated: 1502800385
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
using UnityEngine;
|
||||
using UnityEngine.Tilemaps;
|
||||
|
||||
[ExecuteInEditMode]
|
||||
public class TintTextureGenerator : MonoBehaviour
|
||||
{
|
||||
public int k_TintMapSize = 256;
|
||||
|
||||
private Texture2D m_TintTexture;
|
||||
|
||||
private Texture2D tintTexture
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_TintTexture == null)
|
||||
{
|
||||
m_TintTexture = new Texture2D(k_TintMapSize, k_TintMapSize, TextureFormat.ARGB32, false);
|
||||
m_TintTexture.hideFlags = HideFlags.HideAndDontSave;
|
||||
m_TintTexture.wrapMode = TextureWrapMode.Clamp;
|
||||
m_TintTexture.filterMode = FilterMode.Bilinear;
|
||||
RefreshGlobalShaderValues();
|
||||
}
|
||||
|
||||
return m_TintTexture;
|
||||
}
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
Refresh(GetComponent<Grid>());
|
||||
}
|
||||
|
||||
public void Refresh(Grid grid)
|
||||
{
|
||||
if (grid == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var w = tintTexture.width;
|
||||
var h = tintTexture.height;
|
||||
for (var y = 0; y < h; y++)
|
||||
for (var x = 0; x < w; x++)
|
||||
{
|
||||
var world = TextureToWorld(new Vector3Int(x, y, 0));
|
||||
tintTexture.SetPixel(x, y, GetGridInformation(grid).GetPositionProperty(world, "Tint", Color.white));
|
||||
}
|
||||
|
||||
tintTexture.Apply();
|
||||
}
|
||||
|
||||
public void Refresh(Grid grid, Vector3Int position)
|
||||
{
|
||||
if (grid == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RefreshGlobalShaderValues();
|
||||
var texPosition = WorldToTexture(position);
|
||||
tintTexture.SetPixel(texPosition.x, texPosition.y, GetGridInformation(grid).GetPositionProperty(position, "Tint", Color.white));
|
||||
tintTexture.Apply();
|
||||
}
|
||||
|
||||
public Color GetColor(Grid grid, Vector3Int position)
|
||||
{
|
||||
if (grid == null)
|
||||
{
|
||||
return Color.white;
|
||||
}
|
||||
|
||||
return GetGridInformation(grid).GetPositionProperty(position, "Tint", Color.white);
|
||||
}
|
||||
|
||||
public void SetColor(Grid grid, Vector3Int position, Color color)
|
||||
{
|
||||
if (grid == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GetGridInformation(grid).SetPositionProperty(position, "Tint", color);
|
||||
Refresh(grid, position);
|
||||
}
|
||||
|
||||
private Vector3Int WorldToTexture(Vector3Int world)
|
||||
{
|
||||
return new Vector3Int(world.x + tintTexture.width / 2, world.y + tintTexture.height / 2, 0);
|
||||
}
|
||||
|
||||
private Vector3Int TextureToWorld(Vector3Int texpos)
|
||||
{
|
||||
return new Vector3Int(texpos.x - tintTexture.width / 2, texpos.y - tintTexture.height / 2, 0);
|
||||
}
|
||||
|
||||
private GridInformation GetGridInformation(Grid grid)
|
||||
{
|
||||
var gridInformation = grid.GetComponent<GridInformation>();
|
||||
|
||||
if (gridInformation == null)
|
||||
{
|
||||
gridInformation = grid.gameObject.AddComponent<GridInformation>();
|
||||
}
|
||||
|
||||
return gridInformation;
|
||||
}
|
||||
|
||||
private void RefreshGlobalShaderValues()
|
||||
{
|
||||
Shader.SetGlobalTexture("_TintMap", m_TintTexture);
|
||||
Shader.SetGlobalFloat("_TintMapSize", k_TintMapSize);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b41bf0cc11b1c8f419f96e8eb0adea40
|
||||
timeCreated: 1502798706
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f9a74a0ba597dbd4ebbdc09df032a31c
|
||||
folderAsset: yes
|
||||
timeCreated: 1502798946
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
Shader "Custom/TintedTilemap"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
[PerRendererData]_MainTex ("Albedo (RGB)", 2D) = "white" {}
|
||||
}
|
||||
|
||||
SubShader
|
||||
{
|
||||
Tags { "Queue"="Transparent" "Render"="Transparent" "IgnoreProjector"="True"}
|
||||
LOD 200
|
||||
|
||||
ZWrite Off
|
||||
Blend SrcAlpha OneMinusSrcAlpha
|
||||
|
||||
Pass{
|
||||
CGPROGRAM
|
||||
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
|
||||
struct appdata {
|
||||
float4 vertex : POSITION;
|
||||
float4 texcoord : TEXCOORD0;
|
||||
};
|
||||
|
||||
sampler2D _MainTex;
|
||||
sampler2D _TintMap;
|
||||
float _TintMapSize;
|
||||
|
||||
struct v2f {
|
||||
float4 vertex : SV_POSITION;
|
||||
float4 uv : TEXCOORD0;
|
||||
float3 worldPos : float3;
|
||||
};
|
||||
|
||||
v2f vert(appdata v) {
|
||||
v2f o;
|
||||
|
||||
o.worldPos = mul (unity_ObjectToWorld, v.vertex);
|
||||
o.vertex = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = float4(v.texcoord.xy, 0, 0);
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 col = tex2D (_MainTex, i.uv);
|
||||
fixed4 tint = tex2D(_TintMap, (i.worldPos.xy / _TintMapSize) + .5);
|
||||
return tint * col;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
FallBack "Diffuse"
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9fcc3b710e7f7ae44bcf65125a08d5ef
|
||||
timeCreated: 1502805334
|
||||
licenseType: Pro
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
10
Assets/Scripts/UI/Tilemap/Brushes/Tint Brush.meta
Normal file
10
Assets/Scripts/UI/Tilemap/Brushes/Tint Brush.meta
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 91dd673b6b5d18845b756aedc65463ad
|
||||
folderAsset: yes
|
||||
timeCreated: 1502200654
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
10
Assets/Scripts/UI/Tilemap/Brushes/Tint Brush/Scripts.meta
Normal file
10
Assets/Scripts/UI/Tilemap/Brushes/Tint Brush/Scripts.meta
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0da715375d333a8418105408e081f130
|
||||
folderAsset: yes
|
||||
timeCreated: 1502200675
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 27c281d5970a0fd49bfebd8119dc790a
|
||||
folderAsset: yes
|
||||
timeCreated: 1502200680
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Tilemaps;
|
||||
|
||||
namespace UnityEditor
|
||||
{
|
||||
[CustomGridBrush(false, false, false, "Tint Brush")]
|
||||
public class TintBrush : GridBrushBase
|
||||
{
|
||||
public Color m_Color = Color.white;
|
||||
|
||||
public override void Paint(GridLayout grid, GameObject brushTarget, Vector3Int position)
|
||||
{
|
||||
// Do not allow editing palettes
|
||||
if (brushTarget.layer == 31)
|
||||
return;
|
||||
|
||||
Tilemap tilemap = brushTarget.GetComponent<Tilemap>();
|
||||
if (tilemap != null)
|
||||
{
|
||||
SetColor(tilemap, position, m_Color);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Erase(GridLayout grid, GameObject brushTarget, Vector3Int position)
|
||||
{
|
||||
// Do not allow editing palettes
|
||||
if (brushTarget.layer == 31)
|
||||
return;
|
||||
|
||||
Tilemap tilemap = brushTarget.GetComponent<Tilemap>();
|
||||
if (tilemap != null)
|
||||
{
|
||||
SetColor(tilemap, position, Color.white);
|
||||
}
|
||||
}
|
||||
|
||||
private static void SetColor(Tilemap tilemap, Vector3Int position, Color color)
|
||||
{
|
||||
TileBase tile = tilemap.GetTile(position);
|
||||
if (tile != null)
|
||||
{
|
||||
if ((tilemap.GetTileFlags(position) & TileFlags.LockColor) != 0)
|
||||
{
|
||||
if (tile is Tile)
|
||||
{
|
||||
Debug.LogWarning("Tint brush cancelled, because Tile (" + tile.name + ") has TileFlags.LockColor set. Unlock it from the Tile asset debug inspector.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("Tint brush cancelled. because Tile (" + tile.name + ") has TileFlags.LockColor set. Unset it in GetTileData().");
|
||||
}
|
||||
}
|
||||
|
||||
tilemap.SetColor(position, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[CustomEditor(typeof(TintBrush))]
|
||||
public class TintBrushEditor : UnityEditor.Tilemaps.GridBrushEditorBase
|
||||
{
|
||||
public override GameObject[] validTargets
|
||||
{
|
||||
get
|
||||
{
|
||||
return GameObject.FindObjectsOfType<Tilemap>().Select(x => x.gameObject).ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5461c6f43c33cae4e8367042630017f7
|
||||
timeCreated: 1502200727
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Loading…
Add table
Add a link
Reference in a new issue