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

Option - Draw all layers as if it were a single layer #1274

Open
stevetranby opened this issue May 9, 2016 · 17 comments
Open

Option - Draw all layers as if it were a single layer #1274

stevetranby opened this issue May 9, 2016 · 17 comments
Labels
feature It's a feature, not a bug.

Comments

@stevetranby
Copy link

This would allow viewing isometric tilemaps with multiple "wall" layers so that you could separate tiles in different layers for organization, but then have a Layer[0] tile in front of a Layer[4] tile if it would have drawn in front had both tiles been added to the same layer.

Map Tile Size: 32 x 16
Tileset Tile Size: 32 x 64
Tileset 1 @ 0,0 in Layer 2 (overlaps Layer 1 or 2 tiles that extend vertical above)
Tileset 1 @ 1,1 in Layer 1 (overlaps Layer 2 tiles that extend vertical above the tile base)
Tileset 1 @ 2,2 in Layer 0

Not sure I'm making sense, and I can take a screenshot or two if needed.

Most games probably don't need this functionality, but it would be a nice polished feature to make the editor superior for detailed isometric maps.

This may cause many of the renderer frameworks/libraries to render differently than what Tiled shows, and as such this is a more advanced option toggle that can be hidden in some preferences or sub-menu.

Let me know if this would be easy to implement. Possibly I'll look writing the render code myself and present for having others write the hopefully small GUI code to integrate a toggle.

@bjorn
Copy link
Member

bjorn commented May 10, 2016

This is a very tricky issue to implement with the way Tiled works currently, because everything is drawn per layer and not all layers are tile layers. There's two possible directions I've considered to resolve this:

  • Try to make it work anyway and somehow deal with the fact that in the future, tile layers need not all have the same size nor all use the same tile size (once issue Tile Size per layer not per Map #149 is implemented).
  • Make tile layers "3D" with a default thickness of 1 but the option to increase it, and of course adjusting the tools to work nicely with this.

I'm leaning towards the second option. Though it raises several questions about the UI and the tools, I think it is design-wise more realistic than the first one.

Another thing that would have to be decided, is whether to allocate a single block of memory for such layers, or whether to instead allocate "stacks" of tiles. Of course, another alternative is to simulate a block of memory with a sparse data structure. In the end though, these are all implementation details that should generally not affect the UI.

@bjorn bjorn added the feature It's a feature, not a bug. label May 10, 2016
@stevetranby
Copy link
Author

Interesting. Yeah we use the cocos2d-x tilemap renderer. We've customized it, but I think the default version handles this z-ordering correctly if specified with the custom property ("cc_vertexz" = "automatic") using the depth buffer.

I'm not sure what you mean by "a thickness of 1"?

Our current renderer determines depth order using something along the lines of order the isometric rows from top to bottom as back to front and then use the right down ordering to add a small precision offset to mitigate z-fighting.

It's an interesting problem when having to deal with object layers as well ... as usual possibly semi-unique to our needs. I'll have to look further into how a renderer should deal with object layers. For the most part cocos2d-x renderer, for example, doesn't really handle "tile" objects in object layers well, if at all. I'm also working on a new (or enhanced) tile map parser renderer for cocos2d-x that may need to think about this issue.

A similar features allowing 3D tile placement with a height coordinate as given in the TilemapKit example renderer would probably have the same or similar solution.

In the end creating an in-game tile editor may be the best solution for a game with needs that are this specific and somewhat complex.

@bjorn
Copy link
Member

bjorn commented May 13, 2016

We've customized it, but I think the default version handles this z-ordering correctly if specified with the custom property ("cc_vertexz" = "automatic") using the depth buffer.

Right, you could use the depth buffer for this, but only when you don't use pixels with partial transparency. In general, Tiled supports alpha-layered images so it will have to make sure to render the tiles in the right order. Also, it currently uses the QPainter rendering API, which does not support a depth buffer.

I'm not sure what you mean by "a thickness of 1"?

I mean that currently a tile layer is a 2D grid of cells, which is the same as a 3D grid of cells with a thickness of 1, so that would be the default.

In the end creating an in-game tile editor may be the best solution for a game with needs that are this specific and somewhat complex.

Yeah, that or cope with not 1:1 visuals and have a quick reload feature in your engine to make up for it. Your needs do not sound that specific to me though. Adding 3D positioning of layers and objects is something I want to work towards eventually, also in the context of parallax support.

@MarceColl
Copy link
Contributor

MarceColl commented Mar 1, 2017

Taking this issue too in order to solve #1255

@bjorn, would this completely replace the isometric renderer then?

@bjorn
Copy link
Member

bjorn commented Mar 1, 2017

@MarceColl It doesn't really affect the basic workings of each individual renderer, but each will need to be adapted to handle the cells in the tile layer they're rendering in drawTileLayer as stacks of tiles.

I wonder a little how we could avoid affecting a huge amount of existing code. I suppose the Cell class should be changed to store a list of tiles, but that of course affects its API. I would suggest that you keep the existing member functions of Cell working by having them modify the first entry in its list of tiles. Then we can incrementally go over all the code using those functions and see how they should be changed.

@bjorn
Copy link
Member

bjorn commented Mar 1, 2017

It doesn't really affect the basic workings of each individual renderer, but each will need to be adapted to handle the cells in the tile layer they're rendering in drawTileLayer as stacks of tiles.

Also, since rendering a single "tile stack" will be independent of the renderer, it makes sense to delegate this to the CellRenderer class, which is shared between all renderers.

@MarceColl
Copy link
Contributor

MarceColl commented Mar 1, 2017

So if I've understood correctly your idea is to assign a height h to a layer, and each cell of that layer can have a stack of x tiles, each tile of height h. The CellRenderer draws this stacked tiles one on top of the other essentially creating pseudo-3D using 2D tile images. The stack can grow upwards (walls), downwards (like in #1255) or both.

Now, the problem I see is in the tooling. Existing tools only work on the level-0 tile of the stack (2D grid = 3D grid with thickness 1). I have no idea how you could make the stamp brush to be able to edit all the layers without a lot of work by the user, I feel like it would be a pain to work with.

Now, here's an idea. We restrict the use of "3D tiling" to terrains. The terrain creation window should be revamped to work with stacks. We add a new section that shows all the tiles stacked, with the ability to add new layers in between. Also the possibility to group layers and specify that the group can grow (so that if you increase the size of the stack Tiled knows which tiles it can repeat).

This allows the user to:

  • Create the terrain with the stack layers
  • Change the ordering of the stack layers of the whole map at the same time without a lot of work.
  • Be able to individually change the size of the stack while easily specifying which stack layers will shrink/grow.

Things we would have to do (Im probably missing things @bjorn):

  • Change the Cell class to hold stacks of tiles.
  • Change the CellRenderer class to render stacks of tiles
  • Change the renderers to render from top to bottom ignoring layers except to prioritize inside a single cell.
  • Change the terrain window to work with stacks.
  • Change the terrain brush to work with stacks.
  • Add a way to grow/shrink the stack of an individual cell in both directions from the UI

Problems I see at first glance,

  • How does the stamp brush work with the stacked tiles. Does it allow to individually change visible parts of a stack? Do the changes persist when you change the terrain definition? How can you reset to use the terrain definition again?
  • How do we draw objects? How do we decide if they are behind or in front of a stack?

I see also some optimizations we can do if we go this route, but we can discuss them once we have decided if this is a good way to go with this.

@MarceColl
Copy link
Contributor

I will try to create a mockup of how the terrain creation tool could be tonight when I get home, so that it's easier to visualize.

@MarceColl
Copy link
Contributor

@bjorn do you think this is a good way to go?

Another thing that we should consider:

  • How do we represent stacked tiles in exports, particularly something like in csv

@bjorn
Copy link
Member

bjorn commented Mar 2, 2017

@MarceColl I really appreciate your thoughts on this, but I have had no time yet to read it carefully and answer your questions. I will try to get to it this evening.

@MarceColl
Copy link
Contributor

Sure, no problem.

I will try to get the mockup for this evening too.

@bjorn
Copy link
Member

bjorn commented Mar 2, 2017

@MarceColl Sorry, I'm swamped because of the recent interest due to GSoC 2017 acceptance there is so much to respond to and my evening is still not much longer than 1 hour. I'll have to postpone this another time.

@MarceColl
Copy link
Contributor

MarceColl commented Mar 2, 2017

@bjorn no problem I understand man. I've had to delay the mockup for another day too beacuse of university chores.

Looking forward to discussing this with you in some days.

@bjorn
Copy link
Member

bjorn commented Mar 6, 2017

So if I've understood correctly your idea is to assign a height h to a layer, and each cell of that layer can have a stack of x tiles, each tile of height h. The CellRenderer draws this stacked tiles one on top of the other essentially creating pseudo-3D using 2D tile images. The stack can grow upwards (walls), downwards (like in #1255) or both.

I didn't mean the height of a layer to be the height of each tile. What I meant was that you specify a certain maximum height (in tiles) on the tile layer (the maximum stack size), and associate a height (in pixels) with each tile, which is used when drawing the stack. We don't necessarily need the maximum stack size of course, and could instead allocate memory dynamically. I'm just a bit worried about the performance impact.

Now, the problem I see is in the tooling. Existing tools only work on the level-0 tile of the stack (2D grid = 3D grid with thickness 1). I have no idea how you could make the stamp brush to be able to edit all the layers without a lot of work by the user, I feel like it would be a pain to work with.

I think the tools would need some kind of "stack mode". By default, the stamp brush and eraser would replace the entire stack with whatever tile you're placing. But in stack mode, the stamp brush would place tiles on top of the stack, and the eraser would erase tiles from the top, for example.

I don't think the stacks work very well with terrains, or at least I don't see it being a very common combination. As you can see in the screenshot at #1255, the terrain transitions are done very differently and likely on-tile transitions would look quite strange when combined with the height variations, though it would of course be possible. My suggestion would be for the terrain brush to just modify the first layer, leaving anything stacked on top alone.

I must admit that I don't really understand why you would restrict the height map to the terrain tool. Maybe you can still do your mockup, which could help explain things.

How do we draw objects? How do we decide if they are behind or in front of a stack?

I think objects do not mix at all with this feature. They are entirely separate beasts, which is also why I think this feature needs to work within a tile layer rather than being something that works to combine multiple layers, because it would cause problems for any object layers in between.

Of course, this does mean we'll probably be looking to introduce something object-like to tile layers in the future, since they do still have their use.

@eishiya
Copy link
Contributor

eishiya commented May 3, 2022

I think that, rather than attempting to add layer height and stacks to regular tile layers, it would be better to introduce a separate Stack layer type where each cell holds a stack of tiles, with entirely different data storage. This way tools can know to be in stack mode when they're acting on a stack layer, and you never have to worry about accidentally enabling stack mode if you're using regular tile layers. It would also mean that out-of-date Tiled map parsers wouldn't mistakenly interpret their data as plain tile data, they would ignore these layers or warn about an unsupported layer type in most cases.

Stack Layers could have a Maximum Stack Height property, which would help users keep their maps manageable, and give Tiled a ceiling for allocating memory. This parameter could perhaps have an enforced maximum, so that users can't set it to some ridiculous number.
There would be a Tile Depth property, which would determine how much higher each tile in the stack is painted, in pixels.

The Stack Layer would be its own layer, so its depth would not interact with other layers in any way, not even other Stack Layers. Most maps utilising stacks would just need one Stack Layer and nothing else.

Objects need not interact with these stacks at all, but users could use custom properties to define the height of an object in the scene, and if scripts can work with stack layers, it should be doable to write a script that runs on save/export and sets those custom properties automatically based on the height of the stack at each object's location.
Should someone tackle interleaving objects and stack layers, it could be a toggleable render mode (in View, or perhaps a property on each Stack Layer), and only objects on layers between the stack layer and the next non-Object Layer would interleave with it, so there would still be a fairly well-defined ordering that plays decently well with the layered nature of Tiled.

When pasting tile data from a stack layer onto a tile layer, only the top of each stack would be pasted.

A separate layer type can mean entirely separate methods for figuring out where in the layer the cursor is, so there could be an entirely different way of choosing the cell you're painting on, perhaps one that takes into account the heights of the stacks.

Perhaps terrains could be made to work with Stack Layers too. If the Tile Layer-like methods of Stack Layers just return the tops of the stacks, if Stack Layers accept plain stamps/maps for painting, then perhaps at its most basic, Stack Layers can just be entirely transparent to Terrains, and Terrains would read from the tops of the surrounding stacks, and add their tiles to the stacks. With some extra work, Terrains could modify the existing stack-tops instead of adding. With more work still, Terrain tools could be made (optionally) depth-aware, grabbing the height of the hovered cell, and checking the other cells at that height. Placing tiles that transition not only between different terrains but also between different stack heights seems out of scope for Terrains to me, and better suited to automapping (if that can be made stack-aware) or a dedicated tool with different (or additional) mark-up.

@Chase-san
Copy link

In my #3487 I was thinking there would be a special group type so everything within it (tile wise) would be rendered on the same layer. This would resolve trying to explain it in the UI, as it would be obvious which things are being rendered as a single layer.

@bjorn
Copy link
Member

bjorn commented Mar 21, 2023

Just mentioning that this feature also came up on the Tiled forum.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature It's a feature, not a bug.
Projects
None yet
Development

No branches or pull requests

5 participants