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 = tileId != Tileset.k_TileId_Empty? Tileset.Tiles[tileId] : null; int prevTileId = (int)(m_tileDataList[tileIdx] & Tileset.k_TileDataMask_TileId); Tile prevTile = prevTileId != Tileset.k_TileId_Empty? Tileset.Tiles[prevTileId] : null; int brushId = Tileset.GetBrushIdFromTileData(tileData); int prevBrushId = Tileset.GetBrushIdFromTileData(m_tileDataList[tileIdx]); if (brushId != prevBrushId) { TilesetBrush brush = ParentTilemap.Tileset.FindBrush(brushId); TilesetBrush prevBrush = ParentTilemap.Tileset.FindBrush(prevBrushId); if (prevBrush != null) { prevBrush.OnErase(this, locGridX, locGridY, tileData); } if (brush != null) { tileData = brush.OnPaint(this, locGridX, locGridY, tileData); } // 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 (brush != null && brush.AutotileWith(brushId, neighborBrushId) || prevBrush != null && prevBrush.AutotileWith(prevBrushId, neighborBrushId)) if (neighborBrush != null && (neighborBrush.AutotileWith(neighborBrushId, brushId) || neighborBrush.AutotileWith(neighborBrushId, prevBrushId))) { 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 (!Tilemap.DisableTilePrefabCreation) { // Create tile Objects if (tile != null && tile.prefabData.prefab != null) { CreateTileObject(tileIdx, tile.prefabData); } else { DestroyTileObject(tileIdx); } } } }