示例#1
0
        // '°', '├', '═', '┤', | 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 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);
        }
示例#3
0
        bool IsTilemapChunksVisible()
        {
            TilemapChunk chunk = m_tilemap.GetComponentInChildren <TilemapChunk>();

            return(chunk && (chunk.gameObject.hideFlags & HideFlags.HideInHierarchy) == 0);
        }
示例#4
0
 public virtual void OnErase(TilemapChunk chunk, int chunkGx, int chunkGy, uint tileData, int brushId)
 {
     ;
 }
示例#5
0
 public virtual uint OnPaint(TilemapChunk chunk, int chunkGx, int chunkGy, uint tileData)
 {
     return(tileData);
 }
示例#6
0
        /// <summary>
        /// Update the render mesh and mesh collider of all tile chunks. This should be called once after making all modifications to the tilemap with SetTileData.
        /// </summary>
        public void UpdateMeshImmediate()
        {
#if UNITY_EDITOR
            if (!Application.isPlaying && m_markSceneDirtyOnNextUpdateMesh)
            {
                m_markSceneDirtyOnNextUpdateMesh = false;
#if UNITY_5_3 || UNITY_5_3_OR_NEWER
                UnityEditor.SceneManagement.EditorSceneManager.MarkAllScenesDirty();
#else
                EditorApplication.MarkSceneDirty();
#endif
            }
#endif

            RecalculateMapBounds();

            s_chunkList.Clear();
            var valueIter = m_dicChunkCache.Values.GetEnumerator();
            while (valueIter.MoveNext())
            {
                TilemapChunk chunk = valueIter.Current;
                if (chunk)
                {
                    if (!chunk.UpdateMesh())
                    {
#if UNITY_EDITOR
                        if (IsUndoEnabled)
                        {
                            Undo.DestroyObjectImmediate(chunk.gameObject);
                        }
                        else
                        {
                            DestroyImmediate(chunk.gameObject);
                        }
#else
                        DestroyImmediate(chunk.gameObject);
#endif
                    }
                    else
                    {
                        //chunk.UpdateColliderMesh();
                        s_chunkList.Add(chunk);
                    }
                }
            }

            if (m_autoShrink)
            {
                ShrinkMapBoundsToVisibleArea();
            }

            // UpdateColliderMesh is called after calling UpdateMesh of all tilechunks, because UpdateColliderMesh needs the tileId to be updated
            // ( remember a brush sets neighbours tile id to empty, so UpdateColliderMesh won't be able to know the collider type )
            for (int i = 0; i < s_chunkList.Count; ++i)
            {
                s_chunkList[i].UpdateColliders();
            }

            if (OnMeshUpdated != null)
            {
                OnMeshUpdated(this);
            }
        }