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

Tilemap editor feature #977

Open
19 of 42 tasks
dacap opened this issue Feb 24, 2016 · 97 comments
Open
19 of 42 tasks

Tilemap editor feature #977

dacap opened this issue Feb 24, 2016 · 97 comments

Comments

@dacap
Copy link
Member

@dacap dacap commented Feb 24, 2016

UI design and main goals of the tilemap feature:

  • Everything related to tilemaps must be hidden until we create a new tilemap layer using a new Layer > New Tilemap Layer menu option (in this way we avoid bloating the UI with tilemap stuff)
  • As tilemaps will be a kind of layer, we'll be able to have several tilemaps in one sprite
  • One tilemap layer will have its own tileset, a tileset will have its own tile specs (grid size, etc.), but the tileset could be linked from an external file (with possibilities to embed the external tileset content inside the tilemap optionally)
  • Each cel in a tilemap layer will be a new kind of image where each pixels reference a tile:
    • Each pixel in the tilemap image will be a 32-bit value with some bits to reference the tile in the tileset and other bits to specify flip and rotation
  • When we create a new tilemap layer, it should behave almost exactly like a regular layer, and tiles should be handled transparently/automatically by default (so even if an user creates a new tilemap layer by mistake, she/he shouldn't see a different behavior from a default layer)
  • When the active layer is a tilemap layer, a new set of buttons should be displayed in the color bar, those buttons should allow:
    • Changing between the palette view <-> tiles view (keyboard shortcut: Shift+Tab)
    • Changing between the automatic mode of handling tiles
    • Do some special operations to tiles, which should match future operations with the palette too. E.g.
  • When a sprite contains tilemap layers, the sprite properties dialog should show a section of "tilesets":
    • We should be able to reorder tilesets
    • We should be able to add new tilesets
  • Possibility to link external tilesets
    • Persistence (.aseprite information)
    • Auto-sync tileset from external file when the original is modified
    • UI to select external tilesets
    • Special import/external/linked tileset options, e.g. from grids, from frames, from layers, from "Import Sprite Sheet", etc.
  • Drawing tile pixels with three modes: Manual (modify the tiles, don't create new tiles), Auto (create/remove existent tiles automatically), Stack (add new tiles when they are modified, keep the existent tiles unmodified)
  • Drawing tools with tiles
    • Paint with tiles (still buggy)
    • Eyedropper for tiles
    • Selecting tools with tiles
    • Fill, Stroke, and Clear commands for tiles
    • Copy and paste tiles

Special Features

Possible advanced features:

  • Flip/Rotation
  • Overlapped tiles (isometric tiles etc., hexagonal tiles, etc.)
  • Palette shifting (e.g. some bits to shift the colors of a tile in the color palette)
  • Metatiles (hierarchy of tiles, where the tiles of one tileset is another tilemap with smaller tiles)

Persistence

  • Create a new chunk in .aseprite format to save tilesets
  • Each tileset should contain specs (tile width/height, type of tiles, etc.) and source of tiles (e.g. for linked tilesets between files).
  • Save/load layer tilemaps and their cels
  • Save only differences between cels in tilemap layers
  • Save (and load?) TMX files
  • Convert grid settings into tileset specs and save then in the .aseprite file if it's possible (#688), this might enable isometric grids too (#720)

Integration

  • Check the integration with Tiled mode

Ideas, issues to review, and old ideas about the implementation

Review

UI Design

Here I'll be updating this issue to talk about the design of this feature. Some questions to solve:

  • How we create a new tilemap? (File > New > Advanced > a new tab for tilemaps appears? or we start creating the sprite sheet?)
  • Should be the tilemap a switcheable mode like "Tiled Mode"? I don't think so, we could be creating several tilemaps from the same tileset/sprite sheet. So it looks like a tilemap is just a way to say "we are going to create a map feeding tiles from these sprite sheets"

The general idea is this:

  • the color bar should be transformed into a tileset where we can pick tiles
  • the sprite editor is the tilemap editor where we can put/draw/pick(eyedropper) tiles

Internal tasks

Tasks to do (this list is not complete):

  • create a new kind of image that can reference different tiles/doc::Image on each area and with different rotation/flipping. (doc::TiledImage?)
  • create a generic iterator for any kind of image (current doc::Image, and this new tiled image)
  • different parts of code will use the doc::Image iterators (e.g. file format encoders/decoders) and other areas should use this generic iterator (e.g. sprite Editor widget).
  • get tileset from a tilemap (from this thread)

An alternative implementation would be to edit images as a regular image, and after each "tool loop", we update/sync the tilemap/tileset depending on these modifications. Pros: easier to implement (there is no new kind of image), Cons: it will use a lot more memory (and it couldn't be an option for big maps).

@dacap dacap self-assigned this Feb 24, 2016
@not-surt
Copy link

@not-surt not-surt commented Feb 25, 2016

All other image editors with tilemap editing that I know of are limited to non-overlaping rectangular tiles.
This is obviously useless for isometric, other axonometric tiles.
Ideally any solution would allow tiles to overlap on the tilemap canvas and be editable in place.
This should require an full tilemap implementation rather than just a hack on top of a regular image.

@EyeGem
Copy link

@EyeGem EyeGem commented Feb 27, 2016

2not-surt: Full tilesets and tilemaps creation support is far out of animated layered image editing scope. Don't think Aseprite should be jack-of-all-trades here, because wishes will just grow and grow. There are lot of other things possibly required from such support: clipmasks/z-masks, 2D/3D tilemaps, animated voxel/point-cloud sources for isometric tiles/sprites, objects/locations placement with parameters and objects presets archetypes hierarchy, animated scenes timelines for sprites/objects/hints, different lighting/shadows support, advanced grids (hex-grids, walls-and-columns-around-cell grids, etc.). Just too many of them. But simple and clean Super Tiling support will be just OK. Better create another editor or mode for ATnT (Advanced Tiles & Tilemaps) =)

@EyeGem
Copy link

@EyeGem EyeGem commented Feb 27, 2016

2not-surt: And you can create isometric tiles (not tilemaps) in Aseprite using hint guides layer. Frames will be different sprites (or sometimes "frames"). Layers will help create complex tiles with layered layouts. And then use this tileset in tilemap/level editors, not image editor. Simple tiles is special case specifically because they do not overlap.

@KasumiArai
Copy link

@KasumiArai KasumiArai commented Feb 27, 2016

Block tile copy is an absolute must. (That is selecting multiple and pasting multiple tile indices. Pyxel Edit still lacks this, and it's my main problem with its workflow.)

It would be cool if this paired well with issue #974, or at least had a feature found in D-pixel. It allows you to work with tiles in a palettized way. Say you have a range size of say... 4 and draw a tile using indices 4, 5, 6 and 7. You place a duplicate of this tile to the right. You then draw on the left one using color 8. It remaps index 4 to 8, 5 to 9, 6 to 10 and 7 to 11, but only for the left tile. Meanwhile the stroke you made is still made on the identical right tile using color 4. So there's one tile in the tileset, but it can be displayed with two different palettes. Useful for retro stuff. A range equal to the current palette size would end up being "normal" painting behavior.

You can see a gif here, it's probably better than the text explanation:
d-pixel

What D-Pixel lacks that Pyxel Edit has is seeing the stroke you're making across all tiles the stroke has touched. D-Pixel lets you see the stroke, but if you make say... one continuous stroke across two of the same tile, both tiles will look different until you release click and it applies both sets of pixels that overlapped each tile in the map to the actual tile. You can see this above when a line is drawn on the white background. Ideally all of those white tiles would update during the stroke itself so it's never possible for two of the same tile to look different.

This is also a must. The palette stuff would be cool, but is not a must to me.

@EyeGem
Copy link

@EyeGem EyeGem commented Feb 27, 2016

About blocks for Super Tiling I proposed at http://steamcommunity.com/app/431730/discussions/1/405692224243720164/

Copying blocks of tiles could be done by selecting tiles in Tileset window with Ctrl+click (they should be organized there for this, like 2x3 tiles for tree and etc.) or with Tiiling Pen on image layer with Ctrl+Alt+clicks, and then Ctrl+C to copy all selected tiles as image. Yes just an image. Then Ctrl+V to insert it. If current tool is Tiling Pen then Ctrl+V should insert it aligned to grid automatically and then movable with auto-aligning.

Also Ctrl+drag (Tileset window) and Ctrl+Alt+drag (image layer) could select/deselect tiles in rectangular block,yes.

@EyeGem
Copy link

@EyeGem EyeGem commented Feb 27, 2016

2dacap: about "create a new kind of image that can reference different tiles/doc::Image on each area and with different rotation/flipping. (doc::TiledImage?)"

Just to clarify: for Super Tiling you don't need special kind of image. Only special kind of operations. It's perfectly possible to allow select existing files in Tileset window (and layer inside file for .ase files). And make combo list of such files with (+) and (X) buttons somewhere to add new and remove unwanted. And auto-select file and layer from this combo list then switching between layers of main image (restoring lastly selected file/layer for this layer).

@EyeGem
Copy link

@EyeGem EyeGem commented Feb 27, 2016

For any tile WxH it's possible to calculate hash value using, for example, this function:

ub4 one_at_a_time(char *key, ub4 len)
{
ub4 hash, i;
for (hash=0, i=0; i < len; ++i)
{
hash += key[i];
hash += (hash << 10);
hash ^= (hash >> 6);
}
hash += (hash << 3);
hash ^= (hash >> 11);
hash += (hash << 15);
return (hash & mask);
}

From: http://www.burtleburtle.net/bob/hash/doobs.html

It's also possible to calculate hash values for flipped/rotated versions of same tile, because hash function is order-dependent.

These hash values could be used to create hashtable lookup of N lists, N = 2*max_tiles. Simply put tile index (and flip/rotate flags) into list with index = hash_value % N. Then when you need to find matching tile simply calculate hash value for your tile and lookup into same list and compare tile pixels only against those tiles in list (with flipped/rotated flags affecting comparison), not against all tiles of tileset.

max_tiles could be estimated as = ( tileset_width / tile_width + 1 ) * ( tileset_height / tile_height + 1 )

@EyeGem
Copy link

@EyeGem EyeGem commented Feb 27, 2016

One worst case scenario estimation:

  1. image 8192x8192 designed with tiles grid 16x16, thus 512x512 tiles, 256K tiles total
  2. tileset 128x1024 with same tile size 16x16, i.e. 8x64 tiles = 512 tiles
  3. all image tiles same (for example, black), thus same hash value
  4. all tileset tiles same (for example, black), thus same hash value
  5. hash function for 16x16 = 256 bytes ~ max. 3000 processor ticks (for Indexed mode)
  6. let us have CPU 1Ghz
  7. 512 * 3000 * 8 ~ 12M ticks to calculate hash values for tileset (4 rotates with flips) ~ around 10ms
  8. 256K * 3000 = 768M ticks to calculate hash values for whole image ~ less than 1 sec
  9. 512 tiles in list for same hash value, compare every tile 512 times, 256K * 512 * ~1000(memcmp) = ~128G ticks ~ 100 sec ... hmm, slow =)
  10. to optimize don't add to hashtable same tiles, extra 511 comparisons, 511 * ~1000 ~ 512K ~ 0.5ms
  11. thus only 1 tile in list, thus 256K * ~1000 = 256M ~ 200ms

And this 1.5 sec operation is rare operation only for special second click in Tileset window to select all tile instances in main image (including flipped/rotated) and edit them all. All other operations do not operate over full image. And this was really bad case scenario where hashtable failed because of all tiles were the same.

@AkashaRepo
Copy link

@AkashaRepo AkashaRepo commented Apr 18, 2016

Right now I have a workflow where I make tiles in Aesprite and arrange them in Tiled. Being able to do all this in Aesprite would be <3

@astraldata
Copy link

@astraldata astraldata commented Jul 12, 2016

+9000 to KasumiArai -- that sort of tilemap feature would be amazing in Asesprite! D:

@HawkenKing
Copy link

@HawkenKing HawkenKing commented Jan 29, 2017

current workflow is aseprite / photoshop, then Tiled or TileTool2D, or NES ScreenTool (for colours)

Would be nice if NES style per 16x16 tile colouring was implemented but that might be asking for too much.

@dacap dacap added this to the v1.6 milestone Jun 9, 2017
@astraldata
Copy link

@astraldata astraldata commented Jan 4, 2018

It's terrible -- this feature is due by 2021 ... and I've needed at least a preliminary version three years ago... :'(

@dacap
Copy link
Member Author

@dacap dacap commented Jan 4, 2018

Actually I'm planning to prioritize this one, it might be available sooner than you expect.

@oceanhahn
Copy link

@oceanhahn oceanhahn commented Jan 4, 2018

Woah, that'd be three years ahead of schedule! ;)

@dacap dacap removed this from the v1.6 milestone Jan 4, 2018
@dacap dacap added this to the v1.3 milestone Jan 4, 2018
@astraldata
Copy link

@astraldata astraldata commented Jan 6, 2018

Indeed lol!

I currently don't have PyxelEdit, and, personally, I don't care for its pixel workflow in general, but the one feature it has on Aseprite is one I can't get away from -- and that's a tilemap editor.

I don't care about laying out a level in Aseprite -- I can do that in a game engine (or Tiled. )

Everything else I want to do with tiles needs a great pixel editor alongside it.

For that purpose -- I only want/need a few things:

  1. First, a list of editable tile indexes of a specific size that can be selected from and arranged like the color palette already can (in fact, a simple copy/paste of much of the palette arrangement code would do just fine)
  2. Second, a (potentially disposable) "swathe" space (similar to the "preview" window) where I can draw up a preview swathe of tiles (with chosen repetitions / mirrors / flips / rotations) of individual tile indexes
  3. Next, the swathe would respond, in realtime, to the strokes (and the color changes) you lay out in the main window. The main window itself would display a user-selected number of nearby swathe tiles in the X/Y direction and allow those tiles to be individually and simultaneously edited in the main window, right alongside the currently-selected tile from the swathe.

To clarify #3 and the imagined workflow in general -- just as the "Tiled x" and "Tiled y" settings allow repetitions to be displayed and edited in the main window area -- that's essentially what editing in the main window would do with a tile index selected, except with nearby tiles to the one that the user has chosen in the swathe. The swathe will always have 1 index at least, and if you select an index in the list of tiles, it can replace that index in the swathe automatically -- otherwise, selection would usually be done in the swathe palette window where both placement (and selection!) occurs. You would, of course, have a list of tile indexes that would, essentially, just act like the color picker for the most part. Only the first index is considered the origin tile (or perhaps the origin tile /group/) of course.

I do hope I've described everything here well enough to make it sensible.

From what I can tell from the editor -- the design outlined above will allow much of the code to be copy-pasted from the rest of the editor. -- Not all can be copy/pasted, but enough to have a preliminary display of tiles from a palette in a new preview window at least! -- Which is why this feature is so critical! It's the one thing Graphics Gale doesn't have and the one thing all other -lesser- (imo) pixel editors seem to have -- except with a poor implementation. Aseprite is up there with Gale in terms of user-friendliness, and I just wish it had this one feature to make it a Gale-killer for everything Gale lacks.

@haxpor
Copy link

@haxpor haxpor commented Jan 6, 2018

Interesting feature. Although I'm natural on this but I do any pixel related stuff with aseprite so if this feature is there, it would be a plus.

Just want to chime in here as Tiled just released version 1.1 that included interesting concept of Wang Tiles. Their interesting discussion is here. In short, as from my understanding, it can generate tilesets from a few tiles with pre-defined color for each corner, or used to map a proper and correct tile within tilesets while user's drawing road, or terrain map. Sort of those areas. Might be an idea further. Just FYI guys. Anyway, cheers for tilemap feature.

@astraldata
Copy link

@astraldata astraldata commented Jan 7, 2018

Thanks for sharing that, haxpor. -- In many cases (at least with pixel art), simple transparency overlays can handle the same problem Wang Tiles seeks to solve (using an uncecessarily-specialized algorithm).

@dacap 👍 :

If Aseprite did anything to help with what Wang Tiles tries to help with, it could be solved in a more useful and general-purpose way:

For example, it would be amazing if it would let you auto-merge individual layer-pair combinations sequentially. For example, you could specify that layers 1-4 would be the transparent overlays, and layers 5-22 would be the various combinations that 1-4 would overlay (i.e. 1 overlays 5, then 2 overlays 5, etc.., next 1 overlays 6, then 2 overlays 6... yada yada... you get the point.)

And for a slightly more complex (but infinitely more useful) alternative implementation, it would be nice to specify groups and sort orders of multiple overlays before executing the overlay+merge function. The idea came from when I was more recently playing with and it made me think of Aseprite ... It would be nice if the auto-combine feature I proposed above based on haxpor's suggestion could do more advanced transparent overlay combining. The idea behind Charas is to pull from a ton of layers of heads/hair/body-styles/accessories/etc. and letting a user combine them into a sprite atlas. I could see it being highly useful to do something like this for character animation too instead of a hard-coded thing like Charas has (perhaps by simply leveraging animation frames and layers simultaneously) to make it easier for an artist to generate automatic overlay + merges on a large variety of sprite combinations and animations. Even if we had to do this on a per-file basis, it would still be so much greater than the manual merging that is required in every other tool...

Just my two-cents! -- Maybe I'm onto something here though?

@dacap
Copy link
Member Author

@dacap dacap commented Feb 6, 2019

Just in case I'm already working on this one:

https://twitter.com/aseprite/status/1092884555126763521

The basic idea is that we should be able to:

  1. Create a new "tilemap layer" using a new Layer > Add Tilemap Layer menu option
  2. When the active layer is a "tilemap layer", this will show some extra controls in the color bar ("Tiles" and "Auto" buttons at the moment, but that might change in the future)
  3. Then we can draw as in a regular layer, and tiles will be created automatically (when "Auto" button pressed)
  4. Shift+Tab will switch between color palette <-> tiles
  5. Clicking a tile will enable us to put tiles in the canvas (right-click might pick tiles from the canvas, or just act like the right-click default behavior, just like FG/BG colors, we could have a FG/BG tile, or FG/right-click behavior)
  6. When the "Auto" mode is unpressed, we can edit tiles manually (no new tiles are generated automatically)
  7. We should be able to reference different tilesets from each tilemap layer, anyway each tilemap layer will have one layer-specific tileset to create those automatic tiles when the "Auto" mode is enabled.

In general terms, this new tilemap layer should work as the regular layer by default. And the special modes should start giving us more options (like putting tiles, modifying all instances of the same tiles, etc.).

@EyeGem
Copy link

@EyeGem EyeGem commented Feb 6, 2019

... anyway each tilemap layer will have one layer-specific tileset to create those automatic tiles when the "Auto" mode is enabled

Do you mean old tiles not removed from this layer-specific tileset when they entirely removed from Tilemap Layer itself? And editor will keep order of tileset tiles until moved/edited by user just like colors of palette? Hmm... and we can load tiles to tileset from external tileset file (auto split by tiles size) once and then use them to draw map and later export tilemaps with exact tiles order saved? Sounds interesting. Hope tile width and height are Tilemap Layer properties then and could be any, for example 20x25 --- there're cases where art like this looks best. And image right and bottom not-full-tile-size edges should be ignored maybe. And we could mix different tiled layers, like 8x8 for physics, 16x16 for platforms and 32x32 for backgrounds. Also if add exporting of animated tilemaps (tiles indices) and maybe even with encode-only-changes-different-from-prev-frame mode it will be something like animated cutscene packing and partial image animations used in good old games.

@dacap
Copy link
Member Author

@dacap dacap commented Feb 6, 2019

Hi @EyeGem!

Do you mean old tiles not removed from this layer-specific tileset when they entirely removed from Tilemap Layer itself?

There should be two possibilities: 1) Keep tiles intact and just add new tiles (+ offer a button to clear unused tiles automatically), 2) Clear unused tiles automatically too.

And editor will keep order of tileset tiles until moved/edited by user just like colors of palette?

The user will be able to disable the "Auto" mode for the layer tileset (a tilemap layer will have only one "auto" tileset that can be enabled/disabled, any other referenced tileset will not be automatically handled = be in this "auto" mode).

we can load tiles to tileset from external tileset file (auto split by tiles size) once and then use them to draw map and later export tilemaps with exact tiles order saved?

Yes, the final version of the tilemap editor should give us the chance to reference several tilesets (from external .aseprite files too) and use tiles from those tilesets in one or several layer tilemaps.

Hope tile width and height are Tilemap Layer properties then and could be any

Yes, the only limitation will be that the "tileset specs" (tile width/height) should match with the layer tilemap specs. Anyway you will be able to have several layer tilemaps in the same files with different specs.

About animated tilemaps: each frame in a layer tilemap will be a different tilemaps (so you could reference the same tilesets/tiles on each frame or vary only one tile, etc.). I still have to think about the persistence details and memory usage implications for huge tilemaps, but we should save tilemaps differences only for animations.

If I find something really complicated in the process, I'll try to push things forward for future versions and have a more basic version in the first v1.3-beta.

@EyeGem
Copy link

@EyeGem EyeGem commented Feb 6, 2019

the final version of the tilemap editor should give us the chance to reference several tilesets (from external .aseprite files too) and use tiles from those tilesets in one or several layer tilemaps.

To keep things simple it could be really preferable to just have one single tileset inside each Tilemap Layer data and give user tools to copy images from external tilesets into this single tileset, so that exporting tilemap may produce simple indexes of tiles and those indices not broken even by "Auto clear unused tiles" option or "Now clear unused tiles" button, so tileset should really have used/not used bit flag for each tile and allow free moving of tiles inside tileset, it's often really useful to arrange tiles in tileset in specific manner, so those unused-flagged tiles around arranged tiles will be helpful.

@LeonardoCunhaGitHub
Copy link

@LeonardoCunhaGitHub LeonardoCunhaGitHub commented Sep 30, 2020

@dacap Thank you for your hard work towards this feature! Much appreciated!

@awesomez
Copy link

@awesomez awesomez commented Oct 1, 2020

https://www.youtube.com/watch?v=ZWQ0591PAxM

@dacap -- This is an interesting video to look at for the meta-tiles concept I explained above! D:

@darthdeus
Copy link

@darthdeus darthdeus commented Oct 11, 2020

I assume this is not being built on the github repo? Looking at the tweet showing the tilemap from almost two years ago (https://twitter.com/aseprite/status/1092884555126763521) it already seems better than what PyxelEdit has? I'd be totally up for beta testing it as well.

@haimat
Copy link

@haimat haimat commented Jan 13, 2021

Hey guys, this would be a really great feature and I am very much looking forward to it.
Is there any estimation when this tile set support might be released?

@nights321
Copy link

@nights321 nights321 commented Jan 13, 2021

@erayzesen
Copy link

@erayzesen erayzesen commented Jan 28, 2021

Hi all. What happened? I'm still waiting this feature : (

@seattleowl
Copy link

@seattleowl seattleowl commented Feb 15, 2021

When is this coming? I would love to know if it will have autotile support.

@Gnumaru
Copy link

@Gnumaru Gnumaru commented Mar 24, 2021

For any future googler eager for updates regarding the upcoming tilemap editor feature, check out Adam Cyounis' quick look at the tilemap features in a closed beta build of Aseprite 1.3

https://www.youtube.com/watch?v=TL_JZIuydas

@not-surt
Copy link

@not-surt not-surt commented Apr 12, 2021

Stumbled on something that I posted on to the Pro Motion forums ages ago and figure it might be useful in regards to my previous comments:

I’d love to see support for overlapping tile geometries too, but it does pose a bit of a problem for the editing interface.
You could no longer just freely paint as a screen pixel could have multiple tiles overlapping it.
Need some way to resolve which tile an edit applies to.
Easiest way I can think of would be to mark a specific tile as the current editing target, then limit all edits to that tile, though not the nicest workflow.

For me the ideal solution for supporting non-rectangular tile grids would be:

  • Rectangular tile bounds
  • Tile grid step vectors (one 2D vector per grid axis, ideally three so support 3D tile maps such as UFO: Enemy Unknown, Transport Tycoon, Ultima VII, etc.)
  • Tile origin offset relative to tile bounds
  • Tile centroid offset for mouse picking (default to bounds centroid, needs to be manual for uneven bounds fringe, eg. iso with more overlap above)
  • Axis draw order and direction (so tiles overlap as desired)
  • Quadrilateral grids can use axis step vectors for grid line drawing, hexagonal requires a special case though
  • Could have presets/wizard to hide the complexity from less technical users
  • Would then support any axonometric projection of quadrilateral and hexagonal grids.

image

@EyeGem
Copy link

@EyeGem EyeGem commented Apr 12, 2021

I’d love to see support for overlapping tile geometries too, but it does pose a bit of a problem for the editing interface.
You could no longer just freely paint as a screen pixel could have multiple tiles overlapping it.
Need some way to resolve which tile an edit applies to.
Easiest way I can think of would be to mark a specific tile as the current editing target, then limit all edits to that tile, though not the nicest workflow.

Tile bounds should be separated from vectors. This will eliminate any need for third vector and give way to draw tile content outside of basic shape. Also no special hexagonal case will be reqiured, except for centroid position, but it could be setting too. So parameters of tiling will be: IntVec2 tiling_origin, tile_width, tile_height, IntVec2 tile_origin, IntVec2 tile_center, IntVec2 tiling_ustep, IntVec2 tiling_vstep. Also tiles resize relative to tile_origin should be available, just like canvas resize.

And yes, ustep and vstep vectors could be directed up and left too for alternate sorting orders. Or with additional tiling parameter like: tiling_order (4 basic variants and maybe even more like sorting around some center for fake-perspective tiles).

And basic tiling is just tile_w=grid_w, tile_h=grid_h, tile_origin=(0,0), tile_center(tile_w/2,tile_h/2), tiling_ustep=(tile_w,0), tiling_vstep=(0,tile_h).

As for editing of specific tiles it could be separate mode of "only selected tile editing" which hide (or draws under and faded) neightbour tiles. And cursor keys could switch selected tile to neightbour tile in this mode for happy editing.

@dacap
Copy link
Member Author

@dacap dacap commented Apr 12, 2021

About non-rectangular tiles: At the very beginning, when I started implementing this feature, there were plans for isometric/etc. tiles with some parameters:

    gfx::Size tileSize() const { return m_tileSize; }
    gfx::Point origin() const { return m_origin; }
    gfx::Point tileCenter() const { return m_tileCenter; }
    gfx::Point tileOffset() const { return m_tileOffset; }
    gfx::Point oddRowOffset() const { return m_oddRowOffset; }
    gfx::Point oddColOffset() const { return m_oddColOffset; }

where

// Converts a tile position into a canvas position
gfx::Point Grid::tileToCanvas(const gfx::Point& tile) const
{
  gfx::Point result;
  result.x = tile.x * m_tileOffset.x + m_origin.x;
  result.y = tile.y * m_tileOffset.y + m_origin.y;
  if (tile.y & 1) // Odd row
    result += m_oddRowOffset;
  if (tile.x & 1) // Odd column
    result += m_oddColOffset;
  return result;
}

This was left aside to support only rectangular tiles in the first version (v1.3-beta1) but it will be reviewed in future versions.

@EyeGem
Copy link

@EyeGem EyeGem commented Apr 13, 2021

What proposed is like this:

 gfx::Point tilingOrigin() const { return m_tilingOrigin; }
 gfx::Size  tileSize() const { return m_tileSize; }
 gfx::Point tileBase() const { return m_tileBase; }
 gfx::Point tileCenter() const { return m_tileCenter; }
 gfx::Point tilingUStep() const { return m_tilingUStep; }
 gfx::Point tilingVStep() const { return m_tilingVStep; }
 ETileOrder tilingOrder() const { return m_tilingOrder; }
 gfx::Point tilingOrderPoint() const { return m_tilingOrderPoint; }
    
gfx::Point Grid::tileToCanvas( const gfx::Point& tile ) const
{
  gfx::Point result;
  result.x = tile.x * m_tilingUStep.x + tile.y * m_tilingVStep.x - m_tileBase.x + m_tilingOrigin.x;
  result.y = tile.x * m_tilingUStep.y + tile.y * m_tilingVStep.y - m_tileBase.y + m_tilingOrigin.y;
  return result;
}

This also works for hexagonal tiles, because they're just brickwall placed tiles and, for example, VStep could be shifted right to form brickwall tiling pattern case shown in excellent image by not-surt.

@dacap
Copy link
Member Author

@dacap dacap commented Apr 14, 2021

We'll see what we do in the future for this kind of tiles. Meanwhile I think the first v1.3 version will be good enough to experiment with different kind of files. Check this: https://twitter.com/davidcapello/status/1382333026718339079

@EyeGem
Copy link

@EyeGem EyeGem commented Apr 14, 2021

Ah, yes, workarounds are possible, but not so handy. At least 4 tilemap layers required to emulate normal isometric tiles with some height overlapping.

And about those fit-in-rect hex/iso tilemaps (to avoid waste of map cells) it is possible to add m_tilingDelta and m_tilingDeltaRows parameters (m_tilingDelta col delta for every m_tilingDeltaRows rows) and calculate tile x like this:

const int tile_x = tile.x + m_tilingDelta * (tile.y / m_tilingDeltaRows);
result.x = tile_x * m_tilingUStep.x + tile.y * m_tilingVStep.x - m_tileBase.x + m_tilingOrigin.x;
result.y = tile_x * m_tilingUStep.y + tile.y * m_tilingVStep.y - m_tileBase.y + m_tilingOrigin.y;

By default m_tilingDelta = 0 and m_tilingDeltaRows = 1 (never 0). Divison should be integer / integer.

For hexagonals m_tilingDelta = -1 and m_tilingDeltaRows = 2. Same for diamond isometic tiles (same brickwall case with cols and rows along diamond horiz/vert diagonals). And you can easily swap tilingUStep and tilingVStep to reorder rows to cols and cols to rows.

This will also complement from 2 tiling order options (First X then Y) and (First Y then X) and tiles ordering center point (what located left of it drawn left-to-right, what located right of it drawn right-to-left, what located at its col drawn last, same for up/down). Then for default tilemap center point would be at bottom right (100%,100%) corner and together with order (First Y then X) it will enforce ordering by rows (up-to-down) of cols (left-to-right) i.e. first row, then second row, etc.

@LeonardoCunhaGitHub
Copy link

@LeonardoCunhaGitHub LeonardoCunhaGitHub commented May 21, 2021

@dacap I just wanted to take the time to come back here and THANK YOU for developing the tilemap feature.
I know it was a tough road but you did it!
Thanks a lot!

@Adrthegamedev
Copy link

@Adrthegamedev Adrthegamedev commented May 27, 2021

Is it planned to implement padding in tilemaps? a lot of tilesets have padding of at least 1 pixel, and without padding it makes the whole tileset offcentered.

@bsergent
Copy link

@bsergent bsergent commented Jun 2, 2021

Are there any plans to have any sublayers within a single tilemap layer? Before the beta, I had a debug layer on top of my tilesheet to more clearly show what connected to what, but I don't see any way to do that with these new tile layers in the beta other than creating two tile layers and manually syncing them.

tilemap_sublayers

I'm sure it would also be a convenient feature for more detailed tilemaps (like maybe for animating the torches in the above image).

Thanks for this feature regardless. It's amazing!

@EyeGem
Copy link

@EyeGem EyeGem commented Jun 2, 2021

Are there any plans to have any sublayers within a single tilemap layer?

Hmm. Could you describe how it should work? Because it sounds more like advanced map editor feature of rich tile elements rather than simple tiles.

Maybe switching tilesets during work could do the job (after external tilesets will be implemented)? Or do you want a special feature for tilesets to have editing-only info graphics and maybe even user data? Or if your debug data could be different for same tiles it should be separate layer one way or another.

@bsergent
Copy link

@bsergent bsergent commented Jun 2, 2021

Hmm. Could you describe how it should work? Because it sounds more like advanced map editor feature of rich tile elements rather than simple tiles.

My thought was to just have what essentially behaves like a Layer Group but with the functionality of the new Tilemap layers. Currently, from what I can see at least, you lose the ability to split up work into several layers when you switch over to a Tilemap layer. As an example from the image I posted, see the puddle of water tile; I might have the brown background, then the lighter brown rocks on another layer, then the puddle on the topmost layer. That way I could easily modify the water without redrawing the rocks under it each time I make a change. The same would also help for the ladder, torch, and spider web tiles; just allow me to not have to recreate what was below when I make a change. Of course I can do that if necessary, but I like using layers to split the different "parts" of the tile apart.

As for how it would work with the new tilemap features, I would have the automatic updating/adding/removing of tiles respect all the sublayers regardless of visibility. It would flatten them before comparison so that you're not left with different tilesets depending on what sublayers are visible. Still one tilemap and no multiple layers of tiles (that's already supported by just having multiple tilemap layers). The only difference would be in the drawing of the individual tiles.

Maybe switching tilesets during work could do the job (after external tilesets will be implemented)? Or do you want a special feature for tilesets to have editing-only info graphics and maybe even user data? Or if your debug data could be different for same tiles it should be separate layer one way or another.

Yeah, I imagine switching tilesets would be fine for the whole "draw some debug edges" concept. As for the special features you mentioned, those would be neat but not quite what I'm asking about (or attempting to ask about). Just having a layer of lines that I can toggle between visible and invisible is all I'm looking for, no actual information associated with those lines. I use them to just make sure I have all the different variations of edges I need and that I'm testing all the different combinations on a map.

Maybe it will make more sense to show you the kind of layers I have set up in my tileset before using the beta:

image

@EyeGem
Copy link

@EyeGem EyeGem commented Jun 3, 2021

You can write Lua script to automatically update Debug Lines layer and bind this script to hot key combination like Space+U (for example).

Yeah, I imagine switching tilesets would be fine for the whole "draw some debug edges" concept.

I suggest swithing tilesets is very important feature to create multiple tilesets for same tilemap, like for seasons (summer/autumn/winter/spring) or some other kind of progression (meadows/wasteland/etc). I hope that when external tilesets will be implemented it will be possible to switch tileset keeping same indexes.

@SwitchZ
Copy link

@SwitchZ SwitchZ commented Jun 10, 2021

I'm really looking forward to the flip/rotation tile feature!

@Manukineko
Copy link

@Manukineko Manukineko commented Jun 24, 2021

Does exporting tileset a planned feature ?
I mean like exporting an animation as a sprite sheet but where each frame is a tile. With an option to define the width and height of the tileset.

I know I could just place tiles and organise them as I wish in the canvas and then export the image, but in my opinion, it breaks the workflow when using the canvas to create those tiles and i's a bit of a hassle.

I also think, the tile picker should allow to be set a fixed width so when you stretch the window, tiles are still organised. For exemple, if you organised your tree tiles to actually show the whole tree, streching the window will put the tile in single file and it become hardly readable.
(I think the same for the color picker, but it's another subject :D)

@dmitsuki
Copy link

@dmitsuki dmitsuki commented Aug 13, 2021

Is it in planned features to have certain tools constrain to currently active tile? For example, checkbox that makes paintbucket treat the active tile as a selection so it does not leave those constraints?

@EyeGem
Copy link

@EyeGem EyeGem commented Aug 14, 2021

Is it in planned features to have certain tools constrain to currently active tile? For example, checkbox that makes paintbucket treat the active tile as a selection so it does not leave those constraints?

You can press Ctrl+" to enable grid for tilemap layer and Paint bucket will treat grid tile as a constraint. Or you can double click anywhere to select grid tile and then use Paint bucket.

dacap added a commit that referenced this issue Aug 24, 2021
This is the first commit with a simple tilemap editor. Still buggy but
functional in several ways. Several changes were made:

* NewLayer command can receive a tilemap=true to create a new tilemap
  layer
* New ToggleTilesMode command added to switch between the palette and
  the tileset in the ColorBar (the ColorBar was expanded to show
  colors or tilesets with a generic AbstractPaletteViewAdapter)
* All commands to create new layers were moved to Layer >
  New... submenu
* There are a new tileset chunk to save tilesets in .aseprite files,
  and a new kind of cels to save tilemaps
* Added doc::LayerTilemap, doc::Tileset, etc. and several other types
  to handle tilesets/tilemaps in the doc layer.
* Added doc::Grid class with grid specifications that indicates how a
  tilemap <-> tileset must be drawn
* Added and expanded cel operations to work with tilemaps and
  conversions between regular LayerImage cels <-> LayerTilemap cels
  (e.g. copy cels in the timeline between layer types)
@dacap dacap removed this from the v1.3 milestone Sep 3, 2021
@dacap dacap added this to the v1.3-beta8 milestone Sep 3, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet