Skip to content

Commit 332240f

Browse files
-Use WorldToCell comparison when getting GameObjects using PrefabBrush
1 parent 7eed19e commit 332240f

File tree

1 file changed

+141
-145
lines changed

1 file changed

+141
-145
lines changed
Lines changed: 141 additions & 145 deletions
Original file line numberDiff line numberDiff line change
@@ -1,146 +1,142 @@
1-
using System;
2-
using UnityEngine;
3-
using Object = UnityEngine.Object;
4-
5-
namespace UnityEditor.Tilemaps
6-
{
7-
/// <summary>
8-
/// This Brush instances and places a randomly selected Prefabs onto the targeted location and parents the instanced object to the paint target. Use this as an example to quickly place an assorted type of GameObjects onto structured locations.
9-
/// </summary>
10-
[CreateAssetMenu(fileName = "Prefab brush", menuName = "Brushes/Prefab brush")]
11-
[CustomGridBrush(false, true, false, "Prefab Brush")]
12-
public class PrefabBrush : GridBrush
13-
{
14-
private const float k_PerlinOffset = 100000f;
15-
/// <summary>
16-
/// The selection of Prefabs to paint from
17-
/// </summary>
18-
public GameObject[] m_Prefabs;
19-
/// <summary>
20-
/// Factor for distribution of choice of Prefabs to paint
21-
/// </summary>
22-
public float m_PerlinScale = 0.5f;
23-
/// <summary>
24-
/// Anchor Point of the Instantiated Prefab in the cell when painting
25-
/// </summary>
26-
public Vector3 m_Anchor = new Vector3(0.5f, 0.5f, 0.5f);
27-
28-
private GameObject prev_brushTarget;
29-
private Vector3Int prev_position = Vector3Int.one * Int32.MaxValue;
30-
31-
/// <summary>
32-
/// Paints Prefabs into a given position within the selected layers.
33-
/// The PrefabBrush overrides this to provide Prefab painting functionality.
34-
/// </summary>
35-
/// <param name="gridLayout">Grid used for layout.</param>
36-
/// <param name="brushTarget">Target of the paint operation. By default the currently selected GameObject.</param>
37-
/// <param name="position">The coordinates of the cell to paint data to.</param>
38-
public override void Paint(GridLayout grid, GameObject brushTarget, Vector3Int position)
39-
{
40-
if (position == prev_position)
41-
{
42-
return;
43-
}
44-
prev_position = position;
45-
if (brushTarget) {
46-
prev_brushTarget = brushTarget;
47-
}
48-
brushTarget = prev_brushTarget;
49-
50-
// Do not allow editing palettes
51-
if (brushTarget.layer == 31)
52-
return;
53-
54-
int index = Mathf.Clamp(Mathf.FloorToInt(GetPerlinValue(position, m_PerlinScale, k_PerlinOffset) * m_Prefabs.Length), 0, m_Prefabs.Length - 1);
55-
GameObject prefab = m_Prefabs[index];
56-
GameObject instance = (GameObject) PrefabUtility.InstantiatePrefab(prefab);
57-
if (instance != null)
58-
{
59-
Erase(grid, brushTarget, position);
60-
61-
Undo.MoveGameObjectToScene(instance, brushTarget.scene, "Paint Prefabs");
62-
Undo.RegisterCreatedObjectUndo((Object)instance, "Paint Prefabs");
63-
instance.transform.SetParent(brushTarget.transform);
64-
instance.transform.position = grid.LocalToWorld(grid.CellToLocalInterpolated(position + m_Anchor));
65-
}
66-
}
67-
68-
/// <summary>
69-
/// Erases Prefabs in a given position within the selected layers.
70-
/// The PrefabBrush overrides this to provide Prefab erasing functionality.
71-
/// </summary>
72-
/// <param name="gridLayout">Grid used for layout.</param>
73-
/// <param name="brushTarget">Target of the erase operation. By default the currently selected GameObject.</param>
74-
/// <param name="position">The coordinates of the cell to erase data from.</param>
75-
public override void Erase(GridLayout grid, GameObject brushTarget, Vector3Int position)
76-
{
77-
if (brushTarget)
78-
{
79-
prev_brushTarget = brushTarget;
80-
}
81-
brushTarget = prev_brushTarget;
82-
// Do not allow editing palettes
83-
if (brushTarget.layer == 31)
84-
return;
85-
86-
Transform erased = GetObjectInCell(grid, brushTarget.transform, position);
87-
if (erased != null)
88-
Undo.DestroyObjectImmediate(erased.gameObject);
89-
}
90-
91-
private static Transform GetObjectInCell(GridLayout grid, Transform parent, Vector3Int position)
92-
{
93-
int childCount = parent.childCount;
94-
Vector3 min = grid.LocalToWorld(grid.CellToLocalInterpolated(position));
95-
Vector3 max = grid.LocalToWorld(grid.CellToLocalInterpolated(position + Vector3Int.one));
96-
Bounds bounds = new Bounds((max + min)*.5f, max - min);
97-
98-
for (int i = 0; i < childCount; i++)
99-
{
100-
Transform child = parent.GetChild(i);
101-
if (bounds.Contains(child.position))
102-
return child;
103-
}
104-
return null;
105-
}
106-
107-
private static float GetPerlinValue(Vector3Int position, float scale, float offset)
108-
{
109-
return Mathf.PerlinNoise((position.x + offset)*scale, (position.y + offset)*scale);
110-
}
111-
}
112-
113-
/// <summary>
114-
/// The Brush Editor for a Prefab Brush.
115-
/// </summary>
116-
[CustomEditor(typeof(PrefabBrush))]
117-
public class PrefabBrushEditor : GridBrushEditor
118-
{
119-
private PrefabBrush prefabBrush { get { return target as PrefabBrush; } }
120-
121-
private SerializedProperty m_Prefabs;
122-
private SerializedProperty m_Anchor;
123-
private SerializedObject m_SerializedObject;
124-
125-
protected override void OnEnable()
126-
{
127-
base.OnEnable();
128-
m_SerializedObject = new SerializedObject(target);
129-
m_Prefabs = m_SerializedObject.FindProperty("m_Prefabs");
130-
m_Anchor = m_SerializedObject.FindProperty("m_Anchor");
131-
}
132-
133-
/// <summary>
134-
/// Callback for painting the inspector GUI for the PrefabBrush in the Tile Palette.
135-
/// The PrefabBrush Editor overrides this to have a custom inspector for this Brush.
136-
/// </summary>
137-
public override void OnPaintInspectorGUI()
138-
{
139-
m_SerializedObject.UpdateIfRequiredOrScript();
140-
prefabBrush.m_PerlinScale = EditorGUILayout.Slider("Perlin Scale", prefabBrush.m_PerlinScale, 0.001f, 0.999f);
141-
EditorGUILayout.PropertyField(m_Prefabs, true);
142-
EditorGUILayout.PropertyField(m_Anchor);
143-
m_SerializedObject.ApplyModifiedPropertiesWithoutUndo();
144-
}
145-
}
1+
using System;
2+
using UnityEngine;
3+
using Object = UnityEngine.Object;
4+
5+
namespace UnityEditor.Tilemaps
6+
{
7+
/// <summary>
8+
/// This Brush instances and places a randomly selected Prefabs onto the targeted location and parents the instanced object to the paint target. Use this as an example to quickly place an assorted type of GameObjects onto structured locations.
9+
/// </summary>
10+
[CreateAssetMenu(fileName = "Prefab brush", menuName = "Brushes/Prefab brush")]
11+
[CustomGridBrush(false, true, false, "Prefab Brush")]
12+
public class PrefabBrush : GridBrush
13+
{
14+
private const float k_PerlinOffset = 100000f;
15+
/// <summary>
16+
/// The selection of Prefabs to paint from
17+
/// </summary>
18+
public GameObject[] m_Prefabs;
19+
/// <summary>
20+
/// Factor for distribution of choice of Prefabs to paint
21+
/// </summary>
22+
public float m_PerlinScale = 0.5f;
23+
/// <summary>
24+
/// Anchor Point of the Instantiated Prefab in the cell when painting
25+
/// </summary>
26+
public Vector3 m_Anchor = new Vector3(0.5f, 0.5f, 0.5f);
27+
28+
private GameObject prev_brushTarget;
29+
private Vector3Int prev_position = Vector3Int.one * Int32.MaxValue;
30+
31+
/// <summary>
32+
/// Paints Prefabs into a given position within the selected layers.
33+
/// The PrefabBrush overrides this to provide Prefab painting functionality.
34+
/// </summary>
35+
/// <param name="gridLayout">Grid used for layout.</param>
36+
/// <param name="brushTarget">Target of the paint operation. By default the currently selected GameObject.</param>
37+
/// <param name="position">The coordinates of the cell to paint data to.</param>
38+
public override void Paint(GridLayout grid, GameObject brushTarget, Vector3Int position)
39+
{
40+
if (position == prev_position)
41+
{
42+
return;
43+
}
44+
prev_position = position;
45+
if (brushTarget) {
46+
prev_brushTarget = brushTarget;
47+
}
48+
brushTarget = prev_brushTarget;
49+
50+
// Do not allow editing palettes
51+
if (brushTarget.layer == 31)
52+
return;
53+
54+
int index = Mathf.Clamp(Mathf.FloorToInt(GetPerlinValue(position, m_PerlinScale, k_PerlinOffset) * m_Prefabs.Length), 0, m_Prefabs.Length - 1);
55+
GameObject prefab = m_Prefabs[index];
56+
GameObject instance = (GameObject) PrefabUtility.InstantiatePrefab(prefab);
57+
if (instance != null)
58+
{
59+
Erase(grid, brushTarget, position);
60+
61+
Undo.MoveGameObjectToScene(instance, brushTarget.scene, "Paint Prefabs");
62+
Undo.RegisterCreatedObjectUndo((Object)instance, "Paint Prefabs");
63+
instance.transform.SetParent(brushTarget.transform);
64+
instance.transform.position = grid.LocalToWorld(grid.CellToLocalInterpolated(position + m_Anchor));
65+
}
66+
}
67+
68+
/// <summary>
69+
/// Erases Prefabs in a given position within the selected layers.
70+
/// The PrefabBrush overrides this to provide Prefab erasing functionality.
71+
/// </summary>
72+
/// <param name="gridLayout">Grid used for layout.</param>
73+
/// <param name="brushTarget">Target of the erase operation. By default the currently selected GameObject.</param>
74+
/// <param name="position">The coordinates of the cell to erase data from.</param>
75+
public override void Erase(GridLayout grid, GameObject brushTarget, Vector3Int position)
76+
{
77+
if (brushTarget)
78+
{
79+
prev_brushTarget = brushTarget;
80+
}
81+
brushTarget = prev_brushTarget;
82+
// Do not allow editing palettes
83+
if (brushTarget.layer == 31)
84+
return;
85+
86+
Transform erased = GetObjectInCell(grid, brushTarget.transform, position);
87+
if (erased != null)
88+
Undo.DestroyObjectImmediate(erased.gameObject);
89+
}
90+
91+
private static Transform GetObjectInCell(GridLayout grid, Transform parent, Vector3Int position)
92+
{
93+
int childCount = parent.childCount;
94+
for (int i = 0; i < childCount; i++)
95+
{
96+
Transform child = parent.GetChild(i);
97+
if (position == grid.WorldToCell(child.position))
98+
return child;
99+
}
100+
return null;
101+
}
102+
103+
private static float GetPerlinValue(Vector3Int position, float scale, float offset)
104+
{
105+
return Mathf.PerlinNoise((position.x + offset)*scale, (position.y + offset)*scale);
106+
}
107+
}
108+
109+
/// <summary>
110+
/// The Brush Editor for a Prefab Brush.
111+
/// </summary>
112+
[CustomEditor(typeof(PrefabBrush))]
113+
public class PrefabBrushEditor : GridBrushEditor
114+
{
115+
private PrefabBrush prefabBrush { get { return target as PrefabBrush; } }
116+
117+
private SerializedProperty m_Prefabs;
118+
private SerializedProperty m_Anchor;
119+
private SerializedObject m_SerializedObject;
120+
121+
protected override void OnEnable()
122+
{
123+
base.OnEnable();
124+
m_SerializedObject = new SerializedObject(target);
125+
m_Prefabs = m_SerializedObject.FindProperty("m_Prefabs");
126+
m_Anchor = m_SerializedObject.FindProperty("m_Anchor");
127+
}
128+
129+
/// <summary>
130+
/// Callback for painting the inspector GUI for the PrefabBrush in the Tile Palette.
131+
/// The PrefabBrush Editor overrides this to have a custom inspector for this Brush.
132+
/// </summary>
133+
public override void OnPaintInspectorGUI()
134+
{
135+
m_SerializedObject.UpdateIfRequiredOrScript();
136+
prefabBrush.m_PerlinScale = EditorGUILayout.Slider("Perlin Scale", prefabBrush.m_PerlinScale, 0.001f, 0.999f);
137+
EditorGUILayout.PropertyField(m_Prefabs, true);
138+
EditorGUILayout.PropertyField(m_Anchor);
139+
m_SerializedObject.ApplyModifiedPropertiesWithoutUndo();
140+
}
141+
}
146142
}

0 commit comments

Comments
 (0)