tiled icon indicating copy to clipboard operation
tiled copied to clipboard

Some TMX format clarifications needed

Open bjorn opened this issue 2 years ago • 10 comments

  • <tileset> elements always appear before any layers
  • The gid attribute on <object> tags can contain horizontal and vertical flipping flags.

bjorn avatar Feb 08 '22 15:02 bjorn

Would you like some help removing this behavior altogether or are we stuck with attributes being packed into the bits of the gid?

I'm writing a tmx parser and I thought this was a bug.

billautomata avatar Feb 26 '22 11:02 billautomata

Tile Objects have their own flip properties in addition to those of the Object, and this can be useful in games. It also makes sense that within a format, tiles are always communicated the same way.

The only thing that needs fixing is the documentation, which doesn't make this explicit, hence this issue.

eishiya avatar Feb 26 '22 13:02 eishiya

This is by design? Two sources of truth for flip properties? One set stored as an attribute in human readable form, and one set hidden in the MSB of an integer? It's pretty cumbersome to handle this in any language that lacks native support for unsigned 32 bit integers. When you read the xml files you think there is some kind of overflow error.

billautomata avatar Feb 26 '22 13:02 billautomata

They're different truths, that's the thing. Objects cannot be flipped, they can be rotated and repositioned. For a non-Tile object, there's no "flipping", a rectangle is a rectangle, a polygon is a polygon, etc. But Tile Objects have tile art that needs to also be flipped and which can't simply be rotated to "flip" and that's what's stored with the GID. The tile can also be flipped opposite to that of the object.

(I misled you in my previous post, sorry about that. Poor choice of wording on my part.)

And as I mentioned, this is the same format that's used for tiles in Tile Layers, so any TMX (or other formats using Tiled GIDs) parser will need to deal with these GIDs anyway. If it's going to be a problem for Objects, it's going to be an even bigger problem for Tile Layers, and if it's a significant problem, then a different format entirely may be preferable for you.

eishiya avatar Feb 26 '22 14:02 eishiya

This is by design? Two sources of truth for flip properties? One set stored as an attribute in human readable form, and one set hidden in the MSB of an integer?

So, just to clarify as well, there aren't multiple sources of truth. Only tile objects can be flipped, because the flipping applies to their texture only. And this information is encoded exactly the same way as for tiles on tile layers. So while I agree this is not readable, it is at least consistent.

It's pretty cumbersome to handle this in any language that lacks native support for unsigned 32 bit integers. When you read the xml files you think there is some kind of overflow error.

Since tiles on tile layers are also unsigned 32-bit integers, avoiding it here will not get rid of that confusion nor help with overall readability. Worse, storing flipping as attributes would suggest other objects types can also be flipped (but if we add that kind of flipping it would likely be through a scale attribute).

bjorn avatar Feb 27 '22 10:02 bjorn

On a related note, there's no reason that one day we can't have the other flip flags (or at least diagonal flip, which enables 90 degree rotations) in Tile Objects, and that's something that definitely makes no sense being an Object property. The way I see it, the tile is just some art (which may have some collision to go with it), there's no reason why it couldn't be rotated with respect to the orientation of the Object.

Currently, trying to rotate a tile before placing it as a Tile Object will rotate the object, which I think is part of the reason this is confusing, since it mixes up the tile's cosmetic appearance with the Object's rotation. I'm of the opinion that transformations done on the preview should only apply to the tile and not to the Object, and the object can only be rotated after being created, like all other Objects. Perhaps I should open a separate issue for this?

eishiya avatar Feb 27 '22 13:02 eishiya

@eishiya Hmm, since all objects can be rotated, supporting rotation through a "diagonal flip" flag on tile objects felt like an unnecessary duplication of functionality, and is hence not supported. It is also not very common for libraries or frameworks to support this kind of flipping, so implementations would likely need to translate it into an object rotation and flipping anyway. In the end I think it would just make things more complicated for no benefit.

Regarding rotation before placement, it doesn't make sense for most tools, but it could be supported by the "Insert Template" and "Insert Text" tools as well. I doubt many people would need it, but it may not be hard to support and would be good for consistency.

bjorn avatar Mar 01 '22 10:03 bjorn

Ah, you're right that it's not widely supported. I wasn't thinking of that, only of the theoretical side of it.

I don't think Text and Templates should be rotated before placement, precisely because in those cases it would rotate the Object itself, and not merely set some cosmetic value on the Tile. Then again, Tile Objects can be rotated prior to placement, and that does rotate the Object, so I guess it makes sense for consistency with them. I feel that the Tile Object rotation is inconsistent though xP But it is definitely convenient, so I wouldn't request a change to that. All of this behaviour could become more consitent if/when the ability to scale objects to flip them horizontally is added. But that's its own can of worms with a bunch of its own decisions to make.

eishiya avatar Mar 01 '22 12:03 eishiya

Hoping this issue is for any/all clarifications on the TMX format docs.

I notice the docs say object.type defaults to empty string, but the default behavior of the type property is to not exist until the Class property is filled in within Tiled.

I'm using Tiled 1.10.2

Dalqin avatar Nov 02 '23 16:11 Dalqin

I notice the docs say object.type defaults to empty string, but the default behavior of the type property is to not exist until the Class property is filled in within Tiled.

Whenever the docs say that an attribute defaults to some value, what is meant is that in the absence of that attribute, that is the value that should be assumed. It's like a default value for a function parameter, when you don't mention it at all.

The map writer uses this to avoid writing redundant information. If you have left the class of an object empty, then there is no point in writing that empty value. It defaults to an empty string anyway.

(the docs try to explain this at the start, where it says "All optional attributes are either marked as optional, or have a default value to imply that they are optional.")

bjorn avatar Nov 03 '23 08:11 bjorn