public ColliderFactoryIsometric(float mapTileWidth, float mapTileHeight, SuperImportContext importContext)
     : base(importContext)
 {
     m_MapTileWidth  = mapTileWidth;
     m_MapTileHeight = mapTileHeight;
 }
Beispiel #2
0
        private void PlaceTileAsObject(GameObject goTilemap, SuperTile tile, int cx, int cy, TileIdMath tileId, Vector3Int pos3)
        {
            Assert.IsNotNull(goTilemap.GetComponentInParent <SuperMap>());
            Assert.IsNotNull(goTilemap.GetComponentInParent <SuperLayer>());

            var superMap   = goTilemap.GetComponentInParent <SuperMap>();
            var superLayer = goTilemap.GetComponentInParent <SuperLayer>();
            var color      = new Color(1, 1, 1, superLayer.CalculateOpacity());

            string tileName = string.Format("tile ({0}, {1})", cx, cy);
            var    goTRS    = new GameObject(string.Format("{0} (TRS)", tileName));

            goTilemap.AddChildWithUniqueName(goTRS);

            // Create a faux SuperObject component to add to our placed tile
            // We need this in case we have custom scripts that are looking for tile object via component
            {
                var tileObject = goTRS.AddComponent <SuperObject>();
                tileObject.m_Id        = m_ObjectIdCounter++;
                tileObject.m_TiledName = string.Format("AsObject_{0}", tileObject.m_Id);
                tileObject.m_X         = pos3.x * superMap.m_TileWidth;
                tileObject.m_Y         = -pos3.y * superMap.m_TileHeight;
                tileObject.m_Width     = tile.m_Width;
                tileObject.m_Height    = tile.m_Height;
                tileObject.m_TileId    = (uint)tile.m_TileId;
                tileObject.m_Visible   = true;

                // Does the tile have any properties?
                if (!tile.m_CustomProperties.IsEmpty())
                {
                    var component = tileObject.gameObject.AddComponent <SuperCustomProperties>();
                    component.m_Properties = new List <CustomProperty>();
                    component.m_Properties.CombineFromSource(tile.m_CustomProperties);
                }
            }

            Vector3 translate, rotate, scale;

            tile.GetTRS(tileId.FlipFlags, m_MapComponent.m_Orientation, out translate, out rotate, out scale);

            var cellPos = superMap.CellPositionToLocalPosition(pos3.x, pos3.y);

            translate.x += cellPos.x;
            translate.y += cellPos.y;

            if (m_MapComponent.m_Orientation == MapOrientation.Isometric || m_MapComponent.m_Orientation == MapOrientation.Staggered)
            {
                translate.x -= SuperImportContext.MakeScalar(m_MapComponent.m_TileWidth) * 0.5f;
            }
            else if (m_MapComponent.m_Orientation == MapOrientation.Hexagonal)
            {
                translate.x -= SuperImportContext.MakeScalar(m_MapComponent.m_TileWidth) * 0.5f;
                translate.y -= SuperImportContext.MakeScalar(m_MapComponent.m_TileHeight) * 0.5f;
            }

            // Add the game object for the tile
            goTRS.transform.localPosition = translate;
            goTRS.transform.localRotation = Quaternion.Euler(rotate);
            goTRS.transform.localScale    = scale;

            // Add the sprite renderer component
            var renderer = goTRS.AddComponent <SpriteRenderer>();

            renderer.sprite = tile.m_Sprite;
            renderer.color  = color;
            AssignMaterial(renderer);
            AssignSpriteSorting(renderer);

            if (!tile.m_AnimationSprites.IsEmpty())
            {
                var tileAnimator = goTRS.AddComponent <TileObjectAnimator>();
                tileAnimator.m_AnimationFramerate = SuperImportContext.Settings.AnimationFramerate;
                tileAnimator.m_AnimationSprites   = tile.m_AnimationSprites;
            }

            // Add any colliders that may be on the tile object
            tile.AddCollidersForTileObject(goTRS, SuperImportContext);
        }
Beispiel #3
0
        private static void AddBoxCollider(GameObject go, CollisionObject collision, SuperTile tile, SuperImportContext importContext)
        {
            var box = go.AddComponent <BoxCollider2D>();

            box.offset = importContext.MakePointPPU(collision.m_Size.x, -collision.m_Size.y) * 0.5f;
            box.size   = importContext.MakeSize(collision.m_Size);

            var xpos = importContext.MakeScalar(collision.m_Position.x);
            var ypos = importContext.MakeScalar(collision.m_Position.y);

            go.transform.localPosition    = new Vector3(xpos, ypos);
            go.transform.localEulerAngles = new Vector3(0, 0, importContext.MakeRotation(collision.m_Rotation));

            go.AddComponent <SuperColliderComponent>();
        }
Beispiel #4
0
        private bool ProcessGridObject(XElement xMap)
        {
            // Add the grid to the map
            var goGrid = new GameObject("Grid");

            goGrid.transform.SetParent(m_MapComponent.gameObject.transform);

            // The grid is added to the asset because without it we get prefab modifications for all collision geometry and tile matrices
            // Note: this is crashing Unity 2018.3. Unfortunately prefab instances will be fatter in those versions of Unity. :(
#if UNITY_2019_1_OR_NEWER
            SuperImportContext.AddObjectToAsset("_grid", goGrid);
#endif

            m_GridComponent = goGrid.AddComponent <Grid>();


            // Grid cell size always has a z-value of 1 so that we can use custom axis sorting
            float sx = SuperImportContext.MakeScalar(m_MapComponent.m_TileWidth);
            float sy = SuperImportContext.MakeScalar(m_MapComponent.m_TileHeight);
            m_GridComponent.cellSize = new Vector3(sx, sy, 1);
            var localPosition = new Vector3(0, 0, 0);

            switch (m_MapComponent.m_Orientation)
            {
#if UNITY_2018_3_OR_NEWER
            case MapOrientation.Isometric:
                m_GridComponent.cellLayout = GridLayout.CellLayout.Isometric;
                localPosition = new Vector3(0, -sy, 0);
                break;

            case MapOrientation.Staggered:
                m_GridComponent.cellLayout = GridLayout.CellLayout.Isometric;

                if (m_MapComponent.m_StaggerAxis == StaggerAxis.Y)
                {
                    if (m_MapComponent.m_StaggerIndex == StaggerIndex.Odd)
                    {
                        localPosition = new Vector3(sx * 0.5f, -sy, 0);
                    }
                    else
                    {
                        localPosition = new Vector3(sx, -sy, 0);
                    }
                }
                else if (m_MapComponent.m_StaggerAxis == StaggerAxis.X)
                {
                    if (m_MapComponent.m_StaggerIndex == StaggerIndex.Odd)
                    {
                        localPosition = new Vector3(sx * 0.5f, -sy, 0);
                    }
                    else
                    {
                        localPosition = new Vector3(sx * 0.5f, -sy * 1.5f, 0);
                    }
                }
                break;

            case MapOrientation.Hexagonal:
                if (m_MapComponent.m_StaggerAxis == StaggerAxis.Y)
                {
                    // Pointy-top hex maps
                    m_GridComponent.cellLayout  = GridLayout.CellLayout.Hexagon;
                    m_GridComponent.cellSwizzle = GridLayout.CellSwizzle.XYZ;

                    if (m_MapComponent.m_StaggerIndex == StaggerIndex.Odd)
                    {
                        localPosition = new Vector3(sx * 0.5f, sy * -0.5f, 0);
                    }
                    else
                    {
                        localPosition = new Vector3(sx * 0.5f, sy * 0.25f, 0);
                    }
                }
                else if (m_MapComponent.m_StaggerAxis == StaggerAxis.X)
                {
                    // Flat-top hex maps. Reverse x and y on size.
                    m_GridComponent.cellLayout  = GridLayout.CellLayout.Hexagon;
                    m_GridComponent.cellSwizzle = GridLayout.CellSwizzle.YXZ;
                    m_GridComponent.cellSize    = new Vector3(sy, sx, 1);

                    if (m_MapComponent.m_StaggerIndex == StaggerIndex.Odd)
                    {
                        localPosition = new Vector3(sx * -0.25f, -sy, 0);
                    }
                    else
                    {
                        localPosition = new Vector3(sx * 0.5f, -sy, 0);
                    }
                }
                break;
#endif
            default:
                m_GridComponent.cellLayout = GridLayout.CellLayout.Rectangle;
                localPosition = new Vector3(0, -sy, 0);
                break;
            }

            m_GridComponent.transform.localPosition = localPosition;

            return(true);
        }
        private static void AddEdgeCollider(GameObject go, CollisionObject collision, SuperTile tile, SuperImportContext importContext)
        {
            var edge = go.AddComponent <EdgeCollider2D>();

            edge.points = importContext.MakePointsPPU(collision.Points);

            go.AddComponent <SuperColliderComponent>();
        }
        private void ProcessLayerData(GameObject goLayer, XElement xData)
        {
            Assert.IsNotNull(goLayer);
            Assert.IsNotNull(goLayer.GetComponent <SuperTileLayer>());
            Assert.IsNotNull(xData);

            SuperTileLayer superComp = goLayer.GetComponent <SuperTileLayer>();

            var chunk = new Chunk();

            chunk.Encoding    = xData.GetAttributeAs <DataEncoding>("encoding");
            chunk.Compression = xData.GetAttributeAs <DataCompression>("compression");

            bool tilesAsObjects = m_MapComponent.m_Orientation == MapOrientation.Isometric || m_TilesAsObjects;

            // Are we reading in data in smaller chunks (for infinite maps) or one big chunk (the full map)
            var xChunks = xData.Elements("chunk");

            if (xChunks.Any())
            {
                foreach (var xChunk in xChunks)
                {
                    chunk.XmlChunk = xChunk;
                    chunk.X        = xChunk.GetAttributeAs <int>("x");
                    chunk.Y        = xChunk.GetAttributeAs <int>("y");
                    chunk.Width    = xChunk.GetAttributeAs <int>("width");
                    chunk.Height   = xChunk.GetAttributeAs <int>("height");

                    // Each chunk is a separate game object on the super layer
                    GameObject goChunk = new GameObject(string.Format("Chunk ({0},{1})", chunk.X, chunk.Y));
                    goLayer.AddChildWithUniqueName(goChunk);

                    // Possition the chunk
                    Vector3Int int3      = m_MapComponent.TilePositionToGridPosition(chunk.X, chunk.Y);
                    Vector3    translate = SuperImportContext.MakePoint(int3.x, int3.y);
                    translate.x *= m_MapComponent.m_TileWidth;
                    translate.y *= m_MapComponent.m_TileHeight;

                    goChunk.transform.localPosition = translate;

                    // Create the tilemap for the layer if needed
                    if (!tilesAsObjects)
                    {
                        var tilemap = goChunk.AddComponent <Tilemap>();
                        tilemap.tileAnchor         = Vector3.zero;
                        tilemap.animationFrameRate = SuperImportContext.Settings.AnimationFramerate;
                        tilemap.color = new Color(1, 1, 1, superComp.CalculateOpacity());

                        // Create the renderer for the layer
                        var renderer = goChunk.AddComponent <TilemapRenderer>();
                        renderer.sortOrder = MapRenderConverter.Tiled2Unity(m_MapComponent.m_RenderOrder);
                        AssignSortingLayer(renderer, superComp.m_SortingLayerName, superComp.m_SortingOrder);
                    }

                    ProcessLayerDataChunk(goChunk, chunk);
                }
            }
            else
            {
                // Regular maps only have one chunk with the Tilemap and TileRenderer being on the layer object

                // Add the tilemap components if needed
                if (!tilesAsObjects)
                {
                    var tilemap = goLayer.AddComponent <Tilemap>();
                    tilemap.tileAnchor         = Vector3.zero;
                    tilemap.animationFrameRate = SuperImportContext.Settings.AnimationFramerate;
                    tilemap.color = new Color(1, 1, 1, superComp.CalculateOpacity());

                    // Create the renderer for the layer
                    var renderer = goLayer.AddComponent <TilemapRenderer>();
                    renderer.sortOrder = MapRenderConverter.Tiled2Unity(m_MapComponent.m_RenderOrder);
                    AssignSortingLayer(renderer, superComp.m_SortingLayerName, superComp.m_SortingOrder);
                }

                // For regular maps the 'chunk' is the same as the layer data
                chunk.XmlChunk = xData;
                chunk.X        = 0;
                chunk.Y        = 0;
                chunk.Width    = m_MapComponent.m_Width;
                chunk.Height   = m_MapComponent.m_Height;

                ProcessLayerDataChunk(goLayer, chunk);
            }
        }
Beispiel #7
0
        public static void AddCollidersForTileObject(this SuperTile tile, GameObject goParent, SuperImportContext importContext)
        {
            Assert.IsNotNull(tile);
            Assert.IsNotNull(goParent);
            Assert.IsNotNull(importContext);

            if (!tile.m_CollisionObjects.IsNullOrEmpty())
            {
                foreach (var collision in tile.m_CollisionObjects)
                {
                    collision.AddCollider(tile, goParent, importContext);
                }
            }
        }
        public static void AddCollider(this CollisionObject collision, SuperTile tile, GameObject goParent, SuperImportContext importContext)
        {
            var go = new GameObject(collision.m_ObjectName);

            if (collision.CollisionShapeType == CollisionShapeType.Polygon)
            {
                AddPolygonCollider(go, collision, tile, importContext);
            }
            else if (collision.CollisionShapeType == CollisionShapeType.Polyline)
            {
                AddEdgeCollider(go, collision, tile, importContext);
            }
            else if (collision.CollisionShapeType == CollisionShapeType.Ellipse)
            {
                AddEllipseCollider(go, collision, tile, importContext);
            }
            else if (collision.CollisionShapeType == CollisionShapeType.Rectangle)
            {
                AddBoxCollider(go, collision, tile, importContext);
            }

            // Additional settings on the collider that was just added
            var addedCollider = go.GetComponent <Collider2D>();

            if (addedCollider != null)
            {
                addedCollider.isTrigger = importContext.GetIsTriggerOverridable(collision.m_IsTrigger);
            }

            goParent.AddChildWithUniqueName(go);
        }
Beispiel #9
0
        private bool ProcessGridObject(XElement xMap)
        {
            // Add the grid to the map
            var goGrid = new GameObject("Grid");

            goGrid.transform.SetParent(m_MapComponent.gameObject.transform);

            m_GridComponent = goGrid.AddComponent <Grid>();

            // Grid cell size always has a z-value of 1 so that we can use custom axis sorting
            float sx = SuperImportContext.MakeScalar(m_MapComponent.m_TileWidth);
            float sy = SuperImportContext.MakeScalar(m_MapComponent.m_TileHeight);

            m_GridComponent.cellSize = new Vector3(sx, sy, 1);
            var localPosition = new Vector3(0, 0, 0);

            switch (m_MapComponent.m_Orientation)
            {
#if UNITY_2018_3_OR_NEWER
            case MapOrientation.Isometric:
                m_GridComponent.cellLayout = GridLayout.CellLayout.Isometric;
                localPosition = new Vector3(0, -sy, 0);
                break;

            case MapOrientation.Staggered:
                m_GridComponent.cellLayout = GridLayout.CellLayout.Isometric;

                if (m_MapComponent.m_StaggerAxis == StaggerAxis.Y)
                {
                    if (m_MapComponent.m_StaggerIndex == StaggerIndex.Odd)
                    {
                        localPosition = new Vector3(sx * 0.5f, -sy, 0);
                    }
                    else
                    {
                        localPosition = new Vector3(sx, -sy, 0);
                    }
                }
                else if (m_MapComponent.m_StaggerAxis == StaggerAxis.X)
                {
                    if (m_MapComponent.m_StaggerIndex == StaggerIndex.Odd)
                    {
                        localPosition = new Vector3(sx * 0.5f, -sy, 0);
                    }
                    else
                    {
                        localPosition = new Vector3(sx * 0.5f, -sy * 1.5f, 0);
                    }
                }
                break;

            case MapOrientation.Hexagonal:
                if (m_MapComponent.m_StaggerAxis == StaggerAxis.Y)
                {
                    // Pointy-top hex maps
                    m_GridComponent.cellLayout  = GridLayout.CellLayout.Hexagon;
                    m_GridComponent.cellSwizzle = GridLayout.CellSwizzle.XYZ;

                    if (m_MapComponent.m_StaggerIndex == StaggerIndex.Odd)
                    {
                        localPosition = new Vector3(sx * 0.5f, sy * -0.5f, 0);
                    }
                    else
                    {
                        localPosition = new Vector3(sx * 0.5f, sy * 0.25f, 0);
                    }
                }
                else if (m_MapComponent.m_StaggerAxis == StaggerAxis.X)
                {
                    // Flat-top hex maps. Reverse x and y on size.
                    m_GridComponent.cellLayout  = GridLayout.CellLayout.Hexagon;
                    m_GridComponent.cellSwizzle = GridLayout.CellSwizzle.YXZ;
                    m_GridComponent.cellSize    = new Vector3(sy, sx, 1);

                    if (m_MapComponent.m_StaggerIndex == StaggerIndex.Odd)
                    {
                        localPosition = new Vector3(sx * -0.25f, -sy, 0);
                    }
                    else
                    {
                        localPosition = new Vector3(sx * 0.5f, -sy, 0);
                    }
                }
                break;
#endif
            default:
                m_GridComponent.cellLayout = GridLayout.CellLayout.Rectangle;
                localPosition = new Vector3(0, -sy, 0);
                break;
            }

            m_GridComponent.transform.localPosition = localPosition;

            return(true);
        }
 public ColliderFactoryOrthogonal(SuperImportContext importContext)
     : base(importContext)
 {
 }
        // Creates a new object, attached to the parent, with a specialized layer component
        public static T AddSuperLayerGameObject <T>(this GameObject goParent, SuperLayerLoader loader, SuperImportContext importContext) where T : SuperLayer
        {
            GameObject goLayer = new GameObject();

            // Read in the fields common across our Tiled layer types
            var layerComponent = loader.CreateLayer(goLayer) as T;

            Assert.IsNotNull(layerComponent);

            // Add the object to the parent
            goLayer.name = layerComponent.m_TiledName;
            goParent.AddChildWithUniqueName(goLayer);

            return(layerComponent);
        }
Beispiel #12
0
        // Group convex polygons into a composite collider
        public static void AddCompositePolygonCollider(GameObject go, List <Vector2[]> convexPolygons, SuperImportContext context)
        {
            // If there is only one convex polygon then don't use a composite
            if (convexPolygons.Count == 1)
            {
                var polyCollider = go.AddComponent <PolygonCollider2D>();
                polyCollider.SetPath(0, convexPolygons[0]);
                polyCollider.gameObject.AddComponent <SuperColliderComponent>();
            }
            else
            {
                // Rigid body is needed for composite collider
                var rigid = go.AddComponent <Rigidbody2D>();
                rigid.bodyType  = RigidbodyType2D.Static;
                rigid.simulated = true;

                // Colliders will be grouped by the composite
                // This way we have convex polygon paths (in the children) if needed
                // And we can have complex polygons represented by one object
                var composite = go.AddComponent <CompositeCollider2D>();
                composite.geometryType   = context.Settings.CollisionGeometryType;
                composite.generationType = CompositeCollider2D.GenerationType.Manual;

                // Add polygon colliders
                foreach (var path in convexPolygons)
                {
                    var goPolygon = new GameObject("ConvexPolygon");
                    go.AddChildWithUniqueName(goPolygon);

                    var polyCollider = goPolygon.AddComponent <PolygonCollider2D>();
                    polyCollider.usedByComposite = true;
                    polyCollider.SetPath(0, path);

                    polyCollider.gameObject.AddComponent <SuperColliderComponent>();
                }

                composite.ST2UGenerateGeometry();
            }
        }
 public CollisionBuilder(GameObject goTilemap, Dictionary <uint, TilePolygonCollection> tilePolygonDatabase, SuperImportContext importContext)
 {
     m_TilemapGameObject   = goTilemap;
     m_TilePolygonDatabase = tilePolygonDatabase;
     m_ImportContext       = importContext;
 }
Beispiel #14
0
 public ScopedIsTriggerOverride(SuperImportContext superContext)
 {
     m_SuperContext = superContext;
 }
        // Creates a new object, attached to the parent, with a specialized layer component
        public static T AddSuperLayerGameObject <T>(this GameObject goParent, SuperLayerLoader loader, SuperImportContext importContext) where T : SuperLayer
        {
            GameObject goLayer = new GameObject();

            // Read in the fields common across our Tiled layer types
            var layerComponent = loader.CreateLayer(goLayer) as T;

            Assert.IsNotNull(layerComponent);

            // Add the object to the parent
            goLayer.name = layerComponent.m_TiledName;
            goParent.AddChildWithUniqueName(goLayer);

            // Position the layer based on the x, y offsets and pixels per unit
            goLayer.transform.localPosition = importContext.MakePoint(layerComponent.m_OffsetX, layerComponent.m_OffsetY);

            return(layerComponent);
        }
Beispiel #16
0
 public ScopedLayerIgnoreMode(SuperImportContext superContext, LayerIgnoreMode newIgnoreMode)
 {
     m_SuperContext                 = superContext;
     m_RestoreIgnoreMode            = m_SuperContext.LayerIgnoreMode;
     m_SuperContext.LayerIgnoreMode = newIgnoreMode;
 }
 public ColliderFactory(SuperImportContext importContext)
 {
     ImportContext = importContext;
 }
        private static void AddPolygonCollider(GameObject go, CollisionObject collision, SuperTile tile, SuperImportContext importContext)
        {
            // Note that polygons may need to be decomposed into convex parts
            var points = importContext.MakePointsPPU(collision.Points);

            // Triangulate the polygon points
            var triangulator = new Triangulator();
            var triangles    = triangulator.TriangulatePolygon(points);

            // Gather triangles into a collection of convex polygons
            var composition    = new ComposeConvexPolygons();
            var convexPolygons = composition.Compose(triangles);

            PolygonUtils.AddCompositePolygonCollider(go, convexPolygons, importContext);
        }
Beispiel #19
0
        private static void AddPointCollider(GameObject go, CollisionObject collision, SuperImportContext importContext)
        {
            var xpos = importContext.MakeScalar(collision.m_Position.x);
            var ypos = importContext.MakeScalar(collision.m_Position.y);

            go.transform.localPosition    = new Vector3(xpos, ypos);
            go.transform.localEulerAngles = new Vector3(0, 0, importContext.MakeRotation(collision.m_Rotation));

            go.AddComponent <SuperColliderComponent>();
        }
        private static void AddEllipseCollider(GameObject go, CollisionObject collision, SuperTile tile, SuperImportContext importContext)
        {
            // Add a circle collider if width == height. Otherwise, we have to use am approximate polygon representation.
            if (collision.m_Size.x == collision.m_Size.y)
            {
                var cirlce = go.AddComponent <CircleCollider2D>();
                cirlce.offset = importContext.MakePointPPU(collision.m_Size.x, -collision.m_Size.y) * 0.5f;
                cirlce.radius = importContext.MakeScalar(collision.m_Size.x) * 0.5f;

                var xpos = importContext.MakeScalar(collision.m_Position.x);
                var ypos = importContext.MakeScalar(collision.m_Position.y);
                go.transform.localPosition    = new Vector3(xpos, ypos);
                go.transform.localEulerAngles = new Vector3(0, 0, importContext.MakeRotation(collision.m_Rotation));

                go.AddComponent <SuperColliderComponent>();
            }
            else
            {
                AddPolygonCollider(go, collision, tile, importContext);
            }
        }
Beispiel #21
0
        public static int AddPropertiesFromType(this List <CustomProperty> list, string typeName, SuperImportContext importContext)
        {
            if (list == null)
            {
                return(0);
            }

            if (string.IsNullOrEmpty(typeName))
            {
                return(0);
            }

            CustomObjectType objectType;

            if (importContext.Settings.CustomObjectTypes.TryGetCustomObjectType(typeName, out objectType))
            {
                return(CombineFromSource(list, objectType.m_CustomProperties));
            }

            return(0);
        }