/// <summary>
        /// Sets the tile at the specified grid coordinates.
        /// </summary>
        /// <param name="x">Position, in grid (x,y) coordinates.</param>
        /// <param name="y">Position, in grid (x,y) coordinates.</param>
        /// <param name="tile">The tile object to insert into the tile layer at the specified grid coordinates.</param>
        /// <returns>True if the tile was successfully replaced.</returns>
        public bool SetTileByGridCoords(int x, int y, T2DTileObject tile)
        {
            // tiles with null tile types or tile types with no material are not allowed
            if (tile != null && (tile.TileType == null || tile.TileType.Material == null))
                return false;

            // get the index of the tile in the array
            int index = x + (y * (int)_mapSize.X);

            // allocate our array of T2DTileObject references if it's not already created
            if (_tilesArray == null)
                _tilesArray = new object[(int)_mapSize.X * (int)_mapSize.Y];

            // early out if the index is out of range
            if (index >= _tilesArray.Length)
                return false;

            // get the existing tile object
            T2DTileObject existing = _tilesArray[index] as T2DTileObject;

            // early out if the tile is already the same
            if (tile == existing)
                return true;

            // if the tile isn't null, do some stuff here
            if (tile != null)
            {
                // force the appropriate grid position
                tile.GridPosition = new Vector2(x, y);

                // check if the new tile's tile type is not in our tile types list already
                if (!_tileTypes.Contains(tile.TileType))
                    _tileTypes.Add(tile.TileType);
            }

            // replace the tile with the one specified
            _tilesArray[index] = tile;

            // dispose of the current vertex buffer and set the vertex buffer null so next render pass
            // it will be recreated with the new tile included
            _vb.Invalidate();

            // success: return true
            return true;
        }
        void _RenderTileBounds(SceneRenderState srs, ref Matrix objToWorld, T2DTileObject tile)
        {
            int numVerts = tile.TileType.CollisionPolyBasis.Length + 1;
            if (tile.TileType._collisionPolyVB.IsNull)
            {
                int sizeInBytes = numVerts * GFXVertexFormat.VertexSize;
                tile.TileType._collisionPolyVB = ResourceManager.Instance.CreateDynamicVertexBuffer(ResourceProfiles.ManualStaticVBProfile, sizeInBytes);

                // fill in vertex array
                GFXVertexFormat.PCTTBN[] pVertices = TorqueUtil.GetScratchArray<GFXVertexFormat.PCTTBN>(numVerts);
                for (int k = 0; k < numVerts - 1; ++k)
                {
                    pVertices[k] = new GFXVertexFormat.PCTTBN();
                    pVertices[k].Position = new Vector3(tile.TileType.CollisionPolyBasis[k].X, tile.TileType.CollisionPolyBasis[k].Y, 0.0f);
                    pVertices[k].Color = Color.Green;
                }
                pVertices[numVerts - 1] = pVertices[0];

                tile.TileType._collisionPolyVB.Instance.SetData<GFXVertexFormat.PCTTBN>(pVertices, 0, numVerts);
            }

            srs.World.Push();
            srs.World.MultiplyMatrixLocal(objToWorld);
            float flipx = tile.FlipX ? -1.0f : 1.0f;
            float flipy = tile.FlipY ? -1.0f : 1.0f;
            srs.World.MultiplyMatrixLocal(Matrix.CreateScale(new Vector3(flipx, flipy, 1.0f)));

            if (_effect == null)
            {
                _effect = new GarageGames.Torque.Materials.SimpleMaterial();
            }

            RenderInstance ri = SceneRenderer.RenderManager.AllocateInstance();
            ri.Type = RenderInstance.RenderInstanceType.Mesh2D;
            ri.ObjectTransform = srs.World.Top;
            ri.VertexBuffer = tile.TileType._collisionPolyVB.Instance;
            ri.PrimitiveType = PrimitiveType.LineStrip;
            ri.VertexSize = GFXVertexFormat.VertexSize;
            ri.VertexDeclaration = GFXVertexFormat.GetVertexDeclaration(srs.Gfx.Device);
            ri.VertexCount = numVerts;
            ri.BaseVertex = 0;
            ri.PrimitiveCount = numVerts - 1;

            ri.UTextureAddressMode = TextureAddressMode.Clamp;
            ri.VTextureAddressMode = TextureAddressMode.Clamp;

            ri.Material = _effect;
            SceneRenderer.RenderManager.AddInstance(ri);

            srs.World.Pop();
        }
        public override void OnLoaded()
        {
            base.OnLoaded();

            if (_tilesArray != null)
                return;

            // pre-allocate our array of T2DTileObject references
            _tilesArray = new object[(int)_mapSize.X * (int)_mapSize.Y];

            // filling our lookup array with the tiles we've gotten so far. the DefaultTile stuff below
            //  will depend on finding non-defined tiles, thus the extra loop here.
            foreach (T2DTileObject tile in _xmlTiles)
            {
                int index = (int)tile.GridPosition.X + (int)(tile.GridPosition.Y * _mapSize.X);
                _tilesArray[index] = tile;
            }

            // xml loaded, no more need for this
            _xmlTiles = null;

            if (_tileDefinitions.Length > 0)
            {
                string[] arrMatches = _tileDefinitions.Split(' ');
                for (int i = 0; i < arrMatches.Length; i++)
                {
                    string[] arrTileInfo = arrMatches[i].Split(',');
                    Assert.Fatal(arrTileInfo.Length == 3 || arrTileInfo.Length == 4, "Improperly defined tile definition array.");

                    T2DTileObject newTile = new T2DTileObject();

                    newTile.GridPosition = new Vector2(Convert.ToInt16(arrTileInfo[0]), Convert.ToInt16(arrTileInfo[1]));
                    newTile.TileTypeIndex = Convert.ToInt16(arrTileInfo[2]);

                    if (arrTileInfo.Length == 4)
                    {
                        if (String.Compare(arrTileInfo[3], "x", true) == 0)
                            newTile.FlipX = true;
                        else if (String.Compare(arrTileInfo[3], "y", true) == 0)
                            newTile.FlipY = true;
                        else if (String.Compare(arrTileInfo[3], "xy", true) == 0)
                        {
                            newTile.FlipX = true;
                            newTile.FlipY = true;
                        }
                        else
                            Assert.Fatal(false, "Illegal flip value");
                    }

                    int index = (int)newTile.GridPosition.X + (int)(newTile.GridPosition.Y * _mapSize.X);
                    _tilesArray[index] = newTile;
                }
            }

            // read these in, no more need of them
            _tileDefinitions = null;

            if (_defaultTileType != null)
            {
                for (int j = 0; j < _mapSize.Y; j++)
                {
                    for (int i = 0; i < _mapSize.X; i++)
                    {
                        if (GetTileByGridCoords(i, j) == null)
                        {
                            T2DTileObject newTile = new T2DTileObject();

                            newTile.GridPosition = new Vector2(i, j);
                            newTile.TileTypeName = _defaultTileType.Name;

                            int index = (int)newTile.GridPosition.X + (int)(newTile.GridPosition.Y * _mapSize.X);
                            _tilesArray[index] = newTile;
                        }
                    }
                }
            }

            foreach (T2DTileObject tile in _tilesArray)
            {
                if (tile == null)
                    continue;
                tile.TileType = tile.TileTypeName == null ? _FindTileType(tile.TileTypeIndex) : _FindTileType(tile.TileTypeName);
                Assert.Fatal(tile.TileType != null, "Could not match up Tile with TileType");
            }

            foreach (T2DTileType type in _tileTypes)
            {
                ObjectType += type.ObjectType;
            }

            // automatically calculate Size based on dimensions and individual tile size
            Size = new Vector2(_mapSize.X * _tileSize.X, _mapSize.Y * _tileSize.Y);
            UpdateSpatialData();
        }