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

TileData.get_terrain_peering_bit() returns error #89909

Closed
andreas-volz opened this issue Mar 26, 2024 · 2 comments · Fixed by #89911
Closed

TileData.get_terrain_peering_bit() returns error #89909

andreas-volz opened this issue Mar 26, 2024 · 2 comments · Fixed by #89911

Comments

@andreas-volz
Copy link

andreas-volz commented Mar 26, 2024

Tested versions

v4.2.1.stable.official [b09f793]

System information

Godot v4.2.1.stable - Linux Mint 21 (Vanessa) - X11 - GLES3 (Compatibility) - NVIDIA GeForce RTX 3060 (nvidia; 535.161.07) - AMD Ryzen 5 2600X Six-Core Processor (12 Threads)

Issue description

My gdscript calls TileData.get_terrain_peering_bit() for all tiles in the tile atlas. The reason is to use the peering information for procedural generation.
https://docs.godotengine.org/en/stable/classes/class_tiledata.html#class-tiledata-method-get-terrain-peering-bit

The problem is that I get this error for all tiles which have no peering bits:

E 0:00:00:0861   SuperPosition.gd:116 @ print_tile_bits(): Condition "!is_valid_terrain_peering_bit(p_peering_bit)" is true. Returning: -1
  <C++-Quelle>   scene/resources/tile_set.cpp:5547 @ get_terrain_peering_bit()
  <Stacktrace>   SuperPosition.gd:116 @ print_tile_bits()
                 SuperPosition.gd:70 @ read_superposition_connectors_from_tileset()
                 World.gd:26 @ _ready()

This might be the "problem":
https://github.com/godotengine/godot/blob/master/scene/resources/2d/tile_set.cpp#L6434

solution ideas:

  1. export a gdscript function has_terrain_peering_bit() returning information if any bits are set before asking for it
  2. write a GdNative in my local project and direct access the native API before calling

Steps to reproduce

call get_terrain_peering_bit() on a cell with no peering bit.

Minimal reproduction project (MRP)

this test prints the error:

# works only in Tile Shape "Square"
const TERRAIN_MODE_MATCH_SIDES_DIRECTION := [
	TileSet.CellNeighbor.CELL_NEIGHBOR_TOP_SIDE, # N
	TileSet.CellNeighbor.CELL_NEIGHBOR_RIGHT_SIDE, # E
	TileSet.CellNeighbor.CELL_NEIGHBOR_BOTTOM_SIDE, # S
	TileSet.CellNeighbor.CELL_NEIGHBOR_LEFT_SIDE # W
]

func print_tile_bits(tile_set :TileSet):
	var atlas_source:TileSetAtlasSource = tile_set.get_source(tile_set.get_source_id(0))
	
	print("get_source_count: ", tile_set.get_source_count())
		
	var terrain_set = 0
	
	var terrain_mode := tile_set.get_terrain_set_mode(terrain_set)
	print("terrain_mode: ", terrain_mode)
	
	if terrain_mode == TileSet.TerrainMode.TERRAIN_MODE_MATCH_SIDES:
		for atlas_count in atlas_source.get_tiles_count():
			var tile_id = atlas_source.get_tile_id(atlas_count)
			for i in TERRAIN_MODE_MATCH_SIDES_DIRECTION.size():
				var peering_bit: int = TERRAIN_MODE_MATCH_SIDES_DIRECTION[i]
				var tile_data:TileData = atlas_source.get_tile_data(tile_id, 0)
				var terrain_bit := tile_data.get_terrain_peering_bit(peering_bit)
				#print("valid: ", tile_data.is_valid_terrain_peering_bit)
				if terrain_bit != -1:
					print("tile_id: ", tile_id)
		
		for tile in _data:
			var sockets: Array[int] = []
			sockets.resize(TERRAIN_MODE_MATCH_SIDES_DIRECTION.size())
			tile["sockets"] = sockets
		
			for i in TERRAIN_MODE_MATCH_SIDES_DIRECTION.size():
				var peering_bit: int = TERRAIN_MODE_MATCH_SIDES_DIRECTION[i]
				var tile_data:TileData = atlas_source.get_tile_data(tile.atlas, 0)
				var terrain_bit := tile_data.get_terrain_peering_bit(peering_bit)
				tile["sockets"][i] = terrain_bit
				print("SIDE terrain_bit: ", terrain_bit)
@AThousandShips
Copy link
Member

AThousandShips commented Mar 26, 2024

Yes, the mode only works with square, it need other directions in other modes, this should be documented more clearly, but there's no bug here, see here for the valid neighbors:

bool TileSet::is_valid_terrain_peering_bit_for_mode(TileSet::TerrainMode p_terrain_mode, TileSet::CellNeighbor p_peering_bit) const {
if (tile_shape == TileSet::TILE_SHAPE_SQUARE) {
if (p_terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES || p_terrain_mode == TileSet::TERRAIN_MODE_MATCH_SIDES) {
if (p_peering_bit == TileSet::CELL_NEIGHBOR_RIGHT_SIDE ||
p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE ||
p_peering_bit == TileSet::CELL_NEIGHBOR_LEFT_SIDE ||
p_peering_bit == TileSet::CELL_NEIGHBOR_TOP_SIDE) {
return true;
}
}
if (p_terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES || p_terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS) {
if (p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER ||
p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER ||
p_peering_bit == TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER ||
p_peering_bit == TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER) {
return true;
}
}
} else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) {
if (p_terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES || p_terrain_mode == TileSet::TERRAIN_MODE_MATCH_SIDES) {
if (p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE ||
p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE ||
p_peering_bit == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE ||
p_peering_bit == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
return true;
}
}
if (p_terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES || p_terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS) {
if (p_peering_bit == TileSet::CELL_NEIGHBOR_RIGHT_CORNER ||
p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER ||
p_peering_bit == TileSet::CELL_NEIGHBOR_LEFT_CORNER ||
p_peering_bit == TileSet::CELL_NEIGHBOR_TOP_CORNER) {
return true;
}
}
} else {
if (get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
if (p_terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES || p_terrain_mode == TileSet::TERRAIN_MODE_MATCH_SIDES) {
if (p_peering_bit == TileSet::CELL_NEIGHBOR_RIGHT_SIDE ||
p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE ||
p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE ||
p_peering_bit == TileSet::CELL_NEIGHBOR_LEFT_SIDE ||
p_peering_bit == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE ||
p_peering_bit == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
return true;
}
}
if (p_terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES || p_terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS) {
if (p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER ||
p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_CORNER ||
p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER ||
p_peering_bit == TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER ||
p_peering_bit == TileSet::CELL_NEIGHBOR_TOP_CORNER ||
p_peering_bit == TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER) {
return true;
}
}
} else {
if (p_terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES || p_terrain_mode == TileSet::TERRAIN_MODE_MATCH_SIDES) {
if (p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE ||
p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_SIDE ||
p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE ||
p_peering_bit == TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE ||
p_peering_bit == TileSet::CELL_NEIGHBOR_TOP_SIDE ||
p_peering_bit == TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE) {
return true;
}
}
if (p_terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES || p_terrain_mode == TileSet::TERRAIN_MODE_MATCH_CORNERS) {
if (p_peering_bit == TileSet::CELL_NEIGHBOR_RIGHT_CORNER ||
p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER ||
p_peering_bit == TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER ||
p_peering_bit == TileSet::CELL_NEIGHBOR_LEFT_CORNER ||
p_peering_bit == TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER ||
p_peering_bit == TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER) {
return true;
}
}
}
}
return false;
}

We should probably expose this helper method to help with using this properly

@AThousandShips
Copy link
Member

Making a PR to expose this on TileData

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

Successfully merging a pull request may close this issue.

2 participants