Ejemplo n.º 1
0
        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);
                    }
                }
            }
        }