Skip to content
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

Going forward with the TileMap editor #6415

Open
3 of 6 tasks
groud opened this issue Mar 3, 2023 · 57 comments
Open
3 of 6 tasks

Going forward with the TileMap editor #6415

groud opened this issue Mar 3, 2023 · 57 comments

Comments

@groud
Copy link
Member

groud commented Mar 3, 2023

Describe the project you are working on

Godot

Describe the problem or limitation you are having in your project

The 4.0 TileMap, despite a lot of improvements, has still lot of issues that leads to a frustrating UX in some cases and has an API more complex than in 3.x. I think there are still some big improvements that could be done, that are either compatibility-breaking or not.

I want to use this proposal as a tracker of things that could be improved and how they could be implemented.

  • Tile rotations and flip.

Compared to 3.x, creating flipped / rotated tiles is a bit more complex in 4.0. You need to create alternative tiles for each tile. To solve this issue, I suggest using 3 bits from the alternative_tile to store the filp_h/flip_v/transpose status, which is a 32 bit integer. It's theoretically compat breaking, but I doubt anyone reached enough alternative tiles to need the 32 bits count. When rotating tiles on the map, those bits should only be set for tiles using a TileSetAtlasSource, otherwise it would lead to invalid tiles for TileSetScenesCollectionSource.

Regarding the API, I see two solutions to the problem:

  • make set_cell provide 3 bools to flips to the tile. The main problem with that approach is that it would make the set_cell function super long, and it would also not work with scene tiles (unless we want to make it work with scene tiles, but that would means that it may cause issues with moving scenes).
  • provide a transform_alternative_tile(alternative_id : int, flip_h : bool, flip_v: bool, transpose: bool) -> int function that would set the higher bits of alternative_id.

Would implement #3967.

  • "Get rid" of TileMap quadrants

TileMap quadrants are required for rendering, but they cause significant performance issues for anything else. Indeed, when a quadrant is modified, the whole quadrant needs to update, including the physics, navigation, scenes, etc... systems. The internals should be reworked so that quadrants are only used for rendering, where they are needed. This likely means compat breakage if we rename the property or change the behavior of the quadrant_size property a bit. It should not be that big of a deal.

Implemented by godotengine/godot#74603

  • Allow automatically merging navigation/collision polygons

To improve performance, merging polygons for navigation and collision polygons would be helpful. For collision, it would also help to avoid characters being stopped while running a flat surface and issues like that. For navigation, it would allow creating less regions, and thus create straighter navigation paths.

To avoid triggering again a full merge of the TileMap, the collisions shapes and navigation polygons could be merged inside quadrants. Those quadrants could have different sizes than the rendering one if the previous point is implemented.

  • Remove terrain sets

