Initial Commit
This commit is contained in:
commit
ee5c2f922d
2255 changed files with 547750 additions and 0 deletions
|
|
@ -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:
|
||||
Loading…
Add table
Add a link
Reference in a new issue