public static void TileDataField(Rect position, GUIContent label, SerializedProperty property, Tileset tileset) { Event e = Event.current; bool isLeftMouseReleased = e.type == EventType.MouseUp && e.button == 0; //NOTE: there is a bug with DrawTextureWithTexCoords where the texture disappears. It is fixed by overriding the Editor Script with a CustomEditor. Rect rVisualTile = new Rect(position.x, position.y, k_TilePreviewSize, k_TilePreviewSize); uint tileData = (uint)property.intValue; TilesetBrush brush = tileset.FindBrush(Tileset.GetBrushIdFromTileData(tileData)); if (brush) { tileData = brush.PreviewTileData(); } TilesetEditor.DoGUIDrawTileFromTileData(rVisualTile, tileData, tileset); if (isLeftMouseReleased && rVisualTile.Contains(e.mousePosition)) { EditorWindow wnd = EditorWindow.focusedWindow; TileSelectionWindow.Show(tileset); TileSelectionWindow.Instance.Ping(); wnd.Focus(); GUI.FocusControl(""); } EditorGUI.PropertyField(new Rect(position.x, position.y + k_TilePreviewSize, position.width, position.height - k_TilePreviewSize), property, label); }
/// <summary> /// Flip the map horizontally /// </summary> /// <param name="changeFlags"></param> public void FlipH(bool changeFlags) { List <uint> flippedList = new List <uint>(GridWidth * GridHeight); for (int gx = MinGridX; gx <= MaxGridX; ++gx) { for (int gy = MinGridY; gy <= MaxGridY; ++gy) { int flippedGx = GridWidth - 1 - gx; flippedList.Add(GetTileData(flippedGx, gy)); } } int idx = 0; for (int gx = MinGridX; gx <= MaxGridX; ++gx) { for (int gy = MinGridY; gy <= MaxGridY; ++gy, ++idx) { uint flippedTileData = flippedList[idx]; if ( changeFlags && (flippedTileData != Tileset.k_TileData_Empty) && (flippedTileData & Tileset.k_TileDataMask_BrushId) == 0 // don't activate flip flags on brushes ) { flippedTileData = TilesetBrush.ApplyAndMergeTileFlags(flippedTileData, Tileset.k_TileFlag_FlipH); } SetTileData(gx, gy, flippedTileData); } } }
void OnBrushSelected(Tileset source, int prevBrushId, int newBrushId) { if (AllowBrushSelection) { if (m_selectedTileIdx >= 0 && m_hasFocus) { m_tileIdOff = 0; uint brushTileData = m_getTileDataFunc(m_selectedTileIdx); if (brushTileData == Tileset.k_TileData_Empty) { brushTileData = 0u; // reset flags and everything } Undo.RecordObject(m_target, "BrushChanged"); TilesetBrush brush = Tileset.FindBrush(newBrushId); int tileId = (int)(brush.PreviewTileData() & Tileset.k_TileDataMask_TileId); brushTileData &= Tileset.k_TileDataMask_Flags; brushTileData |= (uint)(newBrushId << 16) & Tileset.k_TileDataMask_BrushId; brushTileData |= (uint)(tileId & Tileset.k_TileDataMask_TileId); m_setTileDataFunc(m_selectedTileIdx, brushTileData); m_hasChanged = true; } EditorUtility.SetDirty(m_target); } }
public override void OnInspectorGUI() { serializedObject.Update(); TilesetBrush brush = (TilesetBrush)target; if (brush.Tileset == null) { EditorGUILayout.HelpBox("Select a tileset first", MessageType.Info); EditorGUILayout.PropertyField(m_tileset); serializedObject.ApplyModifiedProperties(); return; } EditorGUILayout.PropertyField(m_tileset); m_group.intValue = TilesetEditor.DoGroupFieldLayout(brush.Tileset, "Group", m_group.intValue); string sAutotilingModeTooltip = "Autotiling Mode:\n" + "Self: autotile only with brushes of same type\n" + "Other: autotile with any other not empty tile\n" + "Group: autotile with brushes of a group that autotile the brush group"; m_autotilingMode.intValue = System.Convert.ToInt32(EditorGUILayout.EnumMaskField(new GUIContent("Autotiling Mode", sAutotilingModeTooltip), brush.AutotilingMode)); if (GUI.changed) { serializedObject.ApplyModifiedProperties(); EditorUtility.SetDirty(target); } }
private void DisplayAutotiling() { if (Tileset.SelectedBrushId != Tileset.k_BrushId_Default) { TilesetBrush brush = Tileset.FindBrush(Tileset.SelectedBrushId); if (brush) { EditorGUILayout.BeginHorizontal(); GUILayoutUtility.GetRect(1, 1, GUILayout.Width(Tileset.VisualTileSize.x), GUILayout.Height(Tileset.VisualTileSize.y)); TilesetEditor.DoGUIDrawTileFromTileData(GUILayoutUtility.GetLastRect(), brush.GetAnimTileData(), Tileset, brush.GetAnimUV()); GUILayout.Label("(" + brush.name + ":" + brush.GetType().Name + ")", EditorStyles.boldLabel); EditorGUILayout.EndHorizontal(); if (!m_brushEditor || m_brushEditor.target != brush) { m_brushEditor = TilesetBrushEditor.CreateEditor(brush) as TilesetBrushEditor; } (m_brushEditor as TilesetBrushEditor).DoInspectorGUI(); } } else { bool isMultiselection = Tileset.TileSelection != null; Tile selectedTile = isMultiselection ? Tileset.Tiles[(int)(Tileset.TileSelection.selectionData[0] & Tileset.k_TileDataMask_TileId)] : Tileset.SelectedTile; GUILayoutUtility.GetRect(1, 1, GUILayout.Width(Tileset.VisualTileSize.x), GUILayout.Height(Tileset.VisualTileSize.y)); Rect tileUV = selectedTile.uv; GUI.color = Tileset.BackgroundColor; GUI.DrawTextureWithTexCoords(GUILayoutUtility.GetLastRect(), EditorGUIUtility.whiteTexture, tileUV, true); GUI.color = Color.white; GUI.DrawTextureWithTexCoords(GUILayoutUtility.GetLastRect(), Tileset.AtlasTexture, tileUV, true); if (isMultiselection) { EditorGUILayout.LabelField("* Multi-selection Edition", EditorStyles.boldLabel); } EditorGUI.BeginChangeCheck(); selectedTile.autilingGroup = TilesetEditor.DoGroupFieldLayout(Tileset, "Group", selectedTile.autilingGroup); if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(Tileset, "Tile Autotiling Data Changed"); if (isMultiselection) { for (int i = 0; i < Tileset.TileSelection.selectionData.Count; ++i) { Tile tile = Tileset.Tiles[(int)(Tileset.TileSelection.selectionData[i] & Tileset.k_TileDataMask_TileId)]; tile.autilingGroup = selectedTile.autilingGroup; } } EditorUtility.SetDirty(Tileset); } } }
public static uint DoTileDataPropertiesLayout(uint tileData, Tileset tileset, bool displayBrush = true) { EditorGUILayout.BeginVertical(EditorStyles.helpBox); GUI.enabled = tileData != Tileset.k_TileData_Empty; EditorGUIUtility.labelWidth = 100; EditorGUI.BeginChangeCheck(); EditorGUILayout.Toggle("Flip Horizontally", (tileData & Tileset.k_TileFlag_FlipH) != 0); if (EditorGUI.EndChangeCheck()) { tileData ^= Tileset.k_TileFlag_FlipH; } EditorGUI.BeginChangeCheck(); EditorGUILayout.Toggle("Flip Vertically", (tileData & Tileset.k_TileFlag_FlipV) != 0); if (EditorGUI.EndChangeCheck()) { tileData ^= Tileset.k_TileFlag_FlipV; } EditorGUI.BeginChangeCheck(); EditorGUILayout.Toggle("Rotate 90º", (tileData & Tileset.k_TileFlag_Rot90) != 0); if (EditorGUI.EndChangeCheck()) { tileData ^= Tileset.k_TileFlag_Rot90; } if (displayBrush) { EditorGUI.BeginChangeCheck(); int brushId = Tileset.GetBrushIdFromTileData(tileData); TilesetBrush brush = tileset.FindBrush(brushId); brush = (TilesetBrush)EditorGUILayout.ObjectField("Brush", brush, typeof(TilesetBrush), false); if (EditorGUI.EndChangeCheck()) { brushId = brush != null?tileset.FindBrushId(brush.name) : Tileset.k_BrushId_Default; int tileId = brush != null ? (int)(brush.PreviewTileData() & Tileset.k_TileDataMask_TileId) : Tileset.GetTileIdFromTileData(tileData); tileData &= Tileset.k_TileDataMask_Flags; tileData |= (uint)(brushId << 16) & Tileset.k_TileDataMask_BrushId; tileData |= (uint)(tileId & Tileset.k_TileDataMask_TileId); } } if (GUILayout.Button("Reset")) { tileData = Tileset.k_TileData_Empty; } EditorGUIUtility.labelWidth = 0; GUI.enabled = true; EditorGUILayout.EndVertical(); return(tileData); }
public bool IsBrushVisibleByTypeMask(TilesetBrush brush) { if (brush) { string[] brushTypes = GetBrushTypeArray(); if (brushTypes != null && brushTypes.Length > 0) { int idx = System.Array.IndexOf(brushTypes, brush.GetType().Name); return(((1 << idx) & m_brushTypeMask) != 0); } } return(false); }
public override uint[] GetSubtiles(Tilemap tilemap, int gridX, int gridY, uint tileData) { // Add animated tiles { int idx = CalculateIndex(tilemap, gridX, gridY, tileData); TilesetBrush brush = Tileset.FindBrush(Tileset.GetBrushIdFromTileData(TileIds[idx])); if (brush && brush.IsAnimated()) { TilemapChunk.RegisterAnimatedBrush(brush); } } return(null); }
/// <summary> /// Return a tile parameter (bool, int, float, string or UnityEngine.Object) from a tiledata. /// It takes first the parameter from a brush, if possible, then from a tile. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="tileset"></param> /// <param name="tileData"></param> /// <param name="paramName"></param> /// <param name="defaultValue"></param> /// <returns></returns> static public T GetTileParameter <T>(Tileset tileset, uint tileData, string paramName, T defaultValue = default(T)) { Tile tile = tileset.GetTile(Tileset.GetTileIdFromTileData(tileData)); TilesetBrush brush = tileset.FindBrush(Tileset.GetBrushIdFromTileData(tileData)); T value = defaultValue; if (brush) { value = brush.Params.GetParam <T>(paramName, defaultValue); } if (tile != null && EqualityComparer <T> .Default.Equals(value, defaultValue)) { value = tile.paramContainer.GetParam <T>(paramName, defaultValue); } return(value); }
public TilesetBrush FindBrush(int brushId) { if (brushId == Tileset.k_BrushId_Empty) { return(null); } TilesetBrush tileBrush = null; if (!m_brushCache.TryGetValue(brushId, out tileBrush)) { tileBrush = m_brushes.FirstOrDefault(x => x.Id == brushId).BrushAsset; m_brushCache[brushId] = tileBrush; //Debug.Log(" Cache miss! " + tileBrush.name); } return(tileBrush); }
public TilesetBrush FindBrush(int brushId) { if (brushId <= 0) { return(null); } TilesetBrush tileBrush = null; if (!m_brushCache.TryGetValue(brushId, out tileBrush)) { tileBrush = FindBrushContainerByBrushId(brushId).BrushAsset; m_brushCache[brushId] = tileBrush; //Debug.Log(" Cache miss! " + tileBrush.name); } return(tileBrush); }
private void OnBrushSelected(Tileset source, int prevBrushId, int newBrushId) { if (m_randTileListHasFocus && m_randTileList.index >= 0 && m_randTileList.index < m_brush.RandomTileList.Count) { if (m_brush.RandomTileList[m_randTileList.index].tileData == Tileset.k_TileData_Empty) { m_brush.RandomTileList[m_randTileList.index].tileData = 0u;// reset flags and everything } m_brush.RandomTileList[m_randTileList.index].tileData &= ~Tileset.k_TileDataMask_TileId; m_brush.RandomTileList[m_randTileList.index].tileData &= ~Tileset.k_TileDataMask_BrushId; m_brush.RandomTileList[m_randTileList.index].tileData |= (uint)(newBrushId << 16); TilesetBrush brush = m_brush.Tileset.FindBrush(newBrushId); m_brush.RandomTileList[m_randTileList.index].tileData |= (uint)(brush.PreviewTileData() & Tileset.k_TileDataMask_TileId); } EditorUtility.SetDirty(target); m_brush.InvalidateSortedList(); }
protected static bool s_refreshingLinkedBrush = false; //avoid infinite loop /// <summary> /// Returns a new tiledata after calling the refresh method of the linked brush. /// This is used to give support for tiles in a brush that are linked to another brush. Ex: a Road Brush with a tile linked to a random brush. /// </summary> /// <param name="tilemap"></param> /// <param name="gridX"></param> /// <param name="gridY"></param> /// <param name="tileData"></param> /// <returns></returns> public uint RefreshLinkedBrush(STETilemap tilemap, int gridX, int gridY, uint tileData) { if (s_refreshingLinkedBrush) { return(tileData); } int brushId = Tileset.GetBrushIdFromTileData(tileData); TilesetBrush brush = Tileset.FindBrush(brushId); if (brush) { s_refreshingLinkedBrush = true; tileData = ApplyAndMergeTileFlags(brush.Refresh(tilemap, gridX, gridY, tileData), tileData); s_refreshingLinkedBrush = false; } return(tileData); }
public override uint Refresh(STETilemap tilemap, int gridX, int gridY, uint tileData) { if (RandomTileList.Count > 0) { uint randomTileData = GetRandomTile(); if (RandomizeFlagMask != 0) { uint flags = ((uint)Random.Range(0, 8) << 29) & RandomizeFlagMask; randomTileData &= ~RandomizeFlagMask; randomTileData |= flags; } uint brushTileData = RefreshLinkedBrush(tilemap, gridX, gridY, randomTileData); // overwrite flags brushTileData &= ~Tileset.k_TileDataMask_Flags; brushTileData |= randomTileData & Tileset.k_TileDataMask_Flags; TilesetBrush brush = Tileset.FindBrush(Tileset.GetBrushIdFromTileData(brushTileData)); if (brush && brush.IsAnimated()) { // Set the animated brush (overwriting the random brush for this tile) brushTileData &= ~Tileset.k_TileDataMask_BrushId; brushTileData |= randomTileData & Tileset.k_TileDataMask_BrushId; } // Overwrite the brush id for the one in the selected random tile // Side Effect: the tile will loose the brush id for the random brush if (RemoveBrushIdAfterRefresh) { // Do nothing } // Overwrite the selected tile brush id for the random brush id // NOTE: animated tiles wont be animated else { // overwrite brush id brushTileData &= ~Tileset.k_TileDataMask_BrushId; brushTileData |= tileData & Tileset.k_TileDataMask_BrushId; } return(brushTileData); } return(tileData); }
public override uint Refresh(Tilemap tilemap, int gridX, int gridY, uint tileData) { if (RandomTileList.Count > 0) { uint randomTileData = GetRandomTile(); if (RandomizeFlagMask != 0) { uint flags = ((uint)Random.Range(0, 8) << 29) & RandomizeFlagMask; randomTileData &= ~RandomizeFlagMask; randomTileData |= flags; } uint brushTileData = RefreshLinkedBrush(tilemap, gridX, gridY, randomTileData); // overwrite flags brushTileData &= ~Tileset.k_TileDataMask_Flags; brushTileData |= randomTileData & Tileset.k_TileDataMask_Flags; TilesetBrush brush = Tileset.FindBrush(Tileset.GetBrushIdFromTileData(brushTileData)); if (brush && brush.IsAnimated()) { // Set the animated brush (overwriting the random brush for this tile) brushTileData &= ~Tileset.k_TileDataMask_BrushId; brushTileData |= randomTileData & Tileset.k_TileDataMask_BrushId; } // - Commented: // This code will make the Random Brush to work only once // Copy the tile will copy the tile placed the first time // - Uncommented: // This code will make Refresh Tilemap to update all random brushes // Copy the tile will copy a random brush tile /* * { * // overwrite brush id * brushTileData &= ~Tileset.k_TileDataMask_BrushId; * brushTileData |= tileData & Tileset.k_TileDataMask_BrushId; * }*/ return(brushTileData); } return(tileData); }
public bool AutotileWith(int selfBrushId, int otherBrushId) { if ( ((AutotilingMode & eAutotilingMode.Self) != 0 && selfBrushId == otherBrushId) || ((AutotilingMode & eAutotilingMode.Other) != 0 && otherBrushId != selfBrushId && otherBrushId != (Tileset.k_TileDataMask_BrushId >> 16)) ) { return(true); } else if ((AutotilingMode & eAutotilingMode.Group) != 0) { TilesetBrush brush = Tileset.FindBrush(otherBrushId); if (brush) { return(Tileset.GetGroupAutotiling(Group, brush.Group)); } } return(false); }
public string[] UpdateBrushTypeArray() { List <string> outList = new List <string>(); for (int i = 0; i < Brushes.Count; ++i) { TilesetBrush brush = Brushes[i].BrushAsset; if (brush) { string type = brush.GetType().Name; if (!outList.Contains(type)) { outList.Add(type); } } } m_brushTypeMaskOptions = outList.ToArray(); return(m_brushTypeMaskOptions); }
/// <summary> /// Get the parameter container from tileData if tileData contains a tile with parameters or Null in other case /// </summary> /// <param name="tilemap"></param> /// <param name="tileData"></param> /// <returns></returns> static public ParameterContainer GetParamsFromTileData(STETilemap tilemap, uint tileData) { int brushId = Tileset.GetBrushIdFromTileData(tileData); TilesetBrush brush = tilemap.Tileset.FindBrush(brushId); if (brush) { return(brush.Params); } else { int tileId = Tileset.GetTileIdFromTileData(tileData); Tile tile = tilemap.Tileset.GetTile(tileId); if (tile != null) { return(tile.paramContainer); } } return(null); }
/// <summary> /// Rotate the map 90 degrees clockwise /// </summary> /// <param name="changeFlags"></param> public void Rot90(bool changeFlags) { List <uint> flippedList = new List <uint>(GridWidth * GridHeight); for (int gy = MinGridY; gy <= MaxGridY; ++gy) { for (int gx = MinGridX; gx <= MaxGridX; ++gx) { flippedList.Add(GetTileData(gx, gy)); } } int minGridX = MinGridX; int minGridY = MinGridY; int maxGridX = MaxGridY; int maxGridY = MaxGridX; ClearMap(); int idx = 0; for (int gx = minGridX; gx <= maxGridX; ++gx) { for (int gy = maxGridY; gy >= minGridY; --gy, ++idx) { uint flippedTileData = flippedList[idx]; if ( changeFlags && (flippedTileData != Tileset.k_TileData_Empty) && (flippedTileData & Tileset.k_TileDataMask_BrushId) == 0 // don't activate flip flags on brushes ) { flippedTileData = TilesetBrush.ApplyAndMergeTileFlags(flippedTileData, Tileset.k_TileFlag_Rot90); } SetTileData(gx, gy, flippedTileData); } } }
public bool AutotileWith(int selfBrushId, int otherBrushId) { if ( ((AutotilingMode & eAutotilingMode.Self) != 0 && selfBrushId == otherBrushId) || ((AutotilingMode & eAutotilingMode.Other) != 0 && otherBrushId != selfBrushId && otherBrushId != (Tileset.k_TileDataMask_BrushId >> 16)) ) { return(true); } if ((AutotilingMode & eAutotilingMode.Group) != 0) { TilesetBrush brush = Tileset.FindBrush(otherBrushId); if (brush) { return(Tileset.GetGroupAutotiling(Group, brush.Group)); } else if (otherBrushId == Tileset.k_BrushId_Default) { return(Tileset.GetGroupAutotiling(Group, 0)); //with normal tiles, use default group (0) //TODO: this is old code, now it is possible to change tile group. Check if this method is useful after removing it from TilemapChunk } } return(false); }
private void DisplayBrushReorderableList() { Event e = Event.current; if (m_brushList == null || m_brushList.list != Tileset.Brushes) { if (e.type != EventType.Layout) { m_brushList = TilesetEditor.CreateBrushReorderableList(Tileset); m_brushList.onSelectCallback += (ReorderableList list) => { Tileset.BrushContainer brushCont = Tileset.Brushes[list.index]; Tileset.SelectedBrushId = brushCont.Id; RemoveTileSelection(); if (m_dblClick.IsDblClick) { EditorGUIUtility.PingObject(brushCont.BrushAsset); m_selectBrushInInspector = brushCont.BrushAsset; } }; } } else { GUILayout.BeginVertical(m_customBox); m_brushList.index = Tileset.Brushes.FindIndex(x => x.Id == Tileset.SelectedBrushId); m_brushList.index = Mathf.Clamp(m_brushList.index, -1, Tileset.Brushes.Count - 1); m_brushList.elementHeight = Tileset.VisualTileSize.y + 10f; m_brushList.DoLayoutList(); Rect rList = GUILayoutUtility.GetLastRect(); if (e.isMouse && !rList.Contains(e.mousePosition)) { m_brushList.ReleaseKeyboardFocus(); } GUILayout.EndVertical(); } }
public override uint[] GetSubtiles(STETilemap tilemap, int gridX, int gridY, uint tileData) { // Add animated tiles { int brushId = (int)((tileData & Tileset.k_TileDataMask_BrushId) >> 16); bool autotiling_N = AutotileWith(tilemap, brushId, gridX, gridY + 1); bool autotiling_E = AutotileWith(tilemap, brushId, gridX + 1, gridY); bool autotiling_S = AutotileWith(tilemap, brushId, gridX, gridY - 1); bool autotiling_W = AutotileWith(tilemap, brushId, gridX - 1, gridY); int idx = 0; if (autotiling_N) { idx = 1; } if (autotiling_E) { idx |= 2; } if (autotiling_S) { idx |= 4; } if (autotiling_W) { idx |= 8; } TilesetBrush brush = Tileset.FindBrush(Tileset.GetBrushIdFromTileData(TileIds[idx])); if (brush && brush.IsAnimated()) { TilemapChunk.RegisterAnimatedBrush(brush); } } return(null); }
public void AddBrush(TilesetBrush brush) { if (brush.Tileset == this) { if (!m_brushes.Exists(x => x.BrushAsset == brush)) { int id = m_brushes.Count > 0 ? m_brushes[m_brushes.Count - 1].Id : 1; //NOTE: id 0 is reserved for default brush int maxId = (int)(k_TileDataMask_BrushId >> 16); if (m_brushes.Count >= maxId) { Debug.LogError(" Max number of brushes reached! " + maxId); } else { // find a not used id while (m_brushes.Exists(x => x.Id == id)) { ++id; if (id > maxId) { id = 1; } } m_brushes.Add(new BrushContainer() { Id = id, BrushAsset = brush }); m_brushCache.Clear(); } } } else { Debug.LogWarning("This brush " + brush.name + " has a different tileset and will not be added! "); } }
private bool m_displayAutocompleteBtn = false; // fix gui warning when button appears public void Display(Vector2 visualTileSize) { GUI.changed |= m_hasChanged; m_hasChanged = false; Event e = Event.current; bool isLeftMouseReleased = e.type == EventType.MouseUp && e.button == 0; if (isLeftMouseReleased) { m_hasFocus = m_tileSelectionRect.Contains(e.mousePosition); } bool hasEmptyTiles = false; int size = m_width * m_height; Color cSelectedBorderColor = new Color(1f, 1f, 0f, 1f); if (!m_hasFocus) { cSelectedBorderColor *= .8f; } GUILayout.BeginHorizontal(); { // Draw Autotile Combination Control GUI.backgroundColor = Tileset.BackgroundColor; GUILayoutUtility.GetRect(visualTileSize.x * m_width, visualTileSize.y * m_height + 1f); Rect rArea = GUILayoutUtility.GetLastRect(); { if (m_backgroundTexture) { GUI.DrawTexture(new Rect(rArea.position, Vector2.Scale(visualTileSize, new Vector2(m_width, m_height))), m_backgroundTexture); } GUI.backgroundColor = Color.white; for (int tileIdx = 0; tileIdx < size; ++tileIdx) { int gx = tileIdx % m_width; int gy = tileIdx / m_width; Rect rVisualTile = new Rect(gx * visualTileSize.x, gy * visualTileSize.y, visualTileSize.x, visualTileSize.y); rVisualTile.position += rArea.position; uint tileData = m_getTileDataFunc(tileIdx); hasEmptyTiles |= tileData == Tileset.k_TileData_Empty; TilesetBrush brush = Tileset.FindBrush(Tileset.GetBrushIdFromTileData(tileData)); if (brush) { tileData = TilesetBrush.ApplyAndMergeTileFlags(brush.PreviewTileData(), tileData); } int tileId = (int)(tileData & Tileset.k_TileDataMask_TileId); if (tileId != Tileset.k_TileId_Empty) { TilesetEditor.DoGUIDrawTileFromTileData(rVisualTile, tileData, Tileset); } Color bgColor = new Color(1f - Tileset.BackgroundColor.r, 1f - Tileset.BackgroundColor.g, 1f - Tileset.BackgroundColor.b, Tileset.BackgroundColor.a); HandlesEx.DrawRectWithOutline(rVisualTile, m_selectedTileIdx == tileIdx ? new Color(0f, 0f, 0f, 0.1f) : new Color(), m_selectedTileIdx == tileIdx ? cSelectedBorderColor : bgColor); if (isLeftMouseReleased && rVisualTile.Contains(e.mousePosition)) { m_selectedTileIdx = tileIdx; EditorWindow wnd = EditorWindow.focusedWindow; TileSelectionWindow.Show(Tileset); TileSelectionWindow.Instance.Ping(); wnd.Focus(); GUI.FocusControl(""); } } } uint brushTileData = m_selectedTileIdx >= 0 ? m_getTileDataFunc(m_selectedTileIdx) : Tileset.k_TileData_Empty; brushTileData = DoTileDataPropertiesLayout(brushTileData, Tileset, AllowBrushSelection); if (m_selectedTileIdx >= 0) { m_setTileDataFunc(m_selectedTileIdx, brushTileData); } } GUILayout.EndHorizontal(); if (e.type == EventType.Repaint) { m_tileSelectionRect = GUILayoutUtility.GetLastRect(); } m_displayAutocompleteBtn = e.type == EventType.Layout ? !hasEmptyTiles && m_tileIdOff != 0 : m_displayAutocompleteBtn; if (size > 1 && m_displayAutocompleteBtn && GUILayout.Button("Autocomplete relative to last change")) { Undo.RecordObject(m_target, "MultipleTileChanged"); for (int tileIdx = 0; tileIdx < size; ++tileIdx) { if (tileIdx != m_tileIdOffSkipIdx) { int brushTileId = (int)(m_getTileDataFunc(tileIdx) & Tileset.k_TileDataMask_TileId); brushTileId += m_tileIdOff; if (brushTileId < 0 || brushTileId >= m_tileset.Tiles.Count) { m_setTileDataFunc(tileIdx, Tileset.k_TileData_Empty); } else { uint tileData = m_getTileDataFunc(tileIdx); tileData &= ~Tileset.k_TileDataMask_TileId; tileData |= (uint)(brushTileId & Tileset.k_TileDataMask_TileId); m_setTileDataFunc(tileIdx, tileData); } } } m_tileIdOff = 0; EditorUtility.SetDirty(m_target); } if (Tileset.TileSelection != null && Tileset.TileSelection.selectionData.Count == m_width * m_height && Tileset.TileSelection.rowLength == m_width) { if (GUILayout.Button("Autocomplete from selection")) { Undo.RecordObject(m_target, "MultipleTileChanged"); for (int tileIdx = 0; tileIdx < size; ++tileIdx) { int selectionIdx = (tileIdx % m_width) + (m_height - 1 - tileIdx / m_width) * m_width; int brushTileId = (int)(Tileset.TileSelection.selectionData[selectionIdx] & Tileset.k_TileDataMask_TileId); m_setTileDataFunc(tileIdx, (uint)(brushTileId & Tileset.k_TileDataMask_TileId)); } m_tileIdOff = 0; EditorUtility.SetDirty(m_target); } } if (ShowHelpBox) { EditorGUILayout.HelpBox(HelpBoxText, MessageType.Info); } }
public override void OnEnable() { base.OnEnable(); m_brush = (RandomBrush)target; if (m_brush.Tileset != null) { m_brush.Tileset.OnTileSelected += OnTileSelected; m_brush.Tileset.OnBrushSelected += OnBrushSelected; } m_randTileList = new ReorderableList(serializedObject, serializedObject.FindProperty("RandomTileList"), true, true, true, true); m_randTileList.drawHeaderCallback += (Rect rect) => { EditorGUI.LabelField(rect, "Random Tiles", EditorStyles.boldLabel); }; m_randTileList.drawElementCallback += (Rect rect, int index, bool isActive, bool isFocused) => { Rect rTile = rect; rTile.width = rTile.height = m_brush.Tileset.VisualTileSize.y; uint tileData = m_brush.RandomTileList[index].tileData; int tileId = (int)(tileData & Tileset.k_TileDataMask_TileId); int brushId = Tileset.GetBrushIdFromTileData(tileData); TilesetBrush brush = m_brush.Tileset.FindBrush(brushId); if (brush) { GUI.Box(new Rect(rTile.position - Vector2.one, rTile.size + 2 * Vector2.one), ""); TilesetEditor.DoGUIDrawTileFromTileData(rTile, tileData, m_brush.Tileset, brush.GetAnimUV()); } else if (tileId != Tileset.k_TileId_Empty) { GUI.Box(new Rect(rTile.position - Vector2.one, rTile.size + 2 * Vector2.one), ""); TilesetEditor.DoGUIDrawTileFromTileData(rTile, tileData, m_brush.Tileset); } Rect rTileId = rect; rTileId.x += rTile.width + 10; rTileId.width -= rTile.width + 20; rTileId.height = rect.height / 2; if (brush) { GUI.Label(rTileId, "Brush Id(" + brushId + ")"); } else { GUI.Label(rTileId, "Id(" + tileId + ")"); } SerializedProperty randomTileDataProperty = m_randTileList.serializedProperty.GetArrayElementAtIndex(index); SerializedProperty probabilityFactorProperty = randomTileDataProperty.FindPropertyRelative("probabilityFactor"); Rect rProbabilityField = new Rect(rect.x + rTile.width + 10f, rect.y + EditorGUIUtility.singleLineHeight * 2.5f, rect.width - rTile.width - 10f, EditorGUIUtility.singleLineHeight); Rect rProbabilityLabel = new Rect(rProbabilityField.x, rProbabilityField.y - EditorGUIUtility.singleLineHeight, rProbabilityField.width, rProbabilityField.height); float sumProbabilityFactor = m_brush.GetSumProbabilityFactor(); float probability = sumProbabilityFactor >= 0 ? probabilityFactorProperty.floatValue * 100f / sumProbabilityFactor : 100f; EditorGUI.PrefixLabel(rProbabilityLabel, new GUIContent("Probability (" + Mathf.RoundToInt(probability) + "%)")); EditorGUI.PropertyField(rProbabilityField, probabilityFactorProperty, GUIContent.none); if (probabilityFactorProperty.floatValue == 0f) { serializedObject.ApplyModifiedProperties(); sumProbabilityFactor = m_brush.GetSumProbabilityFactor(); if (sumProbabilityFactor <= 0f) { probabilityFactorProperty.floatValue = 0.01f; } } if (GUI.Button(new Rect(rect.x + rect.width - 50f, rect.y, 50f, EditorGUIUtility.singleLineHeight), "Clear")) { m_brush.RandomTileList[index].tileData = Tileset.k_TileData_Empty; } }; m_randTileList.onSelectCallback += (ReorderableList list) => { TileSelectionWindow.Show(m_brush.Tileset); TileSelectionWindow.Instance.Ping(); }; m_randTileList.onAddCallback += (ReorderableList list) => { if (list.index >= 0) { list.serializedProperty.InsertArrayElementAtIndex(list.index); } else { list.serializedProperty.InsertArrayElementAtIndex(0); } list.index = Mathf.Max(0, list.index + 1); list.serializedProperty.serializedObject.ApplyModifiedProperties(); m_brush.RandomTileList[list.index].probabilityFactor = 1f; if (m_brush.Tileset.SelectedTile != null) { m_randTileList.GrabKeyboardFocus(); OnTileSelected(m_brush.Tileset, -1, m_brush.Tileset.SelectedTileId); } }; }
public void SetTileData(int locGridX, int locGridY, uint tileData) { if (locGridX >= 0 && locGridX < m_width && locGridY >= 0 && locGridY < m_height) { int tileIdx = locGridY * m_width + locGridX; int tileId = (int)(tileData & Tileset.k_TileDataMask_TileId); Tile tile = Tileset.GetTile(tileId); int prevTileId = (int)(m_tileDataList[tileIdx] & Tileset.k_TileDataMask_TileId); Tile prevTile = Tileset.GetTile(prevTileId); int brushId = Tileset.GetBrushIdFromTileData(tileData); int prevBrushId = Tileset.GetBrushIdFromTileData(m_tileDataList[tileIdx]); if (brushId != prevBrushId || brushId == 0) //NOTE: because of the autotiling mode, neighbour tiles could be affected by this change, even if the tile is not a brush { if (!s_currUpdatedTilechunk) // avoid this is chunks is being Updated from FillMeshData { // Refresh Neighbors ( and itself if needed ) for (int yf = -1; yf <= 1; ++yf) { for (int xf = -1; xf <= 1; ++xf) { if ((xf | yf) == 0) { if (brushId > 0) { // Refresh itself tileData = (tileData & ~Tileset.k_TileFlag_Updated); } } else { int gx = (locGridX + xf); int gy = (locGridY + yf); int idx = gy * m_width + gx; bool isInsideChunk = (gx >= 0 && gx < m_width && gy >= 0 && gy < m_height); uint neighborTileData = isInsideChunk ? m_tileDataList[idx] : ParentTilemap.GetTileData(GridPosX + locGridX + xf, GridPosY + locGridY + yf); int neighborBrushId = (int)((neighborTileData & Tileset.k_TileDataMask_BrushId) >> 16); TilesetBrush neighborBrush = ParentTilemap.Tileset.FindBrush(neighborBrushId); if (neighborBrush != null && (neighborBrush.AutotileWith(ParentTilemap.Tileset, neighborBrushId, tileData) || neighborBrush.AutotileWith(ParentTilemap.Tileset, neighborBrushId, m_tileDataList[tileIdx]))) { neighborTileData = (neighborTileData & ~Tileset.k_TileFlag_Updated); // force a refresh if (isInsideChunk) { m_tileDataList[idx] = neighborTileData; } else { ParentTilemap.SetTileData(GridPosX + gx, GridPosY + gy, neighborTileData); } } } } } } } else if (brushId > 0) { // Refresh itself tileData = (tileData & ~Tileset.k_TileFlag_Updated); } m_needsRebuildMesh |= (m_tileDataList[tileIdx] != tileData) || (tileData & Tileset.k_TileDataMask_TileId) == Tileset.k_TileId_Empty; m_needsRebuildColliders |= m_needsRebuildMesh && ( (prevBrushId > 0) || (brushId > 0) || // there is a brush (a brush could change the collider data later) (tile != null && tile.collData.type != eTileCollider.None) || (prevTile != null && prevTile.collData.type != eTileCollider.None) // prev. or new tile has colliders ); if (ParentTilemap.ColliderType != eColliderType.None && m_needsRebuildColliders) { // Refresh Neighbors tilechunk colliders, to make the collider autotiling // Only if neighbor is outside this tilechunk for (int yf = -1; yf <= 1; ++yf) { for (int xf = -1; xf <= 1; ++xf) { if ((xf | yf) != 0) // skip this tile position xf = yf = 0 { int gx = (locGridX + xf); int gy = (locGridY + yf); bool isInsideChunk = (gx >= 0 && gx < m_width && gy >= 0 && gy < m_height); if (!isInsideChunk) { ParentTilemap.InvalidateChunkAt(GridPosX + gx, GridPosY + gy, false, true); } } } } } // Update tile data m_tileDataList[tileIdx] = tileData; if (!STETilemap.DisableTilePrefabCreation) { // Create tile Objects if (tile != null && tile.prefabData.prefab != null) { CreateTileObject(tileIdx, tile.prefabData); } else { DestroyTileObject(tileIdx); } } TilesetBrush brush = ParentTilemap.Tileset.FindBrush(brushId); if (brushId != prevBrushId) { TilesetBrush prevBrush = ParentTilemap.Tileset.FindBrush(prevBrushId); if (prevBrush != null) { prevBrush.OnErase(this, locGridX, locGridY, tileData, prevBrushId); } } if (brush != null) { tileData = brush.OnPaint(this, locGridX, locGridY, tileData); } } }
public void Display() { Event e = Event.current; m_dblClick.Update(); // This way a gui exception is avoided if (e.type == EventType.Layout && m_selectBrushInInspector != null) { Selection.activeObject = m_selectBrushInInspector; m_selectBrushInInspector = null; } if (m_lastTime == 0f) { m_lastTime = Time.realtimeSinceStartup; } m_timeDt = Time.realtimeSinceStartup - m_lastTime; m_lastTime = Time.realtimeSinceStartup; if (Tileset == null) { EditorGUILayout.HelpBox("There is no tileset selected", MessageType.Info); return; } else if (Tileset.AtlasTexture == null) { EditorGUILayout.HelpBox("There is no atlas texture set", MessageType.Info); return; } else if (Tileset.Tiles.Count == 0) { EditorGUILayout.HelpBox("There are no tiles to show in the current tileset", MessageType.Info); return; } if (m_scrollStyle == null) { m_scrollStyle = new GUIStyle("ScrollView"); } if (m_customBox == null) { m_customBox = new GUIStyle("Box"); } float visualTilePadding = 1; bool isLeftMouseReleased = e.type == EventType.MouseUp && e.button == 0; bool isRightMouseReleased = e.type == EventType.MouseUp && e.button == 1; bool isInsideTileScrollArea = e.isMouse && m_rTileScrollArea.Contains(e.mousePosition); bool isInsideBrushScrollArea = e.isMouse && m_rBrushScrollArea.Contains(e.mousePosition); // TileViews if (m_tileViewList == null || m_tileViewList.list != Tileset.TileViews) { if (e.type != EventType.Layout) { m_tileViewList = TilesetEditor.CreateTileViewReorderableList(Tileset); m_tileViewList.onSelectCallback += (ReorderableList list) => { m_viewMode = eViewMode.TileView; RemoveTileSelection(); }; m_tileViewList.onRemoveCallback += (ReorderableList list) => { RemoveTileSelection(); }; } } else { GUI.color = Color.cyan; GUILayout.BeginVertical(m_customBox); m_tileViewList.index = Mathf.Clamp(m_tileViewList.index, -1, Tileset.TileViews.Count - 1); m_tileViewList.DoLayoutList(); Rect rList = GUILayoutUtility.GetLastRect(); if (e.isMouse && !rList.Contains(e.mousePosition)) { m_tileViewList.ReleaseKeyboardFocus(); } GUILayout.EndVertical(); GUI.color = Color.white; } TileView tileView = m_tileViewList != null && m_tileViewList.index >= 0 ? Tileset.TileViews[m_tileViewList.index] : null; if (m_viewMode == eViewMode.Tileset) { Tileset.TileRowLength = Mathf.Clamp(EditorGUILayout.IntField("TileRowLength", Tileset.TileRowLength), 1, Tileset.Width); } m_viewMode = (eViewMode)EditorGUILayout.EnumPopup("View Mode", m_viewMode); if (tileView == null) { m_viewMode = eViewMode.Tileset; } if (m_viewMode != m_prevViewMode) { m_prevViewMode = m_viewMode; RemoveTileSelection(); } // Draw Background Color Selector Tileset.BackgroundColor = EditorGUILayout.ColorField("Background Color", Tileset.BackgroundColor); if (m_prevBgColor != Tileset.BackgroundColor || m_scrollStyle.normal.background == null) { m_prevBgColor = Tileset.BackgroundColor; if (m_scrollStyle.normal.background == null) { m_scrollStyle.normal.background = new Texture2D(1, 1) { hideFlags = HideFlags.DontSave } } ; m_scrollStyle.normal.background.SetPixel(0, 0, Tileset.BackgroundColor); m_scrollStyle.normal.background.Apply(); } //--- string sTileIdLabel = Tileset.SelectedTileId != Tileset.k_TileId_Empty? " (id:" + Tileset.SelectedTileId + ")" : ""; EditorGUILayout.LabelField("Tile Palette" + sTileIdLabel, EditorStyles.boldLabel); // keeps values safe m_tileViewRowLength = Mathf.Max(1, m_tileViewRowLength); float tileAreaWidth = m_tileViewRowLength * (Tileset.VisualTileSize.x + visualTilePadding) + 4f; float tileAreaHeight = (Tileset.VisualTileSize.y + visualTilePadding) * (1 + (m_visibleTileCount - 1) / m_tileViewRowLength) + 4f; m_tileViewRowLength = m_viewMode == eViewMode.TileView && tileView != null ? tileView.tileSelection.rowLength : Tileset.TileRowLength; m_tilesScrollPos = EditorGUILayout.BeginScrollView(m_tilesScrollPos, m_scrollStyle); { // Scroll Moving Drag if (e.type == EventType.MouseDrag && (e.button == 1 || e.button == 2)) { m_tilesScrollPos -= e.delta; } else { DoAutoScroll(); } if (e.isMouse) { m_lastTileScrollMousePos = e.mousePosition; } if (Tileset.Tiles != null) { GUILayoutUtility.GetRect(tileAreaWidth, tileAreaHeight); m_visibleTileCount = 0; List <uint> visibleTileList = new List <uint>(); int tileViewWidth = m_viewMode == eViewMode.Tileset ? Tileset.Width : tileView.tileSelection.rowLength; int tileViewHeight = m_viewMode == eViewMode.Tileset ? Tileset.Height : ((tileView.tileSelection.selectionData.Count - 1) / tileView.tileSelection.rowLength) + 1; int totalCount = ((((tileViewWidth - 1) / m_tileViewRowLength) + 1) * m_tileViewRowLength) * tileViewHeight; for (int i = 0; i < totalCount; ++i) { int tileId = GetTileIdFromIdx(i, m_tileViewRowLength, tileViewWidth, tileViewHeight); uint tileData = (uint)tileId; if (m_viewMode == eViewMode.TileView && tileId != Tileset.k_TileId_Empty) { tileData = tileView.tileSelection.selectionData[tileId]; tileId = (int)(tileData & Tileset.k_TileDataMask_TileId); } Tile tile = tileId != Tileset.k_TileId_Empty && tileId < Tileset.Tiles.Count ? Tileset.Tiles[tileId] : null; visibleTileList.Add(tileData); int tx = m_visibleTileCount % m_tileViewRowLength; int ty = m_visibleTileCount / m_tileViewRowLength; Rect rVisualTile = new Rect(2 + tx * (Tileset.VisualTileSize.x + visualTilePadding), 2 + ty * (Tileset.VisualTileSize.y + visualTilePadding), Tileset.VisualTileSize.x, Tileset.VisualTileSize.y); // Optimization, skipping not visible tiles Rect rLocalVisualTile = rVisualTile; rLocalVisualTile.position -= m_tilesScrollPos; if (!rLocalVisualTile.Overlaps(m_rTileScrollSize)) { ; // Do Nothing } else //--- { // Draw Tile if (tile == null) { HandlesEx.DrawRectWithOutline(rVisualTile, new Color(0f, 0f, 0f, 0.2f), new Color(0f, 0f, 0f, 0.2f)); } else { HandlesEx.DrawRectWithOutline(rVisualTile, new Color(0f, 0f, 0f, 0.1f), new Color(0f, 0f, 0f, 0.1f)); TilesetEditor.DoGUIDrawTileFromTileData(rVisualTile, tileData, Tileset); } Rect rTileRect = new Rect(2 + tx * (Tileset.VisualTileSize.x + visualTilePadding), 2 + ty * (Tileset.VisualTileSize.y + visualTilePadding), (Tileset.VisualTileSize.x + visualTilePadding), (Tileset.VisualTileSize.y + visualTilePadding)); if (rVisualTile.Contains(e.mousePosition)) { if (e.type == EventType.MouseDrag && e.button == 0) { m_pointedTileIdxRect = new KeyValuePair <int, Rect>(m_visibleTileCount, rTileRect); } else if (e.type == EventType.MouseDown && e.button == 0) { m_startDragTileIdxRect = m_pointedTileIdxRect = m_endDragTileIdxRect = new KeyValuePair <int, Rect>(m_visibleTileCount, rTileRect); } else if (e.type == EventType.MouseUp && e.button == 0) { m_endDragTileIdxRect = new KeyValuePair <int, Rect>(m_visibleTileCount, rTileRect); DoSetTileSelection(); } } if ((isLeftMouseReleased || isRightMouseReleased) && isInsideTileScrollArea && rVisualTile.Contains(e.mousePosition) && (m_startDragTileIdxRect.Key == m_endDragTileIdxRect.Key) && // and there is not dragging selection m_rTileScrollSize.Contains(e.mousePosition - m_tilesScrollPos)) // and it's inside the scroll area { Tileset.SelectedTileId = tileId; //Give focus to SceneView to get key events FocusSceneView(); if (isRightMouseReleased) { TilePropertiesWindow.Show(Tileset); } } else if (tile != null && Tileset.SelectedTileId == tileId) { HandlesEx.DrawRectWithOutline(rTileRect, new Color(0f, 0f, 0f, 0.1f), new Color(1f, 1f, 0f, 1f)); } } ++m_visibleTileCount; } m_visibleTileList = visibleTileList; // Draw selection rect if (m_startDragTileIdxRect.Key != m_pointedTileIdxRect.Key /*&& m_startDragTileIdxRect.Key == m_endDragTileIdxRect.Key*/) { Rect rSelection = new Rect(m_startDragTileIdxRect.Value.center, m_pointedTileIdxRect.Value.center - m_startDragTileIdxRect.Value.center); rSelection.Set(Mathf.Min(rSelection.xMin, rSelection.xMax), Mathf.Min(rSelection.yMin, rSelection.yMax), Mathf.Abs(rSelection.width), Mathf.Abs(rSelection.height)); rSelection.xMin -= m_startDragTileIdxRect.Value.width / 2; rSelection.xMax += m_startDragTileIdxRect.Value.width / 2; rSelection.yMin -= m_startDragTileIdxRect.Value.height / 2; rSelection.yMax += m_startDragTileIdxRect.Value.height / 2; HandlesEx.DrawRectWithOutline(rSelection, new Color(0f, 0f, 0f, 0.1f), new Color(1f, 1f, 1f, 1f)); } } } EditorGUILayout.EndScrollView(); if (e.type == EventType.Repaint) { m_rTileScrollArea = GUILayoutUtility.GetLastRect(); m_rTileScrollSize = m_rTileScrollArea; m_rTileScrollSize.position = Vector2.zero; // reset position to the Contains and Overlaps inside the tile scroll view without repositioning the position of local positions if (tileAreaWidth > m_rTileScrollSize.width) { m_rTileScrollSize.height -= GUI.skin.verticalScrollbar.fixedWidth; } if (tileAreaHeight > m_rTileScrollSize.height) { m_rTileScrollSize.width -= GUI.skin.verticalScrollbar.fixedWidth; } } EditorGUILayout.BeginHorizontal(); string sBrushIdLabel = Tileset.SelectedBrushId > 0 ? " (id:" + Tileset.SelectedBrushId + ")" : ""; EditorGUILayout.LabelField("Brush Palette" + sBrushIdLabel, EditorStyles.boldLabel); m_displayBrushReordList = EditorUtils.DoToggleButton("Display List", m_displayBrushReordList); EditorGUILayout.EndHorizontal(); int tileRowLength = (int)(m_rTileScrollSize.width / (Tileset.VisualTileSize.x + visualTilePadding)); if (tileRowLength <= 0) { tileRowLength = 1; } float fBrushesScrollMaxHeight = Screen.height / 4; //commented because m_rTileScrollSize.width.height was changed to Screen.height; fBrushesScrollMaxHeight -= fBrushesScrollMaxHeight % 2; // sometimes because size of tile scroll affects size of brush scroll, the height is dancing between +-1, so this is always taking the pair value float fBrushesScrollHeight = Mathf.Min(fBrushesScrollMaxHeight, 4 + (Tileset.VisualTileSize.y + visualTilePadding) * (1 + (Tileset.Brushes.Count / tileRowLength))); EditorGUILayout.BeginVertical(GUILayout.MinHeight(fBrushesScrollHeight)); if (m_displayBrushReordList) { DisplayBrushReorderableList(); } else { bool isRefreshBrushes = false; m_brushesScrollPos = EditorGUILayout.BeginScrollView(m_brushesScrollPos, m_scrollStyle); { Rect rScrollView = new Rect(0, 0, m_rTileScrollSize.width, 0); tileRowLength = Mathf.Clamp((int)rScrollView.width / (int)(Tileset.VisualTileSize.x + visualTilePadding), 1, tileRowLength); if (Tileset.Brushes != null) { GUILayout.Space((Tileset.VisualTileSize.y + visualTilePadding) * (1 + (Tileset.Brushes.Count - 1) / tileRowLength)); for (int i = 0; i < Tileset.Brushes.Count; ++i) { Tileset.BrushContainer brushCont = Tileset.Brushes[i]; if (brushCont.BrushAsset == null) { isRefreshBrushes = true; continue; } int tx = i % tileRowLength; int ty = i / tileRowLength; Rect rVisualTile = new Rect(2 + tx * (Tileset.VisualTileSize.x + visualTilePadding), 2 + ty * (Tileset.VisualTileSize.y + visualTilePadding), Tileset.VisualTileSize.x, Tileset.VisualTileSize.y); //Fix Missing Tileset reference if (brushCont.BrushAsset.Tileset == null) { Debug.LogWarning("Fixed missing tileset reference in brush " + brushCont.BrushAsset.name + " Id(" + brushCont.Id + ")"); brushCont.BrushAsset.Tileset = Tileset; } uint tileData = Tileset.k_TileData_Empty; if (brushCont.BrushAsset.IsAnimated()) { tileData = brushCont.BrushAsset.GetAnimTileData(); } else { tileData = brushCont.BrushAsset.PreviewTileData(); } TilesetEditor.DoGUIDrawTileFromTileData(rVisualTile, tileData, Tileset, brushCont.BrushAsset.GetAnimUV()); if ((isLeftMouseReleased || isRightMouseReleased || m_dblClick.IsDblClick) && isInsideBrushScrollArea && rVisualTile.Contains(Event.current.mousePosition)) { Tileset.SelectedBrushId = brushCont.Id; RemoveTileSelection(); if (m_dblClick.IsDblClick) { EditorGUIUtility.PingObject(brushCont.BrushAsset); m_selectBrushInInspector = brushCont.BrushAsset; } if (isRightMouseReleased) { TilePropertiesWindow.Show(Tileset); } } else if (Tileset.SelectedBrushId == brushCont.Id) { Rect rSelection = new Rect(2 + tx * (Tileset.VisualTileSize.x + visualTilePadding), 2 + ty * (Tileset.VisualTileSize.y + visualTilePadding), (Tileset.VisualTileSize.x + visualTilePadding), (Tileset.VisualTileSize.y + visualTilePadding)); HandlesEx.DrawRectWithOutline(rSelection, new Color(0f, 0f, 0f, 0.1f), new Color(1f, 1f, 0f, 1f)); } } } if (isRefreshBrushes) { Tileset.RemoveNullBrushes(); } } EditorGUILayout.EndScrollView(); if (e.type == EventType.Repaint) { m_rBrushScrollArea = GUILayoutUtility.GetLastRect(); } } EditorGUILayout.EndVertical(); if (GUILayout.Button("Import all brushes found")) { TilesetEditor.AddAllBrushesFoundInTheProject(Tileset); EditorUtility.SetDirty(Tileset); } }
// '°', '├', '═', '┤', | 0, 2, 10, 8, // '┬', '╔', '╦', '╗', | 4, 6, 14, 12, // '║', '╠', '╬', '╣', | 5, 7, 15, 13, // '┴', '╚', '╩', '╝', | 1, 3, 11, 9, public override uint[] GetSubtiles(STETilemap tilemap, int gridX, int gridY, uint tileData) { CalculateNeighbourData(tilemap, gridX, gridY, tileData); // tiles that need subtile division if (s_needsSubTiles) { uint[] aSubTileData = null; if (s_neighIdx == 0) //° { aSubTileData = new uint[] { TileIds[3], TileIds[9], TileIds[6], TileIds[12] }; } else if (s_neighIdx == 4)//┬ { aSubTileData = new uint[] { TileIds[6], TileIds[12], TileIds[6], TileIds[12] }; } else if (s_neighIdx == 5)//║ { aSubTileData = new uint[] { TileIds[7], TileIds[13], TileIds[7], TileIds[13] }; } else if (s_neighIdx == 1)//┴ { aSubTileData = new uint[] { TileIds[3], TileIds[9], TileIds[3], TileIds[9] }; } else if (s_neighIdx == 2)//├ { aSubTileData = new uint[] { TileIds[3], TileIds[3], TileIds[6], TileIds[6] }; } else if (s_neighIdx == 10)//═ { aSubTileData = new uint[] { TileIds[11], TileIds[11], TileIds[14], TileIds[14] }; } else if (s_neighIdx == 8)//┤ { aSubTileData = new uint[] { TileIds[9], TileIds[9], TileIds[12], TileIds[12] }; } // NOTE: this case '╬' cut the tiles different (using corner tiles). // If it is commented, and default case is used, instead or corner tiles, it will use the center tile '╬' // Depending on the graphics it could be interesting add a check box to choose between using this or not. else if (s_neighIdx == 15)// ╬ { aSubTileData = new uint[] { InteriorCornerTileIds[0], InteriorCornerTileIds[1], InteriorCornerTileIds[2], InteriorCornerTileIds[3] }; } else { aSubTileData = new uint[] { TileIds[s_neighIdx], TileIds[s_neighIdx], TileIds[s_neighIdx], TileIds[s_neighIdx] }; } for (int i = 0; i < s_showDiagonal.Length; ++i) { aSubTileData[i] = RefreshLinkedBrush(tilemap, gridX, gridY, aSubTileData[i]); if (s_showDiagonal[i]) { aSubTileData[i] = InteriorCornerTileIds[3 - i]; } // Add animated tiles { TilesetBrush brush = Tileset.FindBrush(Tileset.GetBrushIdFromTileData(aSubTileData[i])); if (brush && brush.IsAnimated()) { TilemapChunk.RegisterAnimatedBrush(brush, i); } } } return(aSubTileData); } // Add animated tiles { TilesetBrush brush = Tileset.FindBrush(Tileset.GetBrushIdFromTileData(s_tileData)); if (brush && brush.IsAnimated()) { TilemapChunk.RegisterAnimatedBrush(brush); } } return(null); }
private void UpdateMeshVertexColor() { //Debug.Log( "[" + ParentTilemap.name + "] FillData -> " + name); if (!Tileset || !Tileset.AtlasTexture) { return; } int totalTiles = m_width * m_height; if (s_colors32 == null) { s_colors32 = new List <Color32>(totalTiles * 4); } else { s_colors32.Clear(); } for (int ty = 0, tileIdx = 0; ty < m_height; ++ty) { for (int tx = 0; tx < m_width; ++tx, ++tileIdx) { uint tileData = m_tileDataList[tileIdx]; if (tileData != Tileset.k_TileData_Empty) { int brushId = (int)((tileData & Tileset.k_TileDataMask_BrushId) >> 16); int tileId = (int)(tileData & Tileset.k_TileDataMask_TileId); Tile tile = Tileset.GetTile(tileId); TilesetBrush tileBrush = null; if (brushId > 0) { tileBrush = Tileset.FindBrush(brushId); } uint[] subtileData = tileBrush != null?tileBrush.GetSubtiles(ParentTilemap, GridPosX + tx, GridPosY + ty, tileData) : null; if (subtileData == null) { if (tile != null) { if (tile.prefabData.prefab == null || tile.prefabData.showTileWithPrefab || //hide the tiles with prefabs ( unless showTileWithPrefab is true ) tileBrush && tileBrush.IsAnimated()) // ( skip if it's an animated brush ) { if (m_tileColorList != null && m_tileColorList.Count > tileIdx) { TileColor32 tileColor32 = m_tileColorList[tileIdx]; s_colors32.Add(tileColor32.c0); s_colors32.Add(tileColor32.c1); s_colors32.Add(tileColor32.c2); s_colors32.Add(tileColor32.c3); } } } } else { for (int i = 0; i < subtileData.Length; ++i) { //if (tileUV != default(Rect)) //NOTE: if this is uncommented, there won't be coherence with geometry ( 16 vertices per tiles with subtiles ). But it means also, the tile shouldn't be null. { if (m_tileColorList != null && m_tileColorList.Count > tileIdx) { TileColor32 tileColor32 = m_tileColorList[tileIdx]; Color32 middleColor = new Color32( System.Convert.ToByte((tileColor32.c0.r + tileColor32.c1.r + tileColor32.c2.r + tileColor32.c3.r) >> 2), System.Convert.ToByte((tileColor32.c0.g + tileColor32.c1.g + tileColor32.c2.g + tileColor32.c3.g) >> 2), System.Convert.ToByte((tileColor32.c0.b + tileColor32.c1.b + tileColor32.c2.b + tileColor32.c3.b) >> 2), System.Convert.ToByte((tileColor32.c0.a + tileColor32.c1.a + tileColor32.c2.a + tileColor32.c3.a) >> 2) ); switch (i) { case 0: s_colors32.Add(tileColor32.c0); s_colors32.Add(Color32.Lerp(tileColor32.c1, tileColor32.c0, .5f)); s_colors32.Add(Color32.Lerp(tileColor32.c2, tileColor32.c0, .5f)); s_colors32.Add(middleColor); break; case 1: s_colors32.Add(Color32.Lerp(tileColor32.c0, tileColor32.c1, .5f)); s_colors32.Add(tileColor32.c1); s_colors32.Add(middleColor); s_colors32.Add(Color32.Lerp(tileColor32.c3, tileColor32.c1, .5f)); break; case 2: s_colors32.Add(Color32.Lerp(tileColor32.c0, tileColor32.c2, .5f)); s_colors32.Add(middleColor); s_colors32.Add(tileColor32.c2); s_colors32.Add(Color32.Lerp(tileColor32.c3, tileColor32.c2, .5f)); break; case 3: s_colors32.Add(middleColor); s_colors32.Add(Color32.Lerp(tileColor32.c1, tileColor32.c3, .5f)); s_colors32.Add(Color32.Lerp(tileColor32.c2, tileColor32.c3, .5f)); s_colors32.Add(tileColor32.c3); break; } } } } } } } } }
/* * private void DummyDeepProfilingFix() * { * // For some reason, in Unity 2017.3.1f1, the Deep Profiling crashes unless FillMeshData call any method, even a dummy method like this * // Other weird thing is, the crash doesn't happens if one case of the switch statement is commented * // FINALLY: the fix was to change the Switch for if-else statements. I keep this notes just in case to remember about this weird issue. * } */ /// <summary> /// Fill the mesh data and return false if all tiles are empty /// </summary> /// <returns></returns> private bool FillMeshData() { //Debug.Log( "[" + ParentTilemap.name + "] FillData -> " + name); //DummyDeepProfilingFix(); if (!Tileset || !Tileset.AtlasTexture) { return(false); } s_currUpdatedTilechunk = this; int totalTiles = m_width * m_height; if (s_vertices == null) { s_vertices = new List <Vector3>(totalTiles * 4); } else { s_vertices.Clear(); } if (s_triangles == null) { s_triangles = new List <int>(totalTiles * 6); } else { s_triangles.Clear(); } if (s_colors32 == null) { s_colors32 = new List <Color32>(totalTiles * 4); } else { s_colors32.Clear(); } if (m_uv == null) { m_uv = new List <Vector2>(totalTiles * 4); } else { m_uv.Clear(); } Vector2[] subTileOffset = new Vector2[] { new Vector2(0f, 0f), new Vector2(CellSize.x / 2f, 0f), new Vector2(0f, CellSize.y / 2f), new Vector2(CellSize.x / 2f, CellSize.y / 2f), }; Vector2 subTileSize = CellSize / 2f; m_animatedTiles.Clear(); bool isEmpty = true; for (int ty = 0, tileIdx = 0; ty < m_height; ++ty) { for (int tx = 0; tx < m_width; ++tx, ++tileIdx) { uint tileData = m_tileDataList[tileIdx]; if (tileData != Tileset.k_TileData_Empty) { int brushId = (int)((tileData & Tileset.k_TileDataMask_BrushId) >> 16); int tileId = (int)(tileData & Tileset.k_TileDataMask_TileId); Tile tile = Tileset.GetTile(tileId); TilesetBrush tileBrush = null; if (tileId >= 0 && tile == null && brushId <= 0) { Debug.LogWarning(ParentTilemap.name + "\\" + name + ": TileId " + tileId + " not found! GridPos(" + (GridPosX + tx) + "," + (GridPosY + ty) + ") tilaData 0x" + tileData.ToString("X")); m_tileDataList[tileIdx] = Tileset.k_TileData_Empty; } if (brushId > 0) { tileBrush = Tileset.FindBrush(brushId); if (tileBrush == null) { Debug.LogWarning(ParentTilemap.name + "\\" + name + ": BrushId " + brushId + " not found! GridPos(" + (GridPosX + tx) + "," + (GridPosY + ty) + ") tilaData 0x" + tileData.ToString("X")); m_tileDataList[tileIdx] = tileData & ~Tileset.k_TileDataMask_BrushId; } if (tileBrush != null && (m_invalidateBrushes || (tileData & Tileset.k_TileFlag_Updated) == 0)) { tileData = tileBrush.Refresh(ParentTilemap, GridPosX + tx, GridPosY + ty, tileData); //+++NOTE: this code add support for animated brushes inside a random brush // Collateral effects of supporting changing the brush id in Refresh: // - When the random brush select a tile data with another brush id, this tile won't be a random tile any more // - If the tilemap is refreshed several times, and at least a tile data contains another brush id, then all tiles will loose the brush id of the random brush if (BrushBehaviour.Instance.BrushTilemap == ParentTilemap) // avoid changing brushId when updating the BrushTilemap { tileData &= ~Tileset.k_TileDataMask_BrushId; tileData |= (uint)(brushId << 16); } int newBrushId = (int)((tileData & Tileset.k_TileDataMask_BrushId) >> 16); if (brushId != newBrushId) { brushId = newBrushId; tileBrush = Tileset.FindBrush(brushId); } //--- tileData |= Tileset.k_TileFlag_Updated; // set updated flag m_tileDataList[tileIdx] = tileData; // update tileData tileId = (int)(tileData & Tileset.k_TileDataMask_TileId); tile = Tileset.GetTile(tileId); // update created objects if (tile != null && tile.prefabData.prefab != null) { CreateTileObject(tileIdx, tile.prefabData); } else { DestroyTileObject(tileIdx); } } } isEmpty = false; if (tileBrush != null && tileBrush.IsAnimated()) { m_animatedTiles.Add(new AnimTileData() { VertexIdx = s_vertices.Count, Brush = tileBrush, SubTileIdx = -1 }); } s_currUVVertex = s_vertices.Count; Rect tileUV; uint[] subtileData = tileBrush != null?tileBrush.GetSubtiles(ParentTilemap, GridPosX + tx, GridPosY + ty, tileData) : null; if (subtileData == null) { if (tile != null) { if (tile.prefabData.prefab == null || tile.prefabData.showTileWithPrefab || //hide the tiles with prefabs ( unless showTileWithPrefab is true ) tileBrush && tileBrush.IsAnimated()) // ( skip if it's an animated brush ) { tileUV = tile.uv; _AddTileToMesh(tileUV, tx, ty, tileData, Vector2.zero, CellSize); if (m_tileColorList != null && m_tileColorList.Count > tileIdx) { TileColor32 tileColor32 = m_tileColorList[tileIdx]; s_colors32.Add(tileColor32.c0); s_colors32.Add(tileColor32.c1); s_colors32.Add(tileColor32.c2); s_colors32.Add(tileColor32.c3); } } } } else { for (int i = 0; i < subtileData.Length; ++i) { uint subTileData = subtileData[i]; int subTileId = (int)(subTileData & Tileset.k_TileDataMask_TileId); Tile subTile = Tileset.GetTile(subTileId); tileUV = subTile != null ? subTile.uv : default(Rect); //if (tileUV != default(Rect)) //NOTE: if this is uncommented, there won't be coherence with geometry ( 16 vertices per tiles with subtiles ). But it means also, the tile shouldn't be null. { _AddTileToMesh(tileUV, tx, ty, subTileData, subTileOffset[i], subTileSize, i); if (m_tileColorList != null && m_tileColorList.Count > tileIdx) { TileColor32 tileColor32 = m_tileColorList[tileIdx]; Color32 middleColor = new Color32( System.Convert.ToByte((tileColor32.c0.r + tileColor32.c1.r + tileColor32.c2.r + tileColor32.c3.r) >> 2), System.Convert.ToByte((tileColor32.c0.g + tileColor32.c1.g + tileColor32.c2.g + tileColor32.c3.g) >> 2), System.Convert.ToByte((tileColor32.c0.b + tileColor32.c1.b + tileColor32.c2.b + tileColor32.c3.b) >> 2), System.Convert.ToByte((tileColor32.c0.a + tileColor32.c1.a + tileColor32.c2.a + tileColor32.c3.a) >> 2) ); //switch(i) // FIX Deep Profiling crash in Unity 2017.3.1f1 see: DummyDeepProfilingFix notes { if (i == 0) { s_colors32.Add(tileColor32.c0); s_colors32.Add(Color32.Lerp(tileColor32.c1, tileColor32.c0, .5f)); s_colors32.Add(Color32.Lerp(tileColor32.c2, tileColor32.c0, .5f)); s_colors32.Add(middleColor); } else if (i == 1) { s_colors32.Add(Color32.Lerp(tileColor32.c0, tileColor32.c1, .5f)); s_colors32.Add(tileColor32.c1); s_colors32.Add(middleColor); s_colors32.Add(Color32.Lerp(tileColor32.c3, tileColor32.c1, .5f)); } else if (i == 2) { s_colors32.Add(Color32.Lerp(tileColor32.c0, tileColor32.c2, .5f)); s_colors32.Add(middleColor); s_colors32.Add(tileColor32.c2); s_colors32.Add(Color32.Lerp(tileColor32.c3, tileColor32.c2, .5f)); } else if (i == 3) { s_colors32.Add(middleColor); s_colors32.Add(Color32.Lerp(tileColor32.c1, tileColor32.c3, .5f)); s_colors32.Add(Color32.Lerp(tileColor32.c2, tileColor32.c3, .5f)); s_colors32.Add(tileColor32.c3); } } } } } } } } } //NOTE: the destruction of tileobjects needs to be done here to avoid a Undo/Redo bug. Check inside DestroyTileObject for more information. for (int i = 0; i < m_tileObjToBeRemoved.Count; ++i) { DestroyTileObject(m_tileObjToBeRemoved[i]); } m_tileObjToBeRemoved.Clear(); s_currUpdatedTilechunk = null; return(!isEmpty); }