The main purpose of terrain set is to group a set of terrains under a same "terrain matching mode". It however bloats both the UI and make the API more complex. Instead, someone (sorry I don't remember who) suggested to simply assign a matching mode to each terrain. Only terrains with the same mode would interact with each other. That should simplify the API and the UI a lot, but it would definitely break compatibility on the API side (the tile data should be easy to keep though)

  • Move layers to node

To respect the common Godot workflow to add things to the tree, it would be great to move layers to nodes. After all, layers are basically CanvasItems. That, however, causes some challenges:

  • The selected layer feature, dimming other unselected layers should still work as it is super useful. It's a bit more complex to implement when done on several nodes.
  • The parent "TileMap" node should block its children positioning, like containers do for control nodes.

Technically, this should not be super complex to implement, but of course, this is compatibility-breaking.
Also, that would require every TileMap user to add a TileMapLayer node to be able to use a given TileMap. Also, the TileSet would be on another node than the Layer, which might be a bit annoying to work with.

More solutions could be imagined here, like a TileMapGroup node that would use several child TileMap as layer, and impose them a TileSet. Other solutions could be find I guess.

  • Allow moving alternative tiles within a grid, maybe more

The way alternative tiles is made makes things difficult to work with, especially if we now want to move the flip/transpose stuff to the TileMap. To help users with that, the idea would be to be able to lay alternative tiles anywhere on a grid, so that people would organize it however they want. That brings some challenges to the table, as users would like to get an alternative ID out of it's coordinates on the grid. This would require a mapping function from coords to (altlas_coords, alternative_id), and update the API to allow moving those alternatives tiles on the grid.

This leads to another possible improvement, that is for super long term (likely 5.0, not before, if it ever happend). If we consider moving alternative tiles to a grid, we could move everything in a TileSet to a single grid too, and thus lay out all TileSet sources (atlas and scenes) to a single grid. The TileSet would then provide you with a unique ID for each tile, so that moving TileSet sources on the atlas would not lead to a breakage of all your TileSet. A function would be provided to give you an ID for a given coords. This would simplify all TileMap and TileSets APIs which currently use 3 IDs source ID, atlas_coords and alternative_tile. All functions would then now use a single ID instead. To set a cell you could do something like:

var id = tile_set.get_tile_id_for_coords(coords_in_tileset)
tilemap.set_cell(coords_in_tilemap, id)

instead of:

tilemap.set_cell(coords_in_tilemap, source_id, atlas_coords, alternative_id)

This would also allow to remove the source list of TileSet's editor UI and would thus make things a lot simpler: just drag your texture on the grid and it works. TileSetter hacs a bit of this UI and it might be a good example about how it could work for us.

I'll try to add more things to the list when I remember ideas.

@KoBeWi
Copy link
Member

KoBeWi commented Mar 4, 2023

Another needed feature is collider merging. Right now every tile adds a separate polygon (!) to the physics layer, which results in performance issues with very big TileMaps. It's also surprisingly easy to hit the seams between tiles, which may result in unexpected bouncing or colliding of some objects. The collider merging would basically try to merge all shapes into one big polygon. A single polygon, even if it has hundreds of vertices, is vastly more performant.

Move layers to node

Only if switching with the shortcut will still be possible.

@Calinou
Copy link
Member

Calinou commented Mar 4, 2023

Another needed feature is collider merging. Right now every tile adds a separate polygon (!) to the physics layer, which results in performance issues with very big TileMaps. It's also surprisingly easy to hit the seams between tiles, which may result in unexpected bouncing or colliding of some objects. The collider merging would basically try to merge all shapes into one big polygon. A single polygon, even if it has hundreds of vertices, is vastly more performant.

This will also help reduce collision issues with seams between shapes.

That said, a single large polygon may take a while to be created (and that approach may not do well with a chunked/procedurally generated TileMap). Should we create a single shape per row/column/quadrant instead?

@dalexeev
Copy link
Member

dalexeev commented Mar 4, 2023

  • Move layers to node

To respect the common Godot workflow to add things to the tree, it would be great to move layers to nodes.

What are the advantages of this option? I saw this idea, but I do not understand what problem it should solve. Especially if we artificially block many properties of layers as nodes.

Also, one user noticed that you cannot use different cell sizes for different layers of the same TileMap. But this does not depend on whether the layers are nodes or not.

@smix8
Copy link

smix8 commented Mar 4, 2023

In the NavigationMeshGenerator pr godotengine/godot#70724 the NavigationRegion2D receives a navigation polygon baking feature. The baking feature merges the entire TileMap navigation polygons into one optimized polygon by parsing all the TileMap used collision shapes or navigation polygons. This works more or less the same as NavigationRegion3D and GridMap.

217048075-9cd9c4c5-5dfa-4c76-bf86-ea64331caeca

The same behind the scene feature could be retrofitted to be used for physics collision merging either by quadrant or for the entire TileMap. From tests it is pretty performant even for large and complex TileMaps and also can be split into steps with a WorkerThreadPool to not block framerate when doing runtime changes to the TileMap tiles.

I would not remove the TileMap quadrants. You need some in-the-middle update unit between cells and the entire TileMap.

@kleonc
Copy link
Member

kleonc commented Mar 4, 2023

Tile rotations and flip.

(...)

Regarding the API, I see two solutions to the problem:

  • make set_cell provide 3 bools to flips to the tile. The main problem with that approach is that it would make the set_cell function super long, and it would also not work with scene tiles (unless we want to make it work with scene tiles, but that would means that it may cause issues with moving scenes).
  • provide a transform_alternative_tile(alternative_id : int, flip_h : bool, flip_v: bool, transpose: bool) -> int function that would set the higher bits of alternative_id.

Note these 3 bools are complete as they do allow all rotations etc. but I don't think they're user friendly. Like it's not obvious what should be passed to get 90 degrees rotation, etc. Maybe a better solution would be to add a flags enum for it instead. This way it would be a single parameter, and also many common operations could be exposed as combinations of the basic ones. E.g. something like:

FLIP_H = 1,
FLIP_V = 2,
TRANSPOSE = 4,

ROTATE_90 = FLIP_H | TRANSPOSE,
ROTATE_180 = FLIP_H | FLIP_V,
ROTATE_270 = FLIP_V | TRANSPOSE,
...

I guess with such approach the question would be what should be the exact naming for each of 8 combinations, and whether maybe some combinations should be exposed as few different namings (like e.g. if there would be ROTATE_90_MIRRORED, ROTATE_180_MIRRORED and ROTATE_270_MIRRORED then ROTATE_180_MIRRORED would be the same as FLIP_V).

@Zireael07
Copy link

@kleonc this ties into another open proposal about bitmasking being more user friendly

@groud
Copy link
Member Author

groud commented Mar 8, 2023

Another needed feature is collider merging.

Added it to the list, and mentioned navigation too, as smix8 suggested to.

What are the advantages of this option? I saw this idea, but I do not understand what problem it should solve. Especially if we artificially block many properties of layers as nodes.

As we exposed a lot of properties of the internal canvas item, a layer now shares a lot of properties with a basic Node2D (modulation, visible, name, etc...). And it would make sense to add the possibility to set a shader on a layer, or things like that.

Eventually, it would also make the API a bit simpler (as you would do $MyLayer.modulation = color instead of $TileMap.set_layer_modulate(layer_index, color) as well as the editor UI (you would not need to have the layer selector dropdown anymore, the layer list is easier to edit in the node tree, etc...)

Initially I did not plan to use nodes for layers, but people kept asking for per-layer features, so in the end I feel it might deserve a custom node.

On a side note, I am more leaning towards implementing a TileMapGroup node, that would have a TileSet property. TileMap would have only one layer, with an optional TileSet. If a TileMap is a child of a TileMapGroup node, it would use the parents TileMapGroup's tileset and would see it's position locked. Also, the TileMapGroup node would handle the data for dimming not-edited layers.

Note these 3 bools are complete as they do allow all rotations etc. but I don't think they're user friendly.

I was mostly discussing the internals. Exposing an enum makes sense, but it's likely that implementing rotation/flip functions would be even simpler.

@smix8
Copy link

smix8 commented Mar 8, 2023

I think the TileMap layers are fine as they are, just the naming and gui could be better, looking at you layers_layers_of_layers function. Maybe allow some more drag&drop with layers but still contained inside the same TileMap node.

Initially I did not plan to use nodes for layers, but people kept asking for per-layer features, so in the end I feel it might deserve a custom node.

Users ask for a lot of things, not always aware of all the issues they invite with them.

By adding dependency on subnodes you are opening a giant can-of-worms, basically begging for trouble. If we learned one thing from all the nodepaths and debug visual nodes troubles in the past it is that everything that can not be an extra subnode should not be an extra subnode.

@Gnumaru
Copy link

Gnumaru commented Mar 8, 2023

I also think layers should remain inside the same node.

If layers are kept inside the node, the users always has the option of not using them and use several nodes if he wants to. But if layers are moved outside the node, there will be no alternative.

BUT, if there are good enough reason to separate them, like a performance or usability gain, or making the architecture/implementation simpler, then it is justifiable to use separate nodes.

@groud
Copy link
Member Author

groud commented Mar 8, 2023

By adding dependency on subnodes you are opening a giant can-of-worms, basically begging for trouble. If we learned one thing from all the nodepaths and debug visual nodes troubles in the past it is that everything that can not be an extra subnode should not be an extra subnode.

Oh, that's for long term anyway, not a soon-to-be-released version anyway.
But in general, I think you overestimate the risk here. The TileMap internals should be pretty straightforward to port to another node, as the API and internal methods are already split per-layer.

If layers are kept inside the node, the users always has the option of not using them and use several nodes if he wants to. But if layers are moved outside the node, there will be no alternative.

This would be the exact same with my last comment's proposal. The TileMap node would be used as a layer only if used as a child of a TileMapGroup. Otherwise, it would provide a single layer with an associated TileSet. No feature is lost here.

@Proggle
Copy link

Proggle commented Mar 10, 2023

I have a few small things that I think would help for UX

For collision:

image

I'm not seeing any 'close curve' tool in the layer painter - there's just add polygon, delete point, and move point. It would be really nice to have one, because when trying to close the curve I keep missing the end node somehow, and Godot just adds more points in a little cluster to my polygon.

This tool already exists on the path2d node, so this would make it consistent with the existing UI.

image

Second:
I'm not seeing any way to view collision shapes for tiles in the editor - they show up in the game itself when the 'show collision shapes' is on, but it'd be nice to have collision be visible while mapping, so you can see if you have a gap somewhere.

Finally:

image

If no physics or navigation layer exists in a tileset, Godot currently displays a gray bar for "physics" or "navigation" that can't be interacted with, which doesn't have a submenu. It would be nice if there were a submenu option for 'create physics layer' or 'create navigation layer' there, so you can just create it and immediately use it seamlessly.

@groud
Copy link
Member Author

groud commented Mar 10, 2023

I'm not seeing any 'close curve' tool in the layer painter

That's a good idea, it could be added.

I'm not seeing any way to view collision shapes for tiles in the editor - they show up in the game itself when the 'show collision shapes' is on, but it'd be nice to have collision be visible while mapping, so you can see if you have a gap somewhere.

This already exists, it's there:
Screenshot_20230310_103618

If no physics or navigation layer exists in a tileset, Godot currently displays a gray bar for "physics" or "navigation" that can't be interacted with, which doesn't have a submenu. It would be nice if there were a submenu option for 'create physics layer' or 'create navigation layer' there, so you can just create it and immediately use it seamlessly.

I am not sure this would be easily feasible, but I guess that could be done yeah.

Edit: ah, and sorry for the missclick close.

@groud groud closed this as completed Mar 10, 2023
@groud groud reopened this Mar 10, 2023
@Mickeon
Copy link

Mickeon commented Mar 10, 2023

To respect the common Godot workflow to add things to the tree, it would be great to move layers to nodes.

100%. Absolutely. I was literally thinking about this for soooo much time, but I was afraid that you, groud himself, would take issue with this, because the API had been pretty much finalized.
I'm so, so happy this is on the table, now. The problem was that users couldn't easily edit multiple layers, but the appropriate solution for me was never about putting everything all in a single Node. Rather, the solution was improving the workflow with multiple TileMap nodes. It's part of the reason the TileMap API by has been bloated by quite a large margin.

With that said, I do not think multiple "TileMap layers" should be sub-nodes. Coupling them this way doesn't solve much of the confusion behind them. Rather, just normal TileMaps that would be able to "cooperate" with one another in the editor.

@Mickeon
Copy link

Mickeon commented Mar 10, 2023

Tile rotations and flip.

Regarding this, the solution doesn't look nearly as difficult as it is made to be.

As kleonc stated, an enum would suffice for this purpose. However, this also exacerbate how much more complex the TileMap API has gotten. Favouriting nodes for layers would definitely help a tad, but this singular function call would still be quite the mouthful:

var pos = Vector2i(1, 4)
var tile_id = 1
var atlas_coords = Vector2i(-1, -1)
var alt_tile = 0
set_cell(0, pos, tile_id, atlas_coords, alt_tile, FLIP_H | TRANSPOSE)

Where to even put the additional flip/transpose arguments?

@Proggle
Copy link

Proggle commented Mar 11, 2023

I'm not seeing any 'close curve' tool in the layer painter

That's a good idea, it could be added.

I'm not seeing any way to view collision shapes for tiles in the editor - they show up in the game itself when the 'show collision shapes' is on, but it'd be nice to have collision be visible while mapping, so you can see if you have a gap somewhere.

This already exists, it's there: Screenshot_20230310_103618

Oh, perfect! That does just what I want, maybe needs a rephrasing of the tooltip, but that's a pretty trivial documentation tweak. (I was misled by the tooltip, and assumed that if if the collision boxes didn't appear when visible collision was already set on in the editor, that the property wasn't what I was looking for.)

image

One other thing that I probably am just having trouble finding - when using the physics painter is there a way to grab the collision set for an existing tile?

image

If not, can I suggest that right-clicking a tile should load its collision data into the physics window? That would make it easy to tweak collision from this tab (instead of going back to the 'select' pane), and would also make it possible to copy a collision polygon across multiple tiles in only a few clicks.

@KoBeWi
Copy link
Member

KoBeWi commented Mar 11, 2023

One other thing that I probably am just having trouble finding - when using the physics painter is there a way to grab the collision set for an existing tile?

Use the picker tool (P).

@TrayserCassa
Copy link

Hey, I don't know if I'm right here, but I used the new Tilemap now quite a while so maybe I'm missing some stuff or this would push the Tilemap forward:

Currently you can add scenes, but you can't edit properties of a Scene, right? The use case would be a teleporter scene which will take place as a door for a house. But I need to set which scene he needs to load, so I need properties access for each placed scene. I think this would be really nice but not really necessary right now.

@Gnumaru
Copy link

Gnumaru commented Mar 12, 2023

Currently you can add scenes, but you can't edit properties of a Scene, right?

Indeed, that would be really nice. You currently cannot change any property of instanced scenes in a TileSetScenesCollectionSource (like, for example, if the root of the scene is an audio player, changing the audio stream or the root node). But this would be more useful if it where associated with the tilemap instead of the tileset.

@KoBeWi
Copy link
Member

KoBeWi commented Mar 12, 2023

If you just need a few variations of a scene, you can use inherited scenes as a workaround.

@securas
Copy link

securas commented Mar 12, 2023

Here are a few UX suggestions:

  • When creating automatically tiles, include the possiblility to have all the cells included in the tiles, even empty cells. This is useful for artists+programmers, which often draw the tileset as they fill in the levels. It is also very useful when prototyping since only new cells have to be drawn and then can be immediately used without having to alter the tileset
  • I suppose this has been requested elsewhere but the possibility to delete painted properties like collision. Currently, there's no way other than defining an empty collider and repainting.

@KoBeWi
Copy link
Member

KoBeWi commented Mar 12, 2023

I suppose this has been requested elsewhere but the possibility to delete painted properties like collision. Currently, there's no way other than defining an empty collider and repainting.

Well, you can't really "delete" data, only reset it to the default value. Maybe using right-click for that would be nice (but it conflicts with panning).
btw there's a shortcut for empty collider - C.

@securas
Copy link

securas commented Mar 13, 2023

Panning should be done only with the middle mouse button, like the main window.

@Neicul
Copy link

Neicul commented Mar 13, 2023

Another thing I am missing currently is the option to create custom tile placement logic for terrain.
I would like to use the terrain system for adding conveyor belts in my game.
Now, for conveyors, you not only need the peering bit logic to place the correct tile but also some way to incorporate conveyor direction. Sadly, there is currently no way to use the Custom Data Layers to do that.

Here's an example:
image

@securas
Copy link

securas commented Mar 13, 2023

In general, the terrain system of the v3.x and v4 tilemap systems is very limiting. I think that the target of providing an autotiling logic that is easy to use and prototype has been considered more important than the use of truly flexible rule-based autotiling schemes seen in tilemap softwares such as tiled, ldtk and others. I think that this is one of the best features of the current autotiler. However, for the sake of more advanced autotiling, I would suggest the implementation of a rule-based autotiling system (see LDtk) or, even better (and probably easier), a script-based autotiling system. In Godot 3.x, it was possible to gdscript the tileset resource to define rules by overriding the _forward methods though there is some limited documentation on it. In v4, this is unclear.

@Portponky
Copy link

Along with people wanting to rotate and flip tiles on the fly, I frequently see users wanting to modulate the color of individual tiles. That is, not just a few colours here and there, but using a lot of colors across a lot of tiles. The alternate tile system is very useful, but it gets frustrating for users to have to take what is essentially transient data and make it fixed into the tileset. It bloats out the tileset and is unwieldy. I'd suggest moving all of these properties into the tilemap cells, rather than the alternate tiles, though that is probably too severe a change for a stable API.

Removing terrain tilesets was a move I proposed a good while back, and I still strongly support. I've implemented a plugin for fully featured autotiling (here) and have had a substantial amount of positive feedback. One of the key features is that any terrain type can interact with other terrains in any desired way, regardless of type/grouping. I hope that Godot's built in terrain system can improve to the point where my plugin is obsolete.

@Calinou
Copy link
Member

Calinou commented Mar 14, 2023

Panning should be done only with the middle mouse button, like the main window.

Laptop trackpads rarely have a middle mouse button, which is why you can use the right mouse button for panning as an alternative to the middle mouse button. It's a feature many people rely upon, so we can't remove it like that.

@dalexeev
Copy link
Member

AnimatedSprite{2D,3D} has fps field that affects all frames, and the default duration of 1.0 is relative, not absolute.

But I think it's probably best to add the ability to edit this via the Paint Property in the TileSet editor, since each animation frame is a tile.

@jonSP12
Copy link

jonSP12 commented Mar 20, 2023

Thank you so much for all the time and work you’ve put into Godot 4’s terrain system. It seems very powerful and I’m really excited about all the new possibilities.

I’ve been working on a plugin for bulk editing terrain bits and applying common autotile templates. I’m currently trying create documentation for this plugin to help users set up their tilesets, but I’m running into problems with difficult-to-predict results in the tilemap.

As others here have also requested, I am wondering if the matching algorithm could be made to feel more deterministic.

A large contributor to the feeling of unpredictability is that order of tile placement appears to be prioritized over matching terrain bits in certain cases, and I believe this is already being worked on.

Another aspect is the behavior of terrain IDs (center bits). They seem to serve two functions:

  1. Put a hard constraint on the tiles that can be placed in a cell, only allowing tiles that have the same terrain ID the user placed on the tilemap. I think this is vital for predictability and proc gen and should not change
  2. Determine the order of matching and whether tiles are matched. If I understand correctly, when a user paints a cell with terrain "A", the algorithm first looks at surrounding tiles where terrain_id="A" and chooses its tile, and possibly changes theirs, based on peering bits. But if a surrounding tile has terrain_id="B", it does not prioritize trying to matching with them via peering bits. It instead determines matches based on other, more opaque aspects, such as the terrain ID order in the tileset (merging if it is the first terrain listed). Sometimes it seems to give up and leave a non-matching tile even when a matching one exists. A tile that would match based on peering bits but not terrain ID appears to be ignored.

Here are examples of how the order of terrains currently changes placement:

typical_setup typical_setup dirt_first dirt_first

And how tiles with different terrain IDs but matching peering bits are ignored:

shared_bits shared_bits dirt_first_shared_bits dirt_first_shared_bits

I am wondering if this second behavior of terrain IDs could be tweaked to first find matching tiles based on the peering bits of surrounding tiles regardless of their terrain ID, and then only engage in other, less transparent, behaviors if a matching tile has not been found. (I am not talking about changing the terrain ID of the adjacent cell. Just prioritizing matching a tile of that id to the newly placed terrain ID based on peering bits.)

This would feel much more deterministic and would also allow more complex uses of the terrain system. For example, a commonly requested feature has been to be able to treat multiple terrains as one in the matching process, so that they can be placed separately but merge together as if they are the same terrain by the matching algorithm (Celeste-style, or for slopes in a platformer).

For certain art styles, I think merging could also be used to mitigate the exponential number of connections needed between terrains each time a new one is added, allowing users more full use of the terrain system.

The most obvious option to accomplish this is providing a scripting hook. Merging autotiles were accomplished in Godot 3 by overriding _is_tile_bound(), but, in my understanding, it can’t be as straightforwardly opened up to scripting here.

One option is taking advantage of the terrain order quirk in the "Dirt terrain first" example above. But it feels precarious as it relies on choosing incorrect tiles based on peering bits. And, in my understanding, it may not behave this way consistently enough to make it a viable way to plan tilesets. (Correct me if I’m wrong — if this is indeed a viable exploit, I’ll happily use it.)

However, if all adjacent cells were considered in matching peering bits (the terrain ID constraint was removed), merging terrains should be viable by having tiles with different terrain IDs, but common peering bits.

Here is a demonstration of how matching could work without considering TileSet terrain order or adjacent terrain IDs:

proposal_separate_bits proposal_separate_bits proposal_shared_bits proposal_shared_bits

For users who want more control, this might open up even more complex user-controlled matching behaviors (like complex cliff walls), though that would need more investigation.

A downside is that it could match peering bits of a third, undesired terrain and create an unexpected strip of that terrain. But that is not a new issue as it already happens now from time to time and any increase in this behavior might be mitigated to an extent by assigning higher priority to matching peering bits with one of the two cells’ terrain IDs, and by user education.

If removing the consideration for terrain order is not possible (I understand special behavior was added to terrain 0 to allow matching with void?), documentation of its effects would be very helpful. Perhaps there could be a warning icon next to the first terrain in the right-sided tileset inspector that explains how it is treated differently?

I welcome any feedback and corrections — all my understanding of the algorithm is inferred from experimenting and reading github comments, as I haven’t been able to follow it in the source code.

Just a simple question, but why are you doing this ?!?
I know its easy, to get ahead when coding your own editor, and make lots of improvents based on experience ( trial and error )...
But... wouldnt it be better to have the normal stuff frist ?
A normal base:

  • paint tile
  • paint tile with select multiple tiles
  • flip / rotate tile
  • tile layers
    ----------------//--this-came-out-3-years-later---//-------------
  • autotiles

the tile node, is already convoluted, with stuff ( colliers, slope colliders... now its all collider into one..etc.. )
all this on top of a base that is not what a default tileSet should be... ( adding more stuff to it doesnt make better )

For me this is the same thing that putting a 500 hp engine on a car, that only has 3 wheels... its funny...

@seocwen
Copy link

seocwen commented Mar 24, 2023

I can't say I for sure understand how tiles work in 4.0 at the level of architecture, so I'm just going to ask for clarification.

Near as I understand, the design has been that tiles are considered discreet resources defined in Tilesets. They can be extremely complex resources with many varied parameters - even customizable ones. They can even have variants. But to Tilemaps, a tile is just a glorified table index pointing to this incredibly complex resource in its Tileset. In 4.0, Tilemaps are just integers, and that's made something as rudimentary as flips and rotations hard, because those are parameters, and thus aren't indexable without some decoding.

If all this is as I understand it, I think it's likely to result in greater headaches in the future. It's simply not true in modern games that a Tileset can depend on there being a discreet, countable list of every possible object that can appear inside the environment that it makes possible. Procgen and player customization are things now. It is not possible to know every possible combination of parameters we might want to assign to a tile. Tiles do a lot - flips, rotation, color, depth, collision, transparency... and that's not even getting into terrain and custom data.

I agree it simplifies things immensely to think of, on the one hand, a master list of possible tiles that's already dealt with our parameter hell for us, and a grid that references into that list. But imagine, on the other hand, if we treated Tilesets as a set of defaults, and Tilemaps as a choice between default settings and overrides. That'd be a lot of power. I'm aware that duplicating the Tileset interface in Tilemaps would cause everything to explode. However, I think we should at least consider expanding what Tilemaps hold as data structures.

We could expand Tilemaps to encode a couple of key paraments such as modulation, depth, or collision, for instance. I couldn't say what a "just right" size for such an object would be, so I don't think that's the best way. What I might actually recommend is, by default, keeping everything exactly as it is, but allow users to select a parameter overrides feature. While a parameter override is active, a data structure is created which allows users to override parameters as they they appear in the Tileset, using more or less the Tileset interface for that single parameter, but on individual tiles, and see realtime updates. Under the hood, the data is stored as a simple array of the relevant data, but calling a getter for a Tilemap tile with an override will return the override data instead of its Tileset data. The override data defaults to the tileset data when it is first created, or when it is erased.

This way, we still have the relatively trim and efficient indexing structure we have now most of the time, with only a small incremental penalty as we demand more parametric customization directly into the Tilemaps system. It seems like a fair tradeoff.

@Proggle
Copy link

Proggle commented Mar 27, 2023

Hey, this is probably another thing where I just can't figure out the UI or find the hotkey, but is there any way to copy and paste an entire stack of tiles (across multiple layers)? If you need to add something to the middle of a map and already have large chunks built, it'd be nice to be able to move big pieces as a whole instead of layer by layer.

On the topic of tile stacks, a feature that was very useful in other engines I've worked with was having an option for tiles to override physics for tiles on lower layers.

For instance, if you put a bridge (marked as having no collision) on a layer above nonwalkable water tiles which do have collision, characters could walk over the bridge.

Would this be at all possible, or would it require a fairly deep rework of how the physics of the tilemap is assembled?

Alternatively, if we could toggle 'physics enabled' on a tile layer, to make tiles on that layer ignore collision, that would achieve a similar effect.

EDIT:

Allow moving alternative tiles within a grid, maybe more

This would also offer an additional UI improvement: being able to move normal tiles within the TileSet grid without breaking the links to that tile in a TileMap. As is, it appears that the Tilemap is pointing to the specific x/y coordinates of a tile rather than to a specific tile object, so if you change where a tile is located on your PNG tile sheet, you can't just move the corresponding tile in the tileset and expect the tilemap to grab the tile from the new location.

@CodeLazier
Copy link

Great idea, currently the performance of tilemap is worrying me, do not define any layer and other properties (such as collision, navigation), as long as the scene paint 6000*6000 (cell size:16x16, eq: 375x375 cell), the editor freezes, delays, almost does not work. Even crashes (vulkan error: many too objects), although improved by better GPU/CPU, are currently almost impossible to paint large maps through the editor.

@jonSP12
Copy link

jonSP12 commented Apr 27, 2023

This is the changing levels using PNG images instead of tiles

https://user-images.githubusercontent.com/77247594/234847329-c789b589-118e-40d9-b326-6cb020472729.mov

Using png images instead of tiles the change is instantaneous, it doesnt take any milisecond...

//----------------------//---------//-------------------------------

This is the changing levels using tileMaps made in Tiled exported to godot has *.tcsn

https://user-images.githubusercontent.com/73213594/234847388-bf377fbf-33f1-2176-8b3e-2b1bad93f56b.mov

In here it takes about 1 sec to change between levels, it feels like its processing something....

//-------------------------//------//----------------

the tilesets are no longer has they used to be in the 90's
or later the spectrum 128k era... I could be wrong in this... But has far was i know, The objective was to reduce texture space by reusing some of the textures.

TEXTUREpAGE

Now tiles are used has objects with lots of properties, that get instantiated/spawned on screen with the intent of doing completely diferent things,
instead of drawing a level/background faster than a png...
Its a totally diferente thing only the name is the same 'TileMap'
The tileSet in godot like i said previously in my spitefully critical comment, seems to drawing the tiles on the console window then passing them on into the level has tings with properties...
( totally diferente thing )

.

@seocwen
Copy link

seocwen commented Apr 27, 2023

You know, when I think about it, the Tilemap editor could probably use more like an entire dev team working on it. Tilemap Editors are complicated enough that they're usually stand-alone applications. Depending on the type of game you're doing, you could end up treating the Tilemap Editor more like an entire level editor and end up wanting to do 90% of your entire game inside it rather than all the rest of Godot, which I think is part of what's making these issues so complicated. That, and the very data-centric procedural generation stuff. Either way I think it's a higher priority area than the resources dedicated to it would suggest.

@Calinou
Copy link
Member

Calinou commented Apr 27, 2023

This is the changing levels using tileMaps made in Tiled exported to godot has *.tcsn

The Tiled exporter generates a lot of alternate tiles if you enable the option to do so. Most of these alternative tiles will remain unused, which is hardly ideal in terms of hardware utilization. Also, you should test performance in a project exported in release mode as a debug build has significant overhead with all CPU-bound operations (i.e. everything that isn't GPU-bound or I/O-bound).

@KoBeWi
Copy link
Member

KoBeWi commented Apr 27, 2023

Make sure your TileSets are not embedded in the scene.

@jonSP12
Copy link

jonSP12 commented Apr 27, 2023

The Tiled exporter generates a lot of alternate tiles if you enable the option to do so. Most of these alternative tiles will remain unused, which is hardly ideal in terms of hardware utilization.

It also exports transparent tiles that get into conflict with the godot tileSet

trans

Has i was expecting the flip/rotate triggered a chain of problems, that dragged on top of other things... Also now you ll have to use 3 applications ( tiled/photoshop/godot ), to get a simple castlevania circle of the moon level... Making it very difficult to add, edit or remove levels later on...

You know, when I think about it, the Tilemap editor could probably use more like an entire dev team working on it. Tilemap Editors are complicated enough that they're usually stand-alone applications. Depending on the type of game you're doing, you could end up treating the Tilemap Editor more like an entire level editor and end up wanting to do 90% of your entire game inside it rather than all the rest of Godot, which I think is part of what's making these issues so complicated. That, and the very data-centric procedural generation stuff. Either way I think it's a higher priority area than the resources dedicated to it would suggest.

I dont think making a tile editor is very dificult... All it would take would be a simple drawing program using brushes instead of tiles, godot already has a build grid, theres also a viewport texture...
........//......
That why i think the only option now, would be to have 2 tileSet Editor's... One that would simple draw levels / backgrounds, the other one for scripting / procedural generation stuff.

@Proggle
Copy link

Proggle commented Apr 27, 2023

Even if we go back to like, NES Mario, tilesets were always designed in order to include physics and other interactions, rather than being purely graphical.

EDIT: to give an example, here's the tile data array in RAM for the start of the first level, overlaid on the displayed tiles (with 00 values omitted for clarity). Both physics and graphics are based on looking up the values in this data array (using what the disassembly calls "GetMTileAttrib").

@jonSP12
Copy link

jonSP12 commented Apr 27, 2023

Even if we go back to like, NES Mario, tilesets were always designed in order to include physics and other interactions, rather than being purely graphical.

that is such a lie

EDIT: to give an example, here's the tile data array in RAM for the start of the first level, overlaid on the displayed tiles (with 00 values omitted for clarity). Both physics and graphics are based on looking up the values in this data array (using what the disassembly calls "GetMTileAttrib").

but there are no physics in there only graphics

@Gnumaru
Copy link

Gnumaru commented May 10, 2023

Back in 3.x, tilemaps had the option to use the tilemap colliders as part of a parent body or area:

image

This was really useful for creating tilemap nodes as child of area2ds and use that area for whatever. For example, you could have a "Damager" script attached to the area2d and paint hazards like spikes in the tilemap. Besides, it was easier to setup a collision parent, like an area2d or any body2d and have all the colliders in the tilemap act as was set up in the parent. And even more useful was setting collision_use_parent to true but not using a body or area as parent to ensure that that tilemap was going to be just decoration, guaranteed to be colision free.

In 4.x these things became less convenient. Since we are discussing these things, we could consider restoring the collision_use_parent functionality or at least somehow make it easier to use tilemaps with area2ds.

@jonSP12
Copy link

jonSP12 commented Sep 18, 2023

You know, when I think about it, the Tilemap editor could probably use more like an entire dev team working on it. Tilemap Editors are complicated enough that they're usually stand-alone applications. Depending on the type of game you're doing, you could end up treating the Tilemap Editor more like an entire level editor and end up wanting to do 90% of your entire game inside it rather than all the rest of Godot, which I think is part of what's making these issues so complicated. That, and the very data-centric procedural generation stuff. Either way I think it's a higher priority area than the resources dedicated to it would suggest.

Yes, extremelly difficult, with 90% of the entire game inside.
An entire dev team working on it, may not be enough. You might want to add in there also the entire NASA team...

It took me about 1 week to do this, a few hours a day

godot-4-TileDraw
https://github.com/jonSP12/godot-4-TileDraw.git

Its still not finished, but the basic stuff its there. The very ( data-centric procedural generation stuff ). collisions, access to tiles in game, i wont be adding this one will be mainly for drawing... change tile color...etc..

@seocwen
Copy link

seocwen commented Sep 19, 2023

That's just super, @jonSP12. Here's a gold star. You get an A+ on the assignment. But I'm afraid making something competitive with the other free Tile Editor software out there's going to be a little more work than that. Users of Tile Editors have a lot of bespoke needs, you see. But keep on trying, I'm sure you'll get there. Or maybe you can join one of the existing Tile Editor projects so that the time you spend is will be better appreciated by other people interested in the same things. Tiled is a great project I'm sure would be glad for you to lend a hand. Or Godot. Godot's tile editor could really use some love from an ambitious, talented developer like you. Gold star's are great and all, but they're not everything.

@jonSP12
Copy link

jonSP12 commented Sep 19, 2023

Iam not intrested in gold stars, hey i know the admins will jump in here and say we cant post this stuff, it will be my final message.

Its the way of how you and some other people, sometimes express things in an exaggerated way or a philosophical way...
"A gold Star", "90% percent ", "an entire dev team", "A+ on the assignment", "10 yrs to develop an app"...etc...
I aggree with you on the "tile flip" issue, problem is took 2 years just to make a tile flip. I always wrote the same thing ( not that anyone reads what i write but whatever ),
I always wrote instead of going throw the godot 4 tileSet that is already convoluted, "make a new one" always "make a new one"... But some people have a talent to write in a poetic or philosophical way, and like to write that a tileSet is very dificult thing among other funny things.
I now my tileMap is Crap... but its just a consept, now its adding the buttons, editor menus and so... And that is hard to do, has Hard has finding "passWords123" and not having a cristal ball, or a tooth fairy to tell you what this stuff is supossed to do... You almost have to try telepathy here..

@akien-mga
Copy link
Member

I have to remind you both that we have a Code of Conduct which you have to follow when writing in Godot communities, including GitHub.

Please stay respectful of each other and constructive in the technical discussions.

@seocwen
Copy link

seocwen commented Sep 19, 2023

Of course. I got carried away, and I apologize, both for undervaluing the contribution made by @jonSP12, and for wasting the time of my fellow subscribers. Nothing would please me more than getting back on topic.

I note that the tile flipping/rotating issue has been recently closed: #3967
I'm curious how that was finally implemented, considering there was a great deal of concern, in the beginning, over how that would be handled. In particular, I'm wondering whether the tiles might be more flexible overall in the future, or if the fix was particular to that issue.

@KoBeWi
Copy link
Member

KoBeWi commented Sep 19, 2023

Tiles are stored as 64-bit integers. 16 bits for source ID, 16 for x coordinate in the atlas, 16 for y and last 16 for alternate tile ID. The transforms reserved the last 4 bits of alternate tile, which means there is now 12 bits for alternate tile ID and last 4 are for transform.
As you can see, there is very limited space to add new "properties" to tiles, so e.g. adding per-tile modulation is not possible. This is to ensure that the tiles are stored efficiently.

@HSven1611
Copy link

Are there any plans to make the navigation include all layers and not only the first? It seems like the tilemap editor already supports this (there are checkboxes for "navigation_enabled" for each layer) but apparenlty e.g. navigationRegion2d only uses the first layer of the tilemap and so does navigationAgend2d.

See e.g. this image with the same tile form the same tileset being excluded in layer0 but ignored in layer1.

image

@Zireael07
Copy link

@HSven1611 Don't spam in unrelated issues when there are dedicated ones for navigation in other layers

@HSven1611
Copy link

HSven1611 commented Apr 8, 2024 via email

@groud
Copy link
Member Author

groud commented Apr 8, 2024

@HSven1611 see: godotengine/godot#85856

It's already merged, so it should be working in 4.3.

@chryan
Copy link

chryan commented Aug 6, 2024

Recently found this thread searching for tile map and related editor improvements.

One feature that would be really useful for me is the ability to create tilemaps with textures that extend outside of their cell size.
e.g. 32x16 texture drawn in a 16x16 cell, with 16x16 of the texture outside of it

Here's an illustration of how it would look:
wall_tiling_ideation_breakaway_section
The teal squares represent the cells, the grey walls are animated to show the space within the cell they are supposed to occupy.

I know there's a bunch of tooling work involved and would be willing to attempt implementing this myself if I can get some direction on how I should approach this feature.

@kleonc
Copy link
Member

kleonc commented Aug 6, 2024

One feature that would be really useful for me is the ability to create tilemaps with textures that extend outside of their cell size.
e.g. 32x16 texture drawn in a 16x16 cell, with 16x16 of the texture outside of it

@chryan That's already supported (showcase below in v4.2.2.stable.official [15073afe3]):

Godot_v4 2 2-stable_win64_eZ5aavdRwe Xn5me2zeUO

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests