void OnEnable() { m_tilemap = (Tilemap)target; m_tilemapTileset = m_tilemap.Tileset; RegisterTilesetEvents(m_tilemapTileset); //fix missing material on prefabs tilemaps (when pressing play for example) if (!string.IsNullOrEmpty(AssetDatabase.GetAssetPath(m_tilemap.gameObject))) { m_tilemap.Refresh(true, false, false, false); } if (m_tilemap.ParentTilemapGroup) { m_tilemap.ParentTilemapGroup.SelectedTilemap = m_tilemap; } }
private void DisplayCollider() { Event e = Event.current; if (Tileset.SelectedBrushId != Tileset.k_BrushId_Default) { EditorGUILayout.LabelField("Brush tile editing not allowed", EditorStyles.boldLabel); return; } bool isMultiselection = Tileset.TileSelection != null; bool saveChanges = false; Tile selectedTile = isMultiselection ? Tileset.Tiles[(int)(Tileset.TileSelection.selectionData[0] & Tileset.k_TileDataMask_TileId)] : Tileset.SelectedTile; if (e.type == EventType.MouseDown) { m_isDragging = true; if (selectedTile.collData.vertices != null) { m_savedVertexData = new Vector2[selectedTile.collData.vertices.Length]; selectedTile.collData.vertices.CopyTo(m_savedVertexData, 0); } } else if (e.type == EventType.MouseUp) { m_isDragging = false; } Tileset.BackgroundColor = EditorGUILayout.ColorField(Tileset.BackgroundColor); if (m_prevBgColor != Tileset.BackgroundColor || Styles.Instance.colliderBgStyle.normal.background == null) { m_prevBgColor = Tileset.BackgroundColor; if (Styles.Instance.colliderBgStyle.normal.background == null) { Styles.Instance.colliderBgStyle.normal.background = new Texture2D(1, 1) { hideFlags = HideFlags.DontSave } } ; Styles.Instance.colliderBgStyle.normal.background.SetPixel(0, 0, Tileset.BackgroundColor); Styles.Instance.colliderBgStyle.normal.background.Apply(); } float aspectRatio = Tileset.TilePxSize.x / Tileset.TilePxSize.y; float padding = 2; // pixel size of the border around the tile //Rect rCollArea = GUILayoutUtility.GetRect(1, 1, GUILayout.Width(EditorGUIUtility.currentViewWidth), GUILayout.Height(EditorGUIUtility.currentViewWidth / aspectRatio)); Rect rCollArea = GUILayoutUtility.GetRect(1, 1, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true)); GUI.BeginGroup(rCollArea, Styles.Instance.colliderBgStyle); if (e.type == EventType.Repaint) { float pixelSize = rCollArea.width / (Tileset.TilePxSize.x + 2 * padding); m_mousePos = e.mousePosition; m_rTile = new Rect(padding * pixelSize, padding * pixelSize, rCollArea.width - 2 * padding * pixelSize, (rCollArea.width / aspectRatio) - 2 * padding * pixelSize); m_rTile.height = Mathf.Min(m_rTile.height, rCollArea.height - 2 * padding * pixelSize); m_rTile.width = (m_rTile.height * aspectRatio); } GUI.color = new Color(1f, 1f, 1f, 0.1f); GUI.DrawTexture(m_rTile, EditorGUIUtility.whiteTexture); GUI.color = Color.white; if (isMultiselection) { foreach (uint tileData in Tileset.TileSelection.selectionData) { int tileId = (int)(tileData & Tileset.k_TileDataMask_TileId); Tile tile = Tileset.GetTile(tileId); if (tile != null) { GUI.color = new Color(1f, 1f, 1f, 1f / Tileset.TileSelection.selectionData.Count); GUI.DrawTextureWithTexCoords(m_rTile, Tileset.AtlasTexture, tile.uv); } } GUI.color = Color.white; } else { GUI.DrawTextureWithTexCoords(m_rTile, Tileset.AtlasTexture, selectedTile.uv); } Color savedHandleColor = Handles.color; if (selectedTile.collData.type != eTileCollider.None) { Vector2[] collVertices = selectedTile.collData.type == eTileCollider.Full ? s_fullCollTileVertices : selectedTile.collData.vertices; if (collVertices == null || collVertices.Length == 0) { collVertices = selectedTile.collData.vertices = new Vector2[s_fullCollTileVertices.Length]; Array.Copy(s_fullCollTileVertices, collVertices, s_fullCollTileVertices.Length); EditorUtility.SetDirty(Tileset); } // Fix and snap positions for (int i = 0; i < collVertices.Length; ++i) { Vector2 s0 = collVertices[i]; s0.x = Mathf.Clamp01(Mathf.Round(s0.x * Tileset.TilePxSize.x) / Tileset.TilePxSize.x); s0.y = Mathf.Clamp01(Mathf.Round(s0.y * Tileset.TilePxSize.y) / Tileset.TilePxSize.y); collVertices[i] = s0; } // Draw edges Vector3[] polyEdges = new Vector3[collVertices.Length + 1]; for (int i = 0; i < collVertices.Length; ++i) { Vector2 s0 = collVertices[i]; s0.x = m_rTile.x + m_rTile.width * s0.x; s0.y = m_rTile.yMax - m_rTile.height * s0.y; Vector2 s1 = collVertices[(i + 1) % collVertices.Length]; s1.x = m_rTile.x + m_rTile.width * s1.x; s1.y = m_rTile.yMax - m_rTile.height * s1.y; polyEdges[i] = s0; polyEdges[i + 1] = s1; Handles.color = Color.green; Handles.DrawLine(s0, s1); //Draw normals { Handles.color = Color.white; Vector3 normPos = (s0 + s1) / 2f; Handles.DrawLine(normPos, normPos + Vector3.Cross(s1 - s0, Vector3.forward).normalized *m_rTile.yMin); } Handles.color = savedHandleColor; } float pixelSize = m_rTile.width / Tileset.TilePxSize.x; if (selectedTile.collData.type == eTileCollider.Polygon) { bool isAddingVertexOn = !m_isDragging && e.shift && m_activeVertexIdx == -1; bool isRemovingVertexOn = !m_isDragging && ((Application.platform == RuntimePlatform.OSXEditor)? e.command : e.control) && collVertices.Length > 3; if (isRemovingVertexOn && m_activeVertexIdx != -1 && e.type == EventType.MouseUp) { selectedTile.collData.vertices = new Vector2[collVertices.Length - 1]; for (int i = 0, j = 0; i < collVertices.Length; ++i) { if (i == m_activeVertexIdx) { continue; } selectedTile.collData.vertices[j] = collVertices[i]; ++j; } collVertices = selectedTile.collData.vertices; m_activeVertexIdx = -1; } float minDist = float.MaxValue; if (!m_isDragging) { m_activeVertexIdx = -1; } for (int i = 0; i < collVertices.Length; ++i) { Vector2 s0 = collVertices[i]; s0.x = m_rTile.x + m_rTile.width * s0.x; s0.y = m_rTile.yMax - m_rTile.height * s0.y; if (m_isDragging) { if (i == m_activeVertexIdx) { s0 = m_mousePos; s0 -= m_rTile.position; s0.x = Mathf.Clamp(Mathf.Round(s0.x / pixelSize) * pixelSize, 0, m_rTile.width); s0.y = Mathf.Clamp(Mathf.Round(s0.y / pixelSize) * pixelSize, 0, m_rTile.height); s0 += m_rTile.position; collVertices[i].x = Mathf.Clamp01((s0.x - m_rTile.x) / m_rTile.width); collVertices[i].y = Mathf.Clamp01((s0.y - m_rTile.yMax) / -m_rTile.height); } } else { float dist = Vector2.Distance(m_mousePos, s0); if (dist <= minDist && dist < Styles.Instance.collVertexHandleStyle.normal.background.width) { minDist = dist; m_activeVertexIdx = i; } } if (e.type == EventType.Repaint) { if (i == m_activeVertexIdx) { Styles.Instance.vertexCoordStyle.fontSize = (int)(Mathf.Min(10f, m_rTile.yMin / 2f)); GUI.Label(new Rect(0, 0, m_rTile.width, m_rTile.yMin), Vector2.Scale(collVertices[i], Tileset.TilePxSize).ToString(), Styles.Instance.vertexCoordStyle); } GUI.color = m_activeVertexIdx == i ? (isRemovingVertexOn ? Color.red : Color.cyan) : new Color(0.7f, 0.7f, 0.7f, 0.8f); Styles.Instance.collVertexHandleStyle.Draw(new Rect(s0.x - Styles.Instance.collVertexHandleStyle.normal.background.width / 2, s0.y - Styles.Instance.collVertexHandleStyle.normal.background.height / 2, 1, 1), i.ToString(), false, false, false, false); GUI.color = Color.white; } } if (isAddingVertexOn) { int segmentIdx; Vector2 newVertexPos = ClosestPointToPolyLine(polyEdges, out segmentIdx); if (e.type == EventType.MouseUp) { selectedTile.collData.vertices = new Vector2[collVertices.Length + 1]; segmentIdx = (segmentIdx + 1) % selectedTile.collData.vertices.Length; for (int i = 0, j = 0; i < selectedTile.collData.vertices.Length; ++i) { if (segmentIdx == i) { newVertexPos.x = Mathf.Clamp(Mathf.Round(newVertexPos.x / pixelSize) * pixelSize, m_rTile.x, m_rTile.xMax); newVertexPos.y = Mathf.Clamp(Mathf.Round(newVertexPos.y / pixelSize) * pixelSize, m_rTile.y, m_rTile.yMax); selectedTile.collData.vertices[i].x = Mathf.Clamp01((newVertexPos.x - m_rTile.x) / m_rTile.width); selectedTile.collData.vertices[i].y = Mathf.Clamp01((newVertexPos.y - m_rTile.yMax) / -m_rTile.height); } else { selectedTile.collData.vertices[i] = collVertices[j]; ++j; } } collVertices = selectedTile.collData.vertices; m_activeVertexIdx = -1; } else if (e.type == EventType.Repaint) { GUI.color = new Color(0.7f, 0.7f, 0.7f, 0.8f); Styles.Instance.collVertexHandleStyle.Draw(new Rect(newVertexPos.x - Styles.Instance.collVertexHandleStyle.normal.background.width / 2, newVertexPos.y - Styles.Instance.collVertexHandleStyle.normal.background.height / 2, 1, 1), segmentIdx.ToString(), false, false, false, false); GUI.color = Color.white; } } } if (e.type == EventType.MouseUp) { saveChanges = true; //remove duplicated vertex selectedTile.collData.vertices = selectedTile.collData.vertices.Distinct().ToArray(); if (selectedTile.collData.vertices.Length <= 2) { selectedTile.collData.vertices = m_savedVertexData; } //snap vertex positions selectedTile.collData.SnapVertices(Tileset); } } GUI.EndGroup(); if (GUILayout.Button("Reverse Normals")) { selectedTile.collData.vertices = selectedTile.collData.vertices.Reverse().ToArray(); } EditorGUILayout.Space(); string helpInfo = " - Click and drag over a vertex to move it" + "\n" + " - Hold Shift + Click for adding a new vertex" + "\n" + " - Hold " + ((Application.platform == RuntimePlatform.OSXEditor)? "Command" : "Ctrl") + " + Click for removing a vertex. (should be more than 3)" + "\n" + " - Check the normals for each edge. The normal is displayed in the collision side" + "\n" + ""; s_showHelp = EditorGUILayout.Foldout(s_showHelp, "Help"); if (s_showHelp) { EditorGUILayout.HelpBox(helpInfo, MessageType.Info); } //+++ Collider Settings float savedLabelWidth = EditorGUIUtility.labelWidth; EditorGUIUtility.labelWidth = 40; if (isMultiselection) { EditorGUILayout.LabelField("* Multi-selection Edition", EditorStyles.boldLabel); } EditorGUILayout.BeginHorizontal(GUILayout.MinWidth(140)); { EditorGUILayout.LabelField("Collider Data", EditorStyles.boldLabel); if (GUILayout.Button("Copy", GUILayout.Width(50))) { m_copiedColliderData = selectedTile.collData.Clone(); } if (GUILayout.Button("Paste", GUILayout.Width(50))) { selectedTile.collData = m_copiedColliderData.Clone(); saveChanges = true; } } EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); EditorGUIUtility.labelWidth = 100; EditorGUI.BeginChangeCheck(); //selectedTile.collData.type = (eTileCollider)EditorGUILayout.EnumPopup("Collider Type", selectedTile.collData.type); EditorGUILayout.LabelField("Collider Type:", EditorStyles.boldLabel); EditorGUI.indentLevel += 2; string[] tileColliderNames = System.Enum.GetNames(typeof(eTileCollider)); selectedTile.collData.type = (eTileCollider)GUILayout.Toolbar((int)selectedTile.collData.type, tileColliderNames); EditorGUI.indentLevel -= 2; saveChanges |= EditorGUI.EndChangeCheck(); EditorGUIUtility.labelWidth = savedLabelWidth; //--- //Save changes if (saveChanges) { if (isMultiselection) { for (int i = 0; i < Tileset.TileSelection.selectionData.Count; ++i) { Tileset.Tiles[(int)(Tileset.TileSelection.selectionData[i] & Tileset.k_TileDataMask_TileId)].collData = selectedTile.collData.Clone(); } } EditorUtility.SetDirty(Tileset); //Refresh selected tilemap Tilemap selectedTilemap = Selection.activeGameObject? Selection.activeGameObject.GetComponent <Tilemap>() : null; if (selectedTilemap) { selectedTilemap.Refresh(false, true); } } } /// <summary> // Get the point on a polyline (in 3D space) which is closest to the current // mouse position. And returns the segment index ( the vertex index of the segment with the closest point ) /// </summary> /// <param name="vertices"></param> /// <param name="closestSegmentIdx"></param> /// <returns></returns> Vector3 ClosestPointToPolyLine(Vector3[] vertices, out int closestSegmentIdx) { float minDist = float.MaxValue; closestSegmentIdx = 0; for (int i = 0; i < vertices.Length - 1; ++i) { float dist = HandleUtility.DistanceToLine(vertices[i], vertices[i + 1]); if (dist < minDist) { minDist = dist; closestSegmentIdx = i; } } return(HandleUtility.ClosestPointToPolyLine(vertices)); }
private ReorderableList CreateTilemapReorderableList() { ReorderableList reordList = new ReorderableList(serializedObject, serializedObject.FindProperty("m_tilemaps"), true, true, true, true); reordList.displayAdd = reordList.displayRemove = true; reordList.drawHeaderCallback = (Rect rect) => { EditorGUI.LabelField(rect, "Tilemaps", EditorStyles.boldLabel); Texture2D btnTexture = reordList.elementHeight == 0f ? EditorGUIUtility.FindTexture("winbtn_win_max_h") : EditorGUIUtility.FindTexture("winbtn_win_min_h"); if (GUI.Button(new Rect(rect.x + rect.width - rect.height, rect.y, rect.height, rect.height), btnTexture, EditorStyles.label)) { GUI.changed = true; reordList.elementHeight = reordList.elementHeight == 0f ? 21f : 0f; reordList.draggable = reordList.elementHeight > 0f; reordList.displayAdd = reordList.draggable; reordList.displayRemove = reordList.draggable; } }; reordList.drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) => { if (reordList.elementHeight == 0) { return; } var element = reordList.serializedProperty.GetArrayElementAtIndex(index); rect.y += 2; Tilemap tilemap = element.objectReferenceValue as Tilemap; if (tilemap) { SerializedObject tilemapSerialized = new SerializedObject(tilemap); SerializedObject tilemapObjSerialized = new SerializedObject(tilemapSerialized.FindProperty("m_GameObject").objectReferenceValue); Rect rToggle = new Rect(rect.x, rect.y, 16f, EditorGUIUtility.singleLineHeight); Rect rName = new Rect(rect.x + 20f, rect.y, rect.width - 130f - 20f, EditorGUIUtility.singleLineHeight); Rect rColliders = new Rect(rect.x + rect.width - 125f, rect.y, 125f, EditorGUIUtility.singleLineHeight); Rect rSortingLayer = new Rect(rect.x + rect.width - 125f, rect.y, 80f, EditorGUIUtility.singleLineHeight); Rect rSortingOrder = new Rect(rect.x + rect.width - 40f, rect.y, 40f, EditorGUIUtility.singleLineHeight); tilemap.IsVisible = EditorGUI.Toggle(rToggle, GUIContent.none, tilemap.IsVisible, STEditorStyles.Instance.visibleToggleStyle); EditorGUI.PropertyField(rName, tilemapObjSerialized.FindProperty("m_Name"), GUIContent.none); if (TilemapEditor.EditMode == TilemapEditor.eEditMode.Collider) { SerializedProperty colliderTypeProperty = tilemapSerialized.FindProperty("ColliderType"); string[] colliderTypeNames = new List <string>(System.Enum.GetNames(typeof(eColliderType)).Select(x => x.Replace('_', ' '))).ToArray(); EditorGUI.BeginChangeCheck(); colliderTypeProperty.intValue = GUI.Toolbar(rColliders, colliderTypeProperty.intValue, colliderTypeNames); if (EditorGUI.EndChangeCheck()) { tilemapSerialized.ApplyModifiedProperties(); tilemap.Refresh(false, true); } } else { // Sorting Layer and Order in layer EditorGUI.BeginChangeCheck(); EditorGUI.PropertyField(rSortingLayer, tilemapSerialized.FindProperty("m_sortingLayer"), GUIContent.none); EditorGUI.PropertyField(rSortingOrder, tilemapSerialized.FindProperty("m_orderInLayer"), GUIContent.none); tilemapSerialized.FindProperty("m_orderInLayer").intValue = (tilemapSerialized.FindProperty("m_orderInLayer").intValue << 16) >> 16; // convert from int32 to int16 keeping sign if (EditorGUI.EndChangeCheck()) { tilemapSerialized.ApplyModifiedProperties(); tilemap.RefreshChunksSortingAttributes(); SceneView.RepaintAll(); } //--- } if (GUI.changed) { tilemapObjSerialized.ApplyModifiedProperties(); } } }; reordList.onReorderCallback = (ReorderableList list) => { var targetObj = target as TilemapGroup; int sibilingIdx = 0; foreach (Tilemap tilemap in targetObj.Tilemaps) { tilemap.transform.SetSiblingIndex(sibilingIdx++); } Repaint(); }; reordList.onSelectCallback = (ReorderableList list) => { m_selectedIndexProp.intValue = reordList.index; serializedObject.ApplyModifiedProperties(); GUI.changed = true; TileSelectionWindow.RefreshIfVisible(); TilePropertiesWindow.RefreshIfVisible(); }; reordList.onAddCallback = (ReorderableList list) => { var targetObj = target as TilemapGroup; Undo.RegisterCompleteObjectUndo(targetObj, "New Tilemap"); GameObject obj = new GameObject(); Undo.RegisterCreatedObjectUndo(obj, "New Tilemap"); Tilemap newTilemap = obj.AddComponent <Tilemap>(); obj.transform.parent = targetObj.transform; obj.name = GameObjectUtility.GetUniqueNameForSibling(obj.transform.parent, "New Tilemap"); Tilemap copiedTilemap = targetObj.SelectedTilemap; if (copiedTilemap) { UnityEditorInternal.ComponentUtility.CopyComponent(copiedTilemap); UnityEditorInternal.ComponentUtility.PasteComponentValues(newTilemap); obj.name = GameObjectUtility.GetUniqueNameForSibling(obj.transform.parent, copiedTilemap.name); } }; reordList.onRemoveCallback = (ReorderableList list) => { m_tilemapRemovingList.Add(m_target.SelectedTilemap.gameObject); }; return(reordList); }
public override void OnInspectorGUI() { Event e = Event.current; if (e.type == EventType.ValidateCommand) { if (e.commandName == "UndoRedoPerformed") { m_tilemap.Refresh(); } } serializedObject.Update(); Tileset prevTileset = m_tilemap.Tileset; GUI.backgroundColor = Color.yellow; EditorGUILayout.BeginVertical(EditorStyles.helpBox); m_tilemap.Tileset = (Tileset)EditorGUILayout.ObjectField("Tileset", m_tilemap.Tileset, typeof(Tileset), false); EditorGUILayout.EndVertical(); GUI.backgroundColor = Color.white; if (prevTileset != m_tilemap.Tileset) { UnregisterTilesetEvents(prevTileset); RegisterTilesetEvents(m_tilemap.Tileset); m_tilemapTileset = m_tilemap.Tileset; } if (m_tilemap.Tileset == null) { EditorGUILayout.HelpBox("There is no tileset selected", MessageType.Info); return; } string[] editModeNames = System.Enum.GetNames(typeof(eEditMode)); s_editMode = (eEditMode)GUILayout.Toolbar((int)s_editMode, editModeNames); EditorGUILayout.BeginVertical(EditorStyles.helpBox); { if (s_editMode == eEditMode.Renderer) { EditorGUI.BeginChangeCheck(); Material prevMaterial = m_tilemap.Material; EditorGUILayout.PropertyField(serializedObject.FindProperty("m_material")); if (EditorGUI.EndChangeCheck()) { serializedObject.ApplyModifiedProperties(); m_tilemap.Refresh(); if (m_tilemap.Material != prevMaterial && !AssetDatabase.Contains(prevMaterial)) { //avoid memory leak DestroyImmediate(prevMaterial); } } // Draw Material Control /* * if (m_matEditor == null || EditorGUI.EndChangeCheck()) * { * if (m_matEditor != null) DestroyImmediate(m_matEditor); * m_matEditor = MaterialEditor.CreateEditor(m_tilemap.Material); * m_matEditor.hideFlags = HideFlags.DontSave; * } * float savedLabelWidth = EditorGUIUtility.labelWidth; * m_matEditor.DrawHeader(); * m_matEditor.OnInspectorGUI(); * EditorGUIUtility.labelWidth = savedLabelWidth; */ //--- EditorGUILayout.PropertyField(serializedObject.FindProperty("m_tintColor")); //Pixel Snap if (m_tilemap.Material.HasProperty("PixelSnap")) { EditorGUI.BeginChangeCheck(); bool isPixelSnapOn = EditorGUILayout.Toggle("Pixel Snap", m_tilemap.PixelSnap); if (EditorGUI.EndChangeCheck()) { m_tilemap.PixelSnap = isPixelSnapOn; } } // Sorting Layer and Order in layer EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(serializedObject.FindProperty("m_sortingLayer")); EditorGUILayout.PropertyField(serializedObject.FindProperty("m_orderInLayer")); serializedObject.FindProperty("m_orderInLayer").intValue = (serializedObject.FindProperty("m_orderInLayer").intValue << 16) >> 16; // convert from int32 to int16 keeping sign if (EditorGUI.EndChangeCheck()) { serializedObject.ApplyModifiedProperties(); m_tilemap.RefreshChunksSortingAttributes(); SceneView.RepaintAll(); } //--- EditorGUILayout.PropertyField(serializedObject.FindProperty("InnerPadding"), new GUIContent("Inner Padding", "The size, in pixels, the tile UV will be stretched. Use this to fix pixel precision artifacts when tiles have no padding border in the atlas.")); m_tilemap.IsVisible = EditorGUILayout.Toggle("Visible", m_tilemap.IsVisible); } else if (s_editMode == eEditMode.Map) { EditorGUILayout.Space(); if (GUILayout.Button("Refresh Map", GUILayout.MaxWidth(125))) { m_tilemap.Refresh(true, true, true, true); } if (GUILayout.Button("Clear Map", GUILayout.MaxWidth(125))) { if (EditorUtility.DisplayDialog("Warning!", "Are you sure you want to clear the map?\nThis action will remove all children objects under the tilemap", "Yes", "No")) { Undo.RegisterFullObjectHierarchyUndo(m_tilemap.gameObject, "Clear Map " + m_tilemap.name); m_tilemap.IsUndoEnabled = true; m_tilemap.ClearMap(); m_tilemap.IsUndoEnabled = false; } } EditorGUILayout.BeginVertical(EditorStyles.helpBox); EditorGUILayout.PropertyField(serializedObject.FindProperty("m_cellSize")); EditorGUILayout.PropertyField(serializedObject.FindProperty("ShowGrid"), new GUIContent("Show Grid", "Show the tilemap grid.")); EditorGUILayout.EndVertical(); EditorGUILayout.Space(); EditorGUILayout.LabelField("Map Size (" + m_tilemap.GridWidth + "," + m_tilemap.GridHeight + ")"); //+++ Display Map Bounds EditorGUILayout.BeginVertical(EditorStyles.helpBox); { EditorGUILayout.LabelField("Map Bounds (in tiles):", EditorStyles.boldLabel); m_toggleMapBoundsEdit = EditorUtils.DoToggleIconButton("Edit Map Bounds", m_toggleMapBoundsEdit, EditorGUIUtility.IconContent("EditCollider")); float savedLabelWidth = EditorGUIUtility.labelWidth; EditorGUIUtility.labelWidth = 80; EditorGUI.indentLevel += 2; EditorGUI.BeginChangeCheck(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.PropertyField(serializedObject.FindProperty("m_minGridX"), new GUIContent("Left")); EditorGUILayout.PropertyField(serializedObject.FindProperty("m_minGridY"), new GUIContent("Bottom")); EditorGUILayout.EndVertical(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.PropertyField(serializedObject.FindProperty("m_maxGridX"), new GUIContent("Right")); EditorGUILayout.PropertyField(serializedObject.FindProperty("m_maxGridY"), new GUIContent("Top")); EditorGUILayout.EndVertical(); if (EditorGUI.EndChangeCheck()) { serializedObject.ApplyModifiedProperties(); m_tilemap.RecalculateMapBounds(); } EditorGUI.indentLevel -= 2; EditorGUIUtility.labelWidth = savedLabelWidth; } EditorGUILayout.EndVertical(); //--- EditorGUILayout.Space(); m_tilemap.AllowPaintingOutOfBounds = EditorGUILayout.ToggleLeft("Allow Painting Out of Bounds", m_tilemap.AllowPaintingOutOfBounds); EditorGUILayout.Space(); if (GUILayout.Button("Shrink to Visible Area", GUILayout.MaxWidth(150))) { m_tilemap.ShrinkMapBoundsToVisibleArea(); } EditorGUILayout.Space(); EditorGUILayout.BeginVertical(EditorStyles.helpBox); { EditorGUILayout.LabelField("Advanced Options", EditorStyles.boldLabel); EditorGUI.BeginChangeCheck(); bool isChunksVisible = IsTilemapChunksVisible(); isChunksVisible = EditorGUILayout.Toggle(new GUIContent("Show Tile Chunks", "Show tilemap chunk objects for debugging or other purposes. Hiding will be refreshed after collapsing the tilemap."), isChunksVisible); if (EditorGUI.EndChangeCheck()) { SetTilemapChunkHideFlag(HideFlags.HideInHierarchy, !isChunksVisible); } EditorGUILayout.PropertyField(serializedObject.FindProperty("m_enableUndoWhilePainting"), new GUIContent("Enable Undo", "Disable Undo when painting on big maps to improve performance.")); } EditorGUILayout.EndVertical(); } else if (s_editMode == eEditMode.Collider) { EditorGUI.BeginChangeCheck(); { //EditorGUILayout.PropertyField(serializedObject.FindProperty("ColliderType")); EditorGUILayout.Space(); EditorGUILayout.BeginVertical(EditorStyles.helpBox); EditorGUILayout.LabelField("Collider Type:", EditorStyles.boldLabel); EditorGUI.indentLevel += 2; SerializedProperty colliderTypeProperty = serializedObject.FindProperty("ColliderType"); string[] colliderTypeNames = new List <string>(System.Enum.GetNames(typeof(eColliderType)).Select(x => x.Replace('_', ' '))).ToArray(); colliderTypeProperty.intValue = GUILayout.Toolbar(colliderTypeProperty.intValue, colliderTypeNames); EditorGUI.indentLevel -= 2; EditorGUILayout.Space(); EditorGUILayout.EndVertical(); EditorGUILayout.Space(); if (m_tilemap.ColliderType == eColliderType._3D) { SerializedProperty colliderDepthProperty = serializedObject.FindProperty("ColliderDepth"); EditorGUILayout.PropertyField(colliderDepthProperty); colliderDepthProperty.floatValue = Mathf.Clamp(colliderDepthProperty.floatValue, Vector3.kEpsilon, Mathf.Max(colliderDepthProperty.floatValue)); } else if (m_tilemap.ColliderType == eColliderType._2D) { EditorGUILayout.PropertyField(serializedObject.FindProperty("Collider2DType")); EditorGUILayout.PropertyField(serializedObject.FindProperty("ShowColliderNormals")); } EditorGUILayout.PropertyField(serializedObject.FindProperty("m_isTrigger")); if (m_tilemap.IsTrigger) { EditorGUILayout.HelpBox("Activating IsTrigger could generate wrong collider lines if not used properly. Use Show Tilechunks in Map section to display the real collider lines.", MessageType.Warning); } else if (m_tilemap.ColliderType == eColliderType._2D && m_tilemap.Collider2DType == e2DColliderType.PolygonCollider2D) { EditorGUILayout.HelpBox("Using Polygon colliders could generate wrong collider lines if not used properly. Use Show Tilechunks in Map section to display the real collider lines.", MessageType.Warning); } } if (EditorGUI.EndChangeCheck()) { serializedObject.ApplyModifiedProperties(); m_tilemap.Refresh(false, true); } EditorGUILayout.Space(); if (GUILayout.Button("Update Collider Mesh")) { m_tilemap.Refresh(false, true); } } else if (s_editMode == eEditMode.Paint) { if (m_tilemap.Tileset != null) { if (m_tilesetCtrl == null) { m_tilesetCtrl = new TilesetControl(); } m_tilesetCtrl.Tileset = m_tilemap.Tileset; m_tilesetCtrl.Display(); } } } EditorGUILayout.EndVertical(); Repaint(); serializedObject.ApplyModifiedProperties(); if (GUI.changed) { EditorUtility.SetDirty(target); } }
private void OnToolSelected_BrushToolbar(ToolbarControl source, int selectedToolIdx, int prevSelectedToolIdx) { ToolIcons.eToolIcon toolIcon = (ToolIcons.eToolIcon)selectedToolIdx; switch (toolIcon) { case ToolIcons.eToolIcon.Pencil: TilemapEditor.s_brushMode = TilemapEditor.eBrushMode.Paint; Tools.current = Tool.None; break; case ToolIcons.eToolIcon.Erase: TilemapEditor.s_brushMode = TilemapEditor.eBrushMode.Erase; brushPaintToolbar.TriggerButton(0); Tools.current = Tool.None; break; case ToolIcons.eToolIcon.Fill: TilemapEditor.s_brushMode = TilemapEditor.eBrushMode.Fill; brushPaintToolbar.TriggerButton(0); Tools.current = Tool.None; break; case ToolIcons.eToolIcon.FlipV: BrushBehaviour.SFlipV(); Tools.current = Tool.None; source.SelectedIdx = prevSelectedToolIdx; break; case ToolIcons.eToolIcon.FlipH: BrushBehaviour.SFlipH(); Tools.current = Tool.None; source.SelectedIdx = prevSelectedToolIdx; break; case ToolIcons.eToolIcon.Rot90: BrushBehaviour.SRot90(); Tools.current = Tool.None; source.SelectedIdx = prevSelectedToolIdx; break; case ToolIcons.eToolIcon.Info: TilemapEditor.s_displayHelpBox = !TilemapEditor.s_displayHelpBox; Tools.current = Tool.None; source.SelectedIdx = prevSelectedToolIdx; source.SetHighlight(selectedToolIdx, TilemapEditor.s_displayHelpBox); break; case ToolIcons.eToolIcon.Refresh: TilemapGroup tilemapGroup = Selection.activeGameObject.GetComponent <TilemapGroup>(); if (tilemapGroup) { foreach (Tilemap tilemap in tilemapGroup.Tilemaps) { tilemap.Refresh(true, true, true, true); } } else { Tilemap tilemap = Selection.activeGameObject.GetComponent <Tilemap>(); if (tilemap) { tilemap.Refresh(true, true, true, true); } } Tools.current = Tool.None; source.SelectedIdx = prevSelectedToolIdx; break; } }
private ReorderableList CreateTilemapReorderableList() { ReorderableList reordList = new ReorderableList(serializedObject, serializedObject.FindProperty("m_tilemaps"), true, true, true, true); reordList.displayAdd = reordList.displayRemove = true; reordList.drawHeaderCallback = (Rect rect) => { EditorGUI.LabelField(rect, "Tilemaps", EditorStyles.boldLabel); Texture2D btnTexture = reordList.elementHeight == 0f ? EditorGUIUtility.FindTexture("winbtn_win_max_h") : EditorGUIUtility.FindTexture("winbtn_win_min_h"); if (GUI.Button(new Rect(rect.width - rect.height, rect.y, rect.height, rect.height), btnTexture, EditorStyles.label)) { reordList.elementHeight = reordList.elementHeight == 0f ? EditorGUIUtility.singleLineHeight : 0f; reordList.draggable = reordList.elementHeight > 0f; } }; reordList.drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) => { var element = reordList.serializedProperty.GetArrayElementAtIndex(index); if (Event.current.type == EventType.Repaint) { m_reordListRectsDic[m_reordIdx] = rect; } else if (Event.current.type == EventType.Layout) { m_reordListRectsDic.TryGetValue(m_reordIdx, out rect); } m_reordIdx++; rect.y += 2; Tilemap tilemap = element.objectReferenceValue as Tilemap; SerializedObject tilemapSerialized = new SerializedObject(tilemap); SerializedObject tilemapObjSerialized = new SerializedObject(tilemapSerialized.FindProperty("m_GameObject").objectReferenceValue); GUILayout.BeginArea(rect); EditorGUILayout.BeginHorizontal(); tilemap.IsVisible = EditorGUILayout.Toggle(tilemap.IsVisible, GUILayout.Width(16)); EditorGUILayout.PropertyField(tilemapObjSerialized.FindProperty("m_Name"), GUIContent.none); if (TilemapEditor.EditMode == TilemapEditor.eEditMode.Collider) { SerializedProperty colliderTypeProperty = tilemapSerialized.FindProperty("ColliderType"); string[] colliderTypeNames = new List <string>(System.Enum.GetNames(typeof(eColliderType)).Select(x => x.Replace('_', ' '))).ToArray(); EditorGUI.BeginChangeCheck(); colliderTypeProperty.intValue = GUILayout.SelectionGrid(colliderTypeProperty.intValue, colliderTypeNames, colliderTypeNames.Length, GUILayout.MaxHeight(0.9f * EditorGUIUtility.singleLineHeight)); if (EditorGUI.EndChangeCheck()) { tilemapSerialized.ApplyModifiedProperties(); tilemap.Refresh(false, true); } } else { // Sorting Layer and Order in layer EditorGUI.BeginChangeCheck(); EditorGUIUtility.labelWidth = 1; EditorGUILayout.PropertyField(tilemapSerialized.FindProperty("m_sortingLayer"), new GUIContent(" ")); EditorGUIUtility.labelWidth = 40; EditorGUILayout.PropertyField(tilemapSerialized.FindProperty("m_orderInLayer"), new GUIContent("Order"), GUILayout.MaxWidth(90)); EditorGUIUtility.labelWidth = 0; tilemapSerialized.FindProperty("m_orderInLayer").intValue = (tilemapSerialized.FindProperty("m_orderInLayer").intValue << 16) >> 16; // convert from int32 to int16 keeping sign if (EditorGUI.EndChangeCheck()) { tilemapSerialized.ApplyModifiedProperties(); tilemap.RefreshChunksSortingAttributes(); SceneView.RepaintAll(); } //--- } EditorGUILayout.EndHorizontal(); GUILayout.EndArea(); if (GUI.changed) { tilemapObjSerialized.ApplyModifiedProperties(); } }; reordList.onReorderCallback = (ReorderableList list) => { var targetObj = target as TilemapGroup; int sibilingIdx = 0; foreach (Tilemap tilemap in targetObj.Tilemaps) { tilemap.transform.SetSiblingIndex(sibilingIdx++); } Repaint(); }; reordList.onSelectCallback = (ReorderableList list) => { serializedObject.FindProperty("m_selectedIndex").intValue = reordList.index; serializedObject.ApplyModifiedProperties(); GUI.changed = true; TileSelectionWindow.RefreshIfVisible(); TilePropertiesWindow.RefreshIfVisible(); }; reordList.onAddCallback = (ReorderableList list) => { var targetObj = target as TilemapGroup; Undo.RegisterCompleteObjectUndo(targetObj, "New Tilemap"); GameObject obj = new GameObject(); Undo.RegisterCreatedObjectUndo(obj, "New Tilemap"); Tilemap newTilemap = obj.AddComponent <Tilemap>(); obj.transform.parent = targetObj.transform; obj.name = GameObjectUtility.GetUniqueNameForSibling(obj.transform.parent, "New Tilemap"); Tilemap copiedTilemap = targetObj.SelectedTilemap; if (copiedTilemap) { UnityEditorInternal.ComponentUtility.CopyComponent(copiedTilemap); UnityEditorInternal.ComponentUtility.PasteComponentValues(newTilemap); obj.SendMessage("_DoDuplicate"); obj.name = GameObjectUtility.GetUniqueNameForSibling(obj.transform.parent, copiedTilemap.name); } }; reordList.onRemoveCallback = (ReorderableList list) => { var targetObj = target as TilemapGroup; Undo.DestroyObjectImmediate(targetObj.SelectedTilemap.gameObject); //NOTE: Fix argument exception if (m_tilemapReordList.index == targetObj.Tilemaps.Count - 1) { serializedObject.FindProperty("m_selectedIndex").intValue = m_tilemapReordList.index = m_tilemapReordList.index - 1; } }; return(reordList); }