Skip to content

Conversation

BSChad
Copy link

@BSChad BSChad commented Dec 7, 2023

This adds support for hexagonal grids in the GridMap node with the same offset and layout semantics as TileMap.

This is a rebase of the latest master for #59842. There was minimal editing outside of updating to the proper 4.2+ API, and using the new naming convention introduced in master. (IE: world_to_map and map_to_world to local_to_map and map_to_local).

Performed functional testing with a hex MeshLibrary.

Closes godotengine/godot-proposals#4337. Based on discussion, it wouldn't be too hard to remove the Layout and Offset Axis options, though they seem to work just fine.

@BSChad BSChad force-pushed the feat-grid-map-hexagonal-cells branch from 01327a1 to 387e409 Compare December 7, 2023 16:39
@BSChad
Copy link
Author

BSChad commented Dec 7, 2023

Fixed argument prefix issues and added some out of range checks for properties. I had, apparently, forgotten to force push the changes to the function names to change world_to_map to local_to_map. Pushed those as well.

@BSChad BSChad force-pushed the feat-grid-map-hexagonal-cells branch from 387e409 to a1212f1 Compare December 7, 2023 16:47
@BSChad
Copy link
Author

BSChad commented Dec 7, 2023

Fixed a case of a function modifying the argument in draw_plane, instead storing calculated axis' in a new local.

@BSChad BSChad force-pushed the feat-grid-map-hexagonal-cells branch 2 times, most recently from 97eaa93 to 09eadc4 Compare December 7, 2023 18:48
@AThousandShips
Copy link
Member

You have more whitespace issues, you can run clang locally to fix these, see here

Copy link
Member

@AThousandShips AThousandShips left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some minor documentation suggestions, you also need to add the new MAX values

@BSChad BSChad force-pushed the feat-grid-map-hexagonal-cells branch from 09eadc4 to b054440 Compare December 7, 2023 19:12
@BSChad
Copy link
Author

BSChad commented Dec 7, 2023

I was looking for the clang-format doc! Saw it once and then couldn't find it again, thanks @AThousandShips. Ran clang-format on the four files and added documentation.

@BSChad BSChad force-pushed the feat-grid-map-hexagonal-cells branch from b054440 to fbd47e5 Compare December 7, 2023 19:18
@berkeleynerd

This comment was marked as off-topic.

@AThousandShips
Copy link
Member

@berkeleynerd Please don't bump without contributing significant new information. Use the 👍 reaction button on the first post instead.

@gulagkulak
Copy link

I'm really looking forward to this feature. Any chance of getting it merged?

@BSChad
Copy link
Author

BSChad commented Jan 19, 2024

I'm really looking forward to this feature. Any chance of getting it merged?

I think we're just waiting for a review (perhaps another rebase) and then enough people to show that this is a use-case they want to use in their shipping game!

I plan to release my game on a custom build of the engine because I need this feature. Would love to join back up with a major version on trunk if it gets merged!

@BSChad BSChad force-pushed the feat-grid-map-hexagonal-cells branch from fbd47e5 to 7a42524 Compare February 12, 2024 14:27
AThousandShips
AThousandShips previously approved these changes Feb 12, 2024
Copy link
Member

@AThousandShips AThousandShips left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code looks good otherwise AFAICT, I'm neither for or against adding this feature though

@nikoladigi
Copy link

nikoladigi commented Feb 21, 2024

I am waiting for this, for my board game project! Currently developing logic in 2d tilemap, but want it to be in 3D. Great Work!

I have build it, but I have noticed a small issue, that hex tiles are not scaled properly
Screenshot 2024-02-21 at 13 43 25

It can be fixed, by setting z size to 1.1 in editor.
There are plenty of use cases and potential games that can be made with this feature.

edit:
@BSChad One suggestion to consider in order for this to be "proper" hex implementation is to add an option to chose between "Flat-Topped" and Pointy-Topped Hex

@BSChad
Copy link
Author

BSChad commented Mar 8, 2024

I am waiting for this, for my board game project! Currently developing logic in 2d tilemap, but want it to be in 3D. Great Work!

I have build it, but I have noticed a small issue, that hex tiles are not scaled properly Screenshot 2024-02-21 at 13 43 25

It can be fixed, by setting z size to 1.1 in editor. There are plenty of use cases and potential games that can be made with this feature.

Interesting. I'll have to recheck the original math here from octetdev. Hopefully something simple.

edit: @BSChad One suggestion to consider in order for this to be "proper" hex implementation is to add an option to chose between "Flat-Topped" and Pointy-Topped Hex

Isn't that what the Offset Axis is? You can choose between Horizontal and Vertical.

@IkutiDev
Copy link

Looks great! Would love it to be merged in not too distant future.

But I have found 1 possible bug. When changing cell size in gridmap from 1:1:1, placing the tiles with the mouse has issues. It's like there is an offset and the place where the tile is placed is in another tile.

I have checked this on 4.2.1 stable and everything works correctly there when changing size to 2:1:2 or 3:1:3. This issue also happens on this branch no matter if shape is hexagon or square, so it would cause the issue to happen to the old grid maps as well.

caspervonb and others added 4 commits September 17, 2024 16:31
This adds support for hexagonal grids in the `GridMap` node with the
same offset and layout semantics as `TileMap`.
`GridMap` for square tiles needed to support 24 different orientations.
When hexagonal tile support was added, the hex tiles were being rotated
as they were cubes, 90 degrees on whichever axis.  This does not work
for hexagonal tiles.

Hex cell rotation is 60 degrees around the y-axis for 6 possible
orientations, then 180 degrees around the x-axis or z-axis (flipping the
tile over).  Any other rotation around x/z would cause a hex tile to
clip any neighboring cells. This results in 12 possible orientations for
hex cells in a GridMap.

In this commit, I added the hex-specific orientations to the GridMap,
along with the 60/180 degree rotations in the GridMap editor plugin.

In addition, I added `Math_SQRT3` as it is used within the hex
orientation.

GridMap: use axial coordinate system for hex cells
The offset-based indexing approach offered many options for mapping
points into map indexes, but the current code had problems correctly
mapping various regions of a cell consistently
(godotengine#85890 (comment)).
Looking at the layout code, there were a lot of options with various
mathematical transforms for each one; verifying where the issue was, and
if it affected the other layouts was challenging.

There is also a comment at the top of the PR (godotengine#85890), and in the
discussion for the previous PR (godotengine#59842) about reducing the complexity of
this PR by removing the mixture of cell layout and orientation options.
That seemed like the best approach.

In this commit, I remove the existing layout & orientation options and
replace them with a single coordinate system (axial coordinates
described in
https://www.redblobgames.com/grids/hexagons/#coordinates-axial), and a
single cell orientation (pointy, previously the vertical orientation).

In addition I added tests for `GridMap::local_to_map()` and
`GridMap::map_to_local()` to verify we can correctly identify the edges
of the cell.

With this change we loose the ability to have irregularly shaped hexagon
cells where not all sides are the same length.  This is a side effect of
the current implementation of the algorithm to map between axial and 3d
coordinates.  I don't think this will be a big problem as most hex-based
3d games are using regular hexagons.

GridMap: support Center-y for hex cells

GridMapEditor: fix floorgrid offset issue

Currently if you exit editing a GridMap on floor != 0, when you return
to the GridMap the floor grid will be redrawn offset from the cusor.  So
the cursor is at floor 0, but the grid is drawn for floor -1.

The cause of this is `_draw_floor_grid()` takes into account the current
floor level when creating the floor grid.  The problem is that the grid
should be created at floor = 0, as it is offset by the floor number when
displayed.

This commit I removed the floor number argument from
`_draw_floor_grid()`.  As a result the floor grid is generated with
coordinates for floor == 0, and is correctly offset now.

HexGridEditor: fix for x-plane editing hex cells

With the conversion to axial coordinates for hex cells, editing cells
along the x-plane caused cells to be drawn in the wrong place.  It
turned out this was because `GridMapEditor::do_input_action()` assumed
it could modify the floor value directly after calling
`GridMap::local_to_map()`.  This looks like it was a workaround for
floating point errors that occur when raycasting against the picking
plane.

This causes a problem with hex cells as the axial coordinate system
means more math is required to set the x value.

In this commit I remove the code that modifies the floor/plane value for
the cell, and instead move the raypicking plane into the middle of the
cell plane. This will eliminate the majority of raypicking errors that
result from being directly on the edge of the cell.

GridMapEditor: cell selection for hex shaped cells

* GridMap: Add `local_region_to_map()` to get cell indices within a
  bounding box
* GridMap: Added `cell_shape_changed` signal to GridMap
* GridMapEditor: Update grid floor when cell shape changes
* GridMapEditor: Add cell shape mesh for hex tiles
* GridMapEditor: Update tile selection mesh when cell shape changes
* GridMapEditor: Fill selection for hex shaped cells
* GridMapEditor: Clear selection for hex shaped cells
* GridMapEditor: Paste for hex shaped cells

GridMapEditor: Hex cell Q/R/S Axis editing support

Editing along the Z-axis with hex cells results in unexpected behavior
for users as cells will be placed in a zig-zag pattern.  This is because
with pointy orientation, the cell centers are offset every other row as
you move along the Z-axis.

In this commit, I added support for editing cells along the Q-axis
(northwest to southeast), and S-axis (southwest to northeast).  The
terms come from the axial coordinate system used in GridMap, and
derrived from:
https://www.redblobgames.com/grids/hexagons/#coordinates-axial

The Z and C hotkeys were repurposed to rotate around the various non-Y
axis options when using hex-shaped cells, using X, Q, Z, then R axis
when rotating clockwise (hotkey C), and the reverse for
counter-clockwise (hotkey Z). For square-shaped cells, these hotkeys
still map to the X-axis and Z-axis.

This commit does not include required changes to the `GridMap` editor
menu to show/hide the hex-specific axis.

Note, also this commit in particular removes code for functionality that
has been broken for some time.  PR godotengine#25406 Added support for using
Shift-Q and Shift-E to expand selection regions to other planes/floors
without changing the actual floor.  This does not function in 4.2.2.  It
looks like at some point the keybindings for change level were changed
from an accelerator to a shortcut, and the code for checking for the key
combination was not updated.

As the functionality does not currently work, and it's non-trivial to
reimplement with hex cells, I'm leaving it out for the time being.
A dedicated PR should be opened to expand selection capabilities within
the GridMapEditor later to re-introduce the functonality.

GridMapEditor: Menu updates for Q/R/S axis editing

GridMap: Fix get_meshes() for NavMesh generation

Needed to update GridMap::get_meshes() to use map_to_local() instead of
manually calculating transforms.

GridMap: Add get_cell_neighbors()

With the transition to axial coordinates for hex shaped cells in
GridMap, it became more difficult to navigate grid map cells to their
neighbors.  This is because the Q/R axial coordinates do not directly
map to x/y equivalents.

In this commit I add GridMap::get_cell_neighbors() which is the minimum
implementation required to map from a GridMap to an AStar3d without
duplicating the axial coordinate math.

This commit should be expanded on to add direction-based neighbor
functions, but I'd rather do that work in a dedicated PR to abstract
navigating cell indexes into a dedicated class for each cell type.

GridMapEditor: Use multimesh for cell highlighting

Minor perf improvement to switch selection to use a multimesh for
highlighting selected cells.

GridMapEditor: Add lines around selection tiles

HexGridEditor: Fix editing grid for Q/R/S axis

GridMapEditor: selection on Q/S planes fixed

Selection along the Q & S planes was selecting a cube volume due to
`GridMap::local_region_to_map()` using the two points as the corners of
an AABB.  This isn't a problem when editing on X/Y/Z planes as the begin
and end points share one common value for at least one of their indices.
The Q & S planes on the other hand, run diagonal across the X/Z
coordinates, so every selection is a cube traversing X/Z.

In this commit I add support for selecting along the Q/S plane.  To do
this, GridMapEditor will now prune the selection region returned from
`GridMap::local_region_to_map()` based on which axis is being edited.

In addition, I trimmed out a lot of extranous values & logic that
weren't being used in the selection code.

GridMapEditor: Update X-Axis grid for hex cells
@BSChad BSChad force-pushed the feat-grid-map-hexagonal-cells branch from d8730d3 to 85b88b2 Compare September 17, 2024 20:50
dmlary added a commit to dmlary/godot-hex-map that referenced this pull request Sep 21, 2024
Extracted `GridMap` code from godot hex-shaped cells PR:
godotengine/godot#85890

In process of converting it into a GDExtension for just hex-shaped
cells.

This commit has just enough functionality to show the edit grid when
selecting `HexMap` in the editor.

Lots of things disconnected and just not working; look for XXX
dmlary added a commit to dmlary/godot-hex-map that referenced this pull request Sep 21, 2024
Adding the Godot license because HexMap & HexMapEditorPlugin come from
GridMap and GridMapEditorPlugin in the Godot Engine.  This project is a
fork of the currently stalled hex-shaped cells PR[^1].

Breaking this into a GDExtension has allowed a 90% rewrite of the
EditorPlugin to improve maintainability.  Also added the HexMapCellId
interface to simplify navigating the hexagonal coordinate space.

The license for all changes made in this repo will also be MIT
licsensed.

[^1]: godotengine/godot#85890
@BSChad BSChad force-pushed the feat-grid-map-hexagonal-cells branch from 85b88b2 to afe806e Compare October 7, 2024 20:39
@BSChad BSChad requested a review from a team as a code owner October 7, 2024 20:39
@AlexLeonardKrea
Copy link

I

GodotsUpcomingHexGrid.mp4

compiled and tested this out today and have to say it's amazing!

@BSChad BSChad force-pushed the feat-grid-map-hexagonal-cells branch from afe806e to c22db78 Compare October 23, 2024 21:21
@BSChad BSChad requested a review from a team as a code owner October 23, 2024 21:21
@KoBeWi
Copy link
Member

KoBeWi commented Oct 29, 2024

I'm not super familiar with GridMap and hexagonal layouts, but I did some testing and read the discussion and this looks fine overall. One thing I noticed is that Center X and Center Z seem to have no effect with Hexagon shape. If this is intended, they should be disabled.

@Mickeon
Copy link
Member

Mickeon commented Oct 29, 2024

Should we aim for 4.4 with this?

Copy link
Member

@Mickeon Mickeon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a lot of lowercase comments, and that doesn't conform to the codestyle. However discussing about the implementation feels more important right now.

Copy link
Member

@Calinou Calinou left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested locally (rebased on top of master 0debc73), it mostly works as expected. This is a great start 🙂

Tip

For prototyping without needing external meshes, use CylinderMesh with 6 sides in the MeshLibrary resource.

Testing project: test-hexagonal-gridmap.zip

I noticed a few issues though:

  • After you bake lightmaps, the shape gets changed back to Square, which messes up the GridMap's appearance. Reloading the scene or restarting the editor/project doesn't fix the issue. The only thing that restores the intended layout is to edit the GridMap, which causes the lightmap data to be invalidated (this persists across reloads if you save the scene). This happens with all rendering methods.
    • The collision data is not affected; it keeps its hexagonal layout regardless.
    • This seems to already have been reported, even without this PR: #95436
  • You can change the X cell size (which automatically changes the Z cell size), but not the Z cell size. Nothing happens when you try to drag it in the inspector. I'd expect to be able to change the Z cell size and have it change the X cell size automatically, for consistency with the X cell size.
  • The default height appears different when you switch between the square and hexagon modes (i.e. floor 0 is at a different height). Is that intended?

Notice how the hexagon's lines appear much closer to the grid which is at Y = 0:

Square Hexagon
Square Hexagon

@BSChad
Copy link
Author

BSChad commented Oct 31, 2024

  • After you bake lightmaps, the shape gets changed back to Square, which messes up the GridMap's appearance. Reloading the scene or restarting the editor/project doesn't fix the issue. The only thing that restores the intended layout is to edit the GridMap, which causes the lightmap data to be invalidated (this persists across reloads if you save the scene). This happens with all rendering methods.

Given that this is currently an issue for the existing Square Gridmap, should this be fixed and investigated separately?

  • You can change the X cell size (which automatically changes the Z cell size), but not the Z cell size. Nothing happens when you try to drag it in the inspector. I'd expect to be able to change the Z cell size and have it change the X cell size automatically, for consistency with the X cell size.

Will fix!

  • The default height appears different when you switch between the square and hexagon modes (i.e. floor 0 is at a different height). Is that intended?

This was not intended, AFAIK. octetdev's original version has some centering code that I think was off and there were definitely a few issues around the drawing of these lines. Does it feel off when placing to you? Wondering if an adjustment like that might be viable in a follow-up change. (Only because I'm currently in slammed by client work mode and would love to not miss the 4.4 boat if the feature has a ticket to ride. 🤣)

@BSChad BSChad force-pushed the feat-grid-map-hexagonal-cells branch from c22db78 to e60071b Compare October 31, 2024 18:53
@Calinou
Copy link
Member

Calinou commented Oct 31, 2024

Does it feel off when placing to you?

Yes, everything is offset while in hexagon mode. Notice how the hexagon shape is crossing the orange grid:

image

Compare this to the same mesh data in square mode, where it sits on top:

image

@dmlary
Copy link
Contributor

dmlary commented Oct 31, 2024

The default height appears different when you switch between the square and hexagon modes (i.e. floor 0 is at a different height). Is that intended?

This is a difference in how the hex grid is placed based on the Center Y property. The hex grid is being shifted to the middle of the cell when Center Y is set. It should be a minor change to adjust the grid to always draw at the bottom of the cell.

That said, based on @AThousandShips very valid concerns about GridMap maintainability and questions about this functionality even belonging in GridMap, I've broken all of the hex functionality out into an independent GDExtension: https://github.com/dmlary/godot-hex-map

@beep-boop-o7
Copy link

Would find this very useful for a project I'm working on, any updates on this getting merged?

@KoBeWi
Copy link
Member

KoBeWi commented Jan 22, 2025

It was discussed in the chat: https://chat.godotengine.org/channel/editor?msg=79mr5SfmnF8rRQ5uj
GridMap has currently no maintainer, so adding new features is problematic.

For now you can use the GDExtension shared above.

@Emaxoso
Copy link

Emaxoso commented May 11, 2025

This would be really super useful for the game I'm developing, is there any update on this PR?
The mentioned GD extension is not compatible with Godot 4.4

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

Successfully merging this pull request may close these issues.

Support hexagon grids with GridMap