public static List <PointF> GetPointsInMapSpace(TmxMap tmxMap, TmxHasPoints objectWithPoints) { PointF local = TmxMath.ObjectPointFToMapSpace(tmxMap, 0, 0); local.X = -local.X; local.Y = -local.Y; List <PointF> xfPoints = objectWithPoints.Points.Select(pt => TmxMath.ObjectPointFToMapSpace(tmxMap, pt)).ToList(); xfPoints = xfPoints.Select(pt => TmxMath.AddPoints(pt, local)).ToList(); return(xfPoints); }
public static TmxObjectGroup FromXml(XElement xml, TmxLayerNode parent, TmxMap tmxMap) { TmxObjectGroup tmxObjectGroup = new TmxObjectGroup(parent, tmxMap); tmxObjectGroup.FromXmlInternal(xml); tmxObjectGroup.Color = TmxHelper.GetAttributeAsColor(xml, "color", new Color32(128, 128, 128, 255)); Logger.WriteVerbose("Parsing objects in object group '{0}'", tmxObjectGroup.Name); IEnumerable <TmxObject> source = from obj in xml.Elements("object") select TmxObject.FromXml(obj, tmxObjectGroup, tmxMap); tmxObjectGroup.Objects = (from o in source orderby TmxMath.ObjectPointFToMapSpace(tmxMap, o.Position).Y select o).ToList(); return(tmxObjectGroup); }
private void AddTileObjectElements(TmxObjectTile tmxTile, XElement xmlTileObject) { // We combine the properties of the tile that is referenced and add it to our own properties AssignTiledProperties(tmxTile.Tile, xmlTileObject); // Add any colliders that might be on the tile foreach (TmxObject tmxObject in tmxTile.Tile.ObjectGroup.Objects) { // All the objects/colliders in our object group need to be separate game objects because they can have unique tags/layers XElement xmlObject = new XElement("GameObject", new XAttribute("name", tmxObject.GetNonEmptyName())); // Transform object locaction into map space (needed for isometric and hex modes) PointF xfPosition = TmxMath.ObjectPointFToMapSpace(this.tmxMap, tmxObject.Position); Vector3D pos = PointFToUnityVector(xfPosition); xmlObject.SetAttributeValue("x", pos.X); xmlObject.SetAttributeValue("y", pos.Y); xmlObject.SetAttributeValue("rotation", tmxObject.Rotation); XElement objElement = null; if (tmxObject.GetType() == typeof(TmxObjectRectangle)) { // Note: Tile objects have orthographic rectangles even in isometric orientations so no need to transform rectangle points objElement = CreateBoxColliderElement(tmxObject as TmxObjectRectangle); } else if (tmxObject.GetType() == typeof(TmxObjectEllipse)) { objElement = CreateCircleColliderElement(tmxObject as TmxObjectEllipse, tmxTile.Tile.ObjectGroup.Name); } else if (tmxObject.GetType() == typeof(TmxObjectPolygon)) { objElement = CreatePolygonColliderElement(tmxObject as TmxObjectPolygon); } else if (tmxObject.GetType() == typeof(TmxObjectPolyline)) { objElement = CreateEdgeColliderElement(tmxObject as TmxObjectPolyline); } if (objElement != null) { xmlTileObject.Add(objElement); } } }
public static TmxObjectGroup FromXml(XElement xml, TmxLayerNode parent, TmxMap tmxMap) { Debug.Assert(xml.Name == "objectgroup"); TmxObjectGroup tmxObjectGroup = new TmxObjectGroup(parent, tmxMap); tmxObjectGroup.FromXmlInternal(xml); // Color is specific to object group tmxObjectGroup.Color = TmxHelper.GetAttributeAsColor(xml, "color", Color.FromArgb(128, 128, 128)); // Get all the objects Logger.WriteLine("Parsing objects in object group '{0}'", tmxObjectGroup.Name); var objects = from obj in xml.Elements("object") select TmxObject.FromXml(obj, tmxObjectGroup, tmxMap); // The objects are ordered "visually" by Y position tmxObjectGroup.Objects = objects.OrderBy(o => TmxMath.ObjectPointFToMapSpace(tmxMap, o.Position).Y).ToList(); return(tmxObjectGroup); }
public static TmxObjectGroup FromXml(XElement xml, TmxMap tmxMap) { Debug.Assert(xml.Name == "objectgroup"); TmxObjectGroup tmxObjectGroup = new TmxObjectGroup(tmxMap); // Order within Xml file is import for layer types tmxObjectGroup.XmlElementIndex = xml.NodesBeforeSelf().Count(); tmxObjectGroup.Name = TmxHelper.GetAttributeAsString(xml, "name", ""); tmxObjectGroup.Visible = TmxHelper.GetAttributeAsInt(xml, "visible", 1) == 1; tmxObjectGroup.Opacity = TmxHelper.GetAttributeAsFloat(xml, "opacity", 1); tmxObjectGroup.Color = TmxHelper.GetAttributeAsColor(xml, "color", Color.FromArgb(128, 128, 128)); tmxObjectGroup.Properties = TmxProperties.FromXml(xml); // Set the "ignore" setting on this object group tmxObjectGroup.Ignore = tmxObjectGroup.Properties.GetPropertyValueAsEnum <IgnoreSettings>("unity:ignore", IgnoreSettings.False); PointF offset = new PointF(0, 0); offset.X = TmxHelper.GetAttributeAsFloat(xml, "offsetx", 0); offset.Y = TmxHelper.GetAttributeAsFloat(xml, "offsety", 0); tmxObjectGroup.Offset = offset; // Get all the objects Logger.WriteLine("Parsing objects in object group '{0}'", tmxObjectGroup.Name); var objects = from obj in xml.Elements("object") select TmxObject.FromXml(obj, tmxObjectGroup, tmxMap); // The objects are ordered "visually" by Y position tmxObjectGroup.Objects = objects.OrderBy(o => TmxMath.ObjectPointFToMapSpace(tmxMap, o.Position).Y).ToList(); // Are we using a unity:layer override? tmxObjectGroup.UnityLayerOverrideName = tmxObjectGroup.Properties.GetPropertyValueAsString("unity:layer", ""); return(tmxObjectGroup); }
private void DrawObjectCollider(Graphics g, TmxObject tmxObject, Color color) { Color brushColor = Color.FromArgb(128, color); using (Brush brush = new HatchBrush(HatchStyle.BackwardDiagonal, color, brushColor)) using (Pen pen = new Pen(color)) { pen.Alignment = PenAlignment.Inset; GraphicsState state = g.Save(); PointF xfPosition = TmxMath.ObjectPointFToMapSpace(this.tmxMap, tmxObject.Position); g.TranslateTransform(xfPosition.X, xfPosition.Y); g.RotateTransform(tmxObject.Rotation); if (tmxObject.GetType() == typeof(TmxObjectPolygon)) { DrawPolygon(g, pen, brush, tmxObject as TmxObjectPolygon); } else if (tmxObject.GetType() == typeof(TmxObjectRectangle)) { if (this.tmxMap.Orientation == TmxMap.MapOrientation.Isometric) { TmxObjectPolygon tmxIsometricRectangle = TmxObjectPolygon.FromIsometricRectangle(this.tmxMap, tmxObject as TmxObjectRectangle); DrawPolygon(g, pen, brush, tmxIsometricRectangle); } else { // Rectangles are polygons DrawPolygon(g, pen, brush, tmxObject as TmxObjectPolygon); } } else if (tmxObject.GetType() == typeof(TmxObjectEllipse)) { DrawEllipse(g, pen, brush, tmxObject as TmxObjectEllipse); } else if (tmxObject.GetType() == typeof(TmxObjectPolyline)) { DrawPolyline(g, pen, tmxObject as TmxObjectPolyline); } else if (tmxObject.GetType() == typeof(TmxObjectTile)) { TmxObjectTile tmxObjectTile = tmxObject as TmxObjectTile; RectangleF rcTile = new RectangleF(); rcTile.X = 0; rcTile.Y = -tmxObjectTile.Tile.TileSize.Height; rcTile.Size = tmxObjectTile.Tile.TileSize; g.FillRectangle(brush, rcTile); g.DrawRectangle(pen, rcTile.X, rcTile.Y, rcTile.Width - 1, rcTile.Height - 1); } else { g.Restore(state); RectangleF bounds = tmxObject.GetWorldBounds(); g.FillRectangle(Brushes.Red, bounds.X, bounds.Y, bounds.Width, bounds.Height); g.DrawRectangle(Pens.White, bounds.X, bounds.Y, bounds.Width, bounds.Height); string message = String.Format("Unhandled object: {0}", tmxObject.GetNonEmptyName()); DrawString(g, message, bounds.X, bounds.Y); } // Restore our state g.Restore(state); } }
private List <XElement> CreateObjectElementList(TmxObjectGroup objectGroup) { List <XElement> elements = new List <XElement>(); foreach (TmxObject tmxObject in objectGroup.Objects) { // All the objects/colliders in our object group need to be separate game objects because they can have unique tags/layers XElement xmlObject = new XElement("GameObject", new XAttribute("name", tmxObject.GetNonEmptyName())); // Transform object locaction into map space (needed for isometric and hex modes) PointF xfPosition = TmxMath.ObjectPointFToMapSpace(this.tmxMap, tmxObject.Position); PointF pos = PointFToUnityVector(xfPosition); xmlObject.SetAttributeValue("x", pos.X); xmlObject.SetAttributeValue("y", pos.Y); xmlObject.SetAttributeValue("rotation", tmxObject.Rotation); AssignUnityProperties(tmxObject, xmlObject, PrefabContext.Object); AssignTiledProperties(tmxObject, xmlObject); // If we're not using a unity:layer override and there is an Object Type to go with this object then use it if (String.IsNullOrEmpty(objectGroup.UnityLayerOverrideName)) { xmlObject.SetAttributeValue("layer", tmxObject.Type); } XElement objElement = null; if (tmxObject.GetType() == typeof(TmxObjectRectangle)) { if (this.tmxMap.Orientation == TmxMap.MapOrientation.Isometric) { TmxObjectPolygon tmxIsometricRectangle = TmxObjectPolygon.FromRectangle(this.tmxMap, tmxObject as TmxObjectRectangle); objElement = CreatePolygonColliderElement(tmxIsometricRectangle); } else { objElement = CreateBoxColliderElement(tmxObject as TmxObjectRectangle); } } else if (tmxObject.GetType() == typeof(TmxObjectEllipse)) { objElement = CreateCircleColliderElement(tmxObject as TmxObjectEllipse, objectGroup.Name); } else if (tmxObject.GetType() == typeof(TmxObjectPolygon)) { objElement = CreatePolygonColliderElement(tmxObject as TmxObjectPolygon); } else if (tmxObject.GetType() == typeof(TmxObjectPolyline)) { objElement = CreateEdgeColliderElement(tmxObject as TmxObjectPolyline); } else if (tmxObject.GetType() == typeof(TmxObjectTile)) { TmxObjectTile tmxObjectTile = tmxObject as TmxObjectTile; // Apply z-cooridnate for use with the depth buffer // (Again, this is complicated by the fact that object tiles position is WRT the bottom edge of a tile) if (Tiled2Unity.Settings.DepthBufferEnabled) { float mapLogicalHeight = this.tmxMap.MapSizeInPixels().Height; float tileLogicalHeight = this.tmxMap.TileHeight; float logicalPos_y = (-pos.Y / Tiled2Unity.Settings.Scale) - tileLogicalHeight; float depth_z = CalculateFaceDepth(logicalPos_y, mapLogicalHeight); xmlObject.SetAttributeValue("z", depth_z); } AddTileObjectElements(tmxObject as TmxObjectTile, xmlObject); } else { Logger.WriteLine("Object '{0}' has been added for use with custom importers", tmxObject); } if (objElement != null) { xmlObject.Add(objElement); } elements.Add(xmlObject); } return(elements); }
private List <XElement> CreateObjectElementList(TmxObjectGroup objectGroup) { List <XElement> elements = new List <XElement>(); foreach (TmxObject tmxObject in objectGroup.Objects) { // All the objects/colliders in our object group need to be separate game objects because they can have unique tags/layers XElement xmlObject = new XElement("GameObject", new XAttribute("name", tmxObject.GetNonEmptyName())); // Transform object locaction into map space (needed for isometric and hex modes) PointF xfPosition = TmxMath.ObjectPointFToMapSpace(this.tmxMap, tmxObject.Position); PointF pos = PointFToUnityVector(xfPosition); xmlObject.SetAttributeValue("x", pos.X); xmlObject.SetAttributeValue("y", pos.Y); xmlObject.SetAttributeValue("rotation", tmxObject.Rotation); AssignUnityProperties(tmxObject, xmlObject, PrefabContext.Object); AssignTiledProperties(tmxObject, xmlObject); // If we're not using a unity:layer override and there is an Object Type to go with this object then use it if (String.IsNullOrEmpty(objectGroup.UnityLayerOverrideName)) { // why would we /ever/ do this, christ //xmlObject.SetAttributeValue("layer", tmxObject.Type); } XElement objElement = null; XElement objComponent = new XElement("TmxObjectComponent", new XAttribute("tmx-object-id", tmxObject.Id), new XAttribute("tmx-object-name", tmxObject.Name), new XAttribute("tmx-object-type", tmxObject.Type), new XAttribute("tmx-object-x", tmxObject.Position.X), new XAttribute("tmx-object-y", tmxObject.Position.Y), new XAttribute("tmx-object-width", tmxObject.Size.Width), new XAttribute("tmx-object-height", tmxObject.Size.Height), new XAttribute("tmx-object-rotation", tmxObject.Rotation)); // Do not create colliders if the are being ignored. (Still want to creat the game object though) bool ignoringCollisions = (objectGroup.Ignore == TmxLayerNode.IgnoreSettings.Collision); if (!ignoringCollisions && tmxObject.GetType() == typeof(TmxObjectRectangle)) { if (this.tmxMap.Orientation == TmxMap.MapOrientation.Isometric) { TmxObjectPolygon tmxIsometricRectangle = TmxObjectPolygon.FromRectangle(this.tmxMap, tmxObject as TmxObjectRectangle); objElement = CreatePolygonColliderElement(tmxIsometricRectangle); } else { objElement = CreateBoxColliderElement(tmxObject as TmxObjectRectangle); } // Set object component type objComponent.Name = "RectangleObjectComponent"; } else if (!ignoringCollisions && tmxObject.GetType() == typeof(TmxObjectEllipse)) { objElement = CreateCircleColliderElement(tmxObject as TmxObjectEllipse, objectGroup.Name); // Set the component type objComponent.Name = "CircleObjectComponent"; } else if (!ignoringCollisions && tmxObject.GetType() == typeof(TmxObjectPolygon)) { objElement = CreatePolygonColliderElement(tmxObject as TmxObjectPolygon); // Set the component type objComponent.Name = "PolygonObjectComponent"; } else if (!ignoringCollisions && tmxObject.GetType() == typeof(TmxObjectPolyline)) { objElement = CreateEdgeColliderElement(tmxObject as TmxObjectPolyline); // Set the component type objComponent.Name = "PolylineObjectComponent"; } else if (tmxObject.GetType() == typeof(TmxObjectTile)) { TmxObjectTile tmxObjectTile = tmxObject as TmxObjectTile; // Apply z-cooridnate for use with the depth buffer if (Tiled2Unity.Settings.DepthBufferEnabled) { float depth_z = CalculateFaceDepth(tmxObjectTile.Position.Y, tmxMap.MapSizeInPixels.Height); xmlObject.SetAttributeValue("z", depth_z); } AddTileObjectElements(tmxObjectTile, xmlObject, objComponent); } else { Logger.WriteLine("Object '{0}' has been added for use with custom importers", tmxObject); } if (objElement != null) { xmlObject.Add(objComponent); xmlObject.Add(objElement); } elements.Add(xmlObject); } return(elements); }
private List <XElement> CreateObjectElementList(TmxObjectGroup objectGroup) { List <XElement> elements = new List <XElement>(); foreach (TmxObject tmxObject in objectGroup.Objects) { // All the objects/colliders in our object group need to be separate game objects because they can have unique tags/layers XElement xmlObject = new XElement("GameObject", new XAttribute("name", tmxObject.GetNonEmptyName())); // Transform object locaction into map space (needed for isometric and hex modes) PointF xfPosition = TmxMath.ObjectPointFToMapSpace(this.tmxMap, tmxObject.Position); PointF pos = PointFToUnityVector(xfPosition); xmlObject.SetAttributeValue("x", pos.X); xmlObject.SetAttributeValue("y", pos.Y); xmlObject.SetAttributeValue("rotation", tmxObject.Rotation); AssignUnityProperties(tmxObject, xmlObject, PrefabContext.Object); AssignTiledProperties(tmxObject, xmlObject); XElement objElement = null; if (tmxObject.GetType() == typeof(TmxObjectRectangle)) { if (this.tmxMap.Orientation == TmxMap.MapOrientation.Isometric) { TmxObjectPolygon tmxIsometricRectangle = TmxObjectPolygon.FromRectangle(this.tmxMap, tmxObject as TmxObjectRectangle); objElement = CreatePolygonColliderElement(tmxIsometricRectangle); } else { objElement = CreateBoxColliderElement(tmxObject as TmxObjectRectangle); } } else if (tmxObject.GetType() == typeof(TmxObjectEllipse)) { objElement = CreateCircleColliderElement(tmxObject as TmxObjectEllipse, objectGroup.Name); } else if (tmxObject.GetType() == typeof(TmxObjectPolygon)) { objElement = CreatePolygonColliderElement(tmxObject as TmxObjectPolygon); } else if (tmxObject.GetType() == typeof(TmxObjectPolyline)) { objElement = CreateEdgeColliderElement(tmxObject as TmxObjectPolyline); } else if (tmxObject.GetType() == typeof(TmxObjectTile)) { AddTileObjectElements(tmxObject as TmxObjectTile, xmlObject); } else { Program.WriteLine("Object '{0}' has been added for use with custom importers", tmxObject); } if (objElement != null) { xmlObject.Add(objElement); } elements.Add(xmlObject); } return(elements); }
private void DrawObjectCollider(Graphics g, TmxObject tmxObject, Color color) { Color brushColor = Color.FromArgb(128, color); using (Brush brush = new HatchBrush(HatchStyle.BackwardDiagonal, color, brushColor)) using (Pen pen = new Pen(color)) { pen.Alignment = PenAlignment.Inset; GraphicsState state = g.Save(); PointF xfPosition = TmxMath.ObjectPointFToMapSpace(this.tmxMap, tmxObject.Position); g.TranslateTransform(xfPosition.X, xfPosition.Y); g.RotateTransform(tmxObject.Rotation); if (tmxObject.GetType() == typeof(TmxObjectPolygon)) { DrawPolygon(g, pen, brush, tmxObject as TmxObjectPolygon); } else if (tmxObject.GetType() == typeof(TmxObjectRectangle)) { if (this.tmxMap.Orientation == TmxMap.MapOrientation.Isometric) { TmxObjectPolygon tmxIsometricRectangle = TmxObjectPolygon.FromRectangle(this.tmxMap, tmxObject as TmxObjectRectangle); DrawPolygon(g, pen, brush, tmxIsometricRectangle); } else { // Rectangles are polygons DrawPolygon(g, pen, brush, tmxObject as TmxObjectPolygon); } } else if (tmxObject.GetType() == typeof(TmxObjectEllipse)) { DrawEllipse(g, pen, brush, tmxObject as TmxObjectEllipse); } else if (tmxObject.GetType() == typeof(TmxObjectPolyline)) { DrawPolyline(g, pen, tmxObject as TmxObjectPolyline); } else if (tmxObject.GetType() == typeof(TmxObjectTile)) { GraphicsState tileState = g.Save(); TmxObjectTile tmxObjectTile = tmxObject as TmxObjectTile; // Apply scale SizeF scale = tmxObjectTile.GetTileObjectScale(); g.ScaleTransform(scale.Width, scale.Height); // Apply horizontal flip if (tmxObjectTile.FlippedHorizontal) { g.TranslateTransform(tmxObjectTile.Tile.TileSize.Width, 0); g.ScaleTransform(-1, 1); } // Apply vertical flip if (tmxObjectTile.FlippedVertical) { g.TranslateTransform(0, -tmxObjectTile.Tile.TileSize.Height); g.ScaleTransform(1, -1); } // (Note: Now we can draw the tile and collisions as normal as the transforms have been set up.) // Draw the tile Rectangle destination = new Rectangle(0, -tmxObjectTile.Tile.TileSize.Height, tmxObjectTile.Tile.TileSize.Width, tmxObjectTile.Tile.TileSize.Height); Rectangle source = new Rectangle(tmxObjectTile.Tile.LocationOnSource, tmxObjectTile.Tile.TileSize); g.DrawImage(tmxObjectTile.Tile.TmxImage.ImageBitmap, destination, source, GraphicsUnit.Pixel); // Put a black border around the tile so it sticks out a bit as an object g.DrawRectangle(Pens.Black, destination); // Draw the collisions // Make up for the fact that the bottom-left corner is the origin g.TranslateTransform(0, -tmxObjectTile.Tile.TileSize.Height); foreach (var obj in tmxObjectTile.Tile.ObjectGroup.Objects) { DrawObjectCollider(g, obj, Color.Gray); } g.Restore(tileState); } else { g.Restore(state); RectangleF bounds = tmxObject.GetWorldBounds(); g.FillRectangle(Brushes.Red, bounds.X, bounds.Y, bounds.Width, bounds.Height); g.DrawRectangle(Pens.White, bounds.X, bounds.Y, bounds.Width, bounds.Height); string message = String.Format("Unhandled object: {0}", tmxObject.GetNonEmptyName()); DrawString(g, message, bounds.X, bounds.Y); } // Restore our state g.Restore(state); } }