-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Object alignment #2698
Object alignment #2698
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for getting the ball rolling on this one!
This is not a finished review. While I've made some inline comments, please don't do further work on this patch for now because as I was reviewing I've also made some local changes that I'd like to push first, just to avoid conflicts. If I don't get to pushing those changes today it may take until tomorrow.
docs/reference/tmx-map-format.rst
Outdated
- **objectalignment:** Controls the origins for tile and shape objects. | ||
Valid values are ``unset``, ``top-left``, ``bottom-left``, and ``bottom-center``. | ||
In isometric mode, ``bottom-left`` is treated the same as ``bottom-center``. | ||
The default value is ``unset``, for compatibility reasons. With ``unset``, tile |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's indeed a necessary evil, but now that we've got a project file we should definitely use that as a place to store a different default value (not affecting the map format though, just affecting the initialization of new maps with that project active). No need to do that as part of this patch though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll look into making that change when this PR is done, then.
Reposted this because github deleted my original comment.
The property exists, can be modified, has UI, and is saved/loaded correctly. The undo/redo functions also work correctly.
* Changed MapObject::alignment to take into account the new object alignment option of the map. * Use Tiled::alignmentOffset to adjust the bounds of an object based on its alignment in the renderers. Both when rendering the object as well as when determining its bounding rect. * Added CellRenderer::TopLeft origin, which is now used for tile objects since their position is already adjusted to their alignment.
84ed41d
to
872ed5f
Compare
@Phlosioneer Alright, I've pushed my changes now so feel free to continue work on this change and please also verify that my changes make sense. I've mainly adjusted the code somewhat to apply to existing functionality like Note that I've also rebased the changes onto latest master, since they were based on a few months old code before. What I'm still unsure about, is whether we really want this property to apply to non-tile objects. Issue #91 is primarily about tile objects and in my last comment there I had suggested we resolve this by introducing a "tile alignment" option on the tileset. Why did you decide to apply this at that map level and to include the shape objects in this change? I can see the advantage of consistency by applying this property to all objects, but there's at least the following problems:
Let me know what you think. |
I pushed it up to the map level and incorporated shape objects because of how I saw the problem statement. I saw the problem as "My rectangle objects are using different alignment rules than my tile objects, and it's weird." So the solution was to make rectangle and tile objects use the same origin. The various alignments then change which origin we use, while any alignment other than "unset" would ensure that a rect and a tile of equal sizes and positions will always occupy the same space. The extension from rects to ellipses is fairly natural. I thought the polygons would also make sense, but you have pointed out that they have their own origin defined by the user already (i.e. the first point drawn). |
Right, whereas, if we could only set an origin on tiles, then only setting it to "TopLeft" would make it match with the rectangle/ellipse objects. I think you're right that consistency between the objects is more important here than consistency between alignment of objects and tiles. Still, due to the nature of the isometric renderer I'm not sure if it makes sense to support the alignment options on shapes there. And actually I think we may have a use-case for turning TopLeft into BottomLeft also for shape objects, which is when we want to finish the feature of allowing the Y axis to be inverted, see #2040 (comment). |
The sticking point here seems to be the isometric renderer. The only alignments we really want to be messing with in the isometric renderer are top corner vs bottom corner. I suggest we use different enum values to handle the isometric case, instead of the current one-size-fits-all approach. So the docs would read:
|
I don't think it's worth adjusting the terminology to the map's orientation. I think it's easier if "top-left" alignment simply means the corner at the top in isometric projection. After all, that is still also the top-left corner of the object's rectangle as far as the code is concerned. In addition, only shape objects are isometrically projected. For tile objects the object alignment can apply exactly the same way on orthogonal maps and isometric maps, since isometric projection is only applied to the position. Btw, just noting here that this PR probably also closes #330, a near duplicate of #91 about isometric maps. |
I am unclear what changes I need to make. |
* Fixed alignment handling for shape objects for isometric renderer * Fixed alignment handling for object creation tools * Added alignment handling to text objects Objects that are in the process of being created are not yet part of the map, so the renderer has to pass its map into MapObject::alignment to be able to get a correct alignment that takes into account the objectAlignment property of the map or the map's orientation when it is not set. Tile and text insertion tools want to center the object at the mouse position and need to take into account the alignment of the object once it is added to the map to place it correctly. Rectangle and ellipse insertion tools need to adjust the bounds they set on the created object to take into account the alignment as well.
9cfaaae
to
4e28320
Compare
I just pushed some more fixes. There was quite a bit left to do, but it was hard to describe or to explain how to fix it. Mostly been testing and considering different approaches to resolve the remaining issues. I think it should be ready for merging now, but could you give it a final round of review and testing? Regarding the discussion above, I decided we shall stick to having this as a map property and to apply it consistently for tile and non-tile objects, also in the isometric renderer. It's just that say BottomLeft is to be interpreted in unprojected coordinate space (in the code this is called "pixel coordinates", as opposed to "screen coordinates"). Whether it will be useful to somebody I don't know, but I think anyway most people will just want to use this property to set the alignment to TopLeft for all objects, heh. |
Seems good to me! |
One remaining problem that occurred to me, is that while this change allows setting a consistent alignment for objects on maps, it does not affect tile collision objects. Of course, tile objects are not allowed as tile collision shapes so there actually isn't an inconsistency there, since the alignment is already TopLeft for shape objects, but it seems weird to support alternative alignments for all objects on maps but not for tile collision shapes. That kind of brings me back to the idea of only supporting this alignment option for tile objects, and putting the property on the tileset instead of the map. What's your opinion on this? We can leave most of this change intact and just move the property and adjust the |
I don't think it's as important to worry about the alignment of collision objects. As you said, there's no actual inconsistency that this would fix. I don't understand your second paragraph, though. Are you saying that tilesets should dictate the orientation of tile objects on maps? So if I had two tilesets, one with Upper Left and one with Bottom Right, tile objects from the two tilesets would behave completely opposite? In any case, I think this is a fine change as-is, and if someone makes an issue asking for object alignment on tilesets, we address it then. Tiled itself has no defined mapping from tile-collision-coordinates to map-coordinates, so any problems users would encounter, would be through code they wrote or a library they use. |
Right, I don't think it's important either, but I do think it's a bit strange to introduce an alignment option that applies to all objects and then to not support it in the tile collision editor. If there was a use-case for this property, then it would be expected to work there as well. If the only use-case of the property is fixing the inconsistency, then it could be on the map or the tileset.
That's what I was saying, but I'll consider the implications further tomorrow...
We need to decide now where this property is best added, because there is no way to remove it again. Due to compatibility issues it's hard to simplify things, we can generally only make things more complicated. |
I strongly disagree with that idea, then. It would cause even more confusion than there currently is. Just swapping tilesets could mean you need to reposition all the tile objects on your document. Tile objects could behave differently if they come from different tilesets, even completely opposite as in the example I provided above. And what happens when different maps want different alignments? Enforcing this on the tileset level means that a normal map and an isometric map couldn't share a tileset for tile objects without weird things happening, or the user would be forced to manually correct the alignment for each object. Which is how things are right now.
What I was talking about maybe adding in the future is an alignment option for a tileset that only affects collision objects, not related to your actual idea. This was a miscommunication. |
This property specifies the alignment to use for the tiles in the tileset, overriding the default behavior implemented in the map renderer. The map object alignment was extended to support all alignment values. If set, it overrides the alignment specified in the tileset. The intention is for this property to be applied for tiles on tile layers as well.
bea901a
to
8833220
Compare
Can be re-added when there is an actual demand for this, but for now let's stick to just having it on the tileset, so only affecting tile objects.
6bd7c36
to
6147a1f
Compare
To make it clear that this property only affects the alignment of tile objects, and not of tiles on a tile layer. We can consider later whether it should also apply to tile layers or whether to have a separate option for that. For now it doesn't.
6147a1f
to
2a4d24c
Compare
Conflicts: docs/reference/scripting.rst src/libtiled/isometricrenderer.cpp src/libtiled/orthogonalrenderer.cpp src/libtiled/tiled.h
Implement object alignment property as described by bjorn in #91