From 167f83d5f1f2b152e8286200bc451de0d2ba9156 Mon Sep 17 00:00:00 2001 From: kayomn Date: Fri, 10 Feb 2023 14:30:27 +0000 Subject: [PATCH] Add support for multiple floor tiles sets in one map --- interior/interior_map.gd | 155 ++++++++++++++++++--------------------- map_editor.scn | 2 +- 2 files changed, 71 insertions(+), 86 deletions(-) diff --git a/interior/interior_map.gd b/interior/interior_map.gd index 1d9f20a..1197733 100644 --- a/interior/interior_map.gd +++ b/interior/interior_map.gd @@ -43,62 +43,34 @@ class Chunk: var _interior_map: InteriorMap = null - var _meshes_by_floor_tile: Array[Mesh] = [] - - var _renderable_by_floor_tile: Array[Renderable] = [] + var _renderables_by_mesh := {} func _init(interior_map: InteriorMap, coordinates: Vector2i) -> void: _interior_map = interior_map _coordinates = coordinates - var floor_tile_count := FloorTile.size() - - _renderable_by_floor_tile.resize(floor_tile_count) - _meshes_by_floor_tile.resize(floor_tile_count) - ## ## Invalidates the mesh block, re-baking its contents from the current mesh data set. ## func invalidate() -> void: - _renderable_by_floor_tile.fill(null) + _renderables_by_mesh.clear() - var interior_floor := _interior_map.interior_floor + var floor_map := _interior_map._floor_map + var map_size := _interior_map.size + var offset := _coordinates * _CHUNK_SIZE + var positions_by_mesh := {} + var map_area := Rect2i(Vector2.ZERO, map_size) - if interior_floor == null: - _meshes_by_floor_tile.fill(null) + for y in _CHUNK_SIZE: + var map_row_offset := (map_size.y * y) - else: - _meshes_by_floor_tile[FloorTile.CORNER_NORTH_EAST] = interior_floor.corner_north_east_mesh - _meshes_by_floor_tile[FloorTile.CORNER_NORTH_WEST] = interior_floor.corner_north_west_mesh - _meshes_by_floor_tile[FloorTile.CORNER_SOUTH_EAST] = interior_floor.corner_south_east_mesh - _meshes_by_floor_tile[FloorTile.CORNER_SOUTH_WEST] = interior_floor.corner_south_west_mesh - _meshes_by_floor_tile[FloorTile.EDGE_EAST] = interior_floor.edge_east_mesh - _meshes_by_floor_tile[FloorTile.EDGE_NORTH] = interior_floor.edge_north_mesh - _meshes_by_floor_tile[FloorTile.EDGE_SOUTH] = interior_floor.edge_south_mesh - _meshes_by_floor_tile[FloorTile.EDGE_WEST] = interior_floor.edge_west_mesh - _meshes_by_floor_tile[FloorTile.ENDCAP_EAST] = interior_floor.endcap_east_mesh - _meshes_by_floor_tile[FloorTile.ENDCAP_NORTH] = interior_floor.endcap_north_mesh - _meshes_by_floor_tile[FloorTile.ENDCAP_SOUTH] = interior_floor.endcap_south_mesh - _meshes_by_floor_tile[FloorTile.ENDCAP_WEST] = interior_floor.endcap_west_mesh - _meshes_by_floor_tile[FloorTile.FILL] = interior_floor.fill_mesh - _meshes_by_floor_tile[FloorTile.ISLAND] = interior_floor.island_mesh - _meshes_by_floor_tile[FloorTile.PATH_HORIZONTAL] = interior_floor.path_horizontal_mesh - _meshes_by_floor_tile[FloorTile.PATH_VERTICAL] = interior_floor.path_vertical_mesh + for x in _CHUNK_SIZE: + var map_coordinates := offset + Vector2i(x, y) - var floor_map := _interior_map._floor_map - var map_size := _interior_map.size - var offset := _coordinates * _CHUNK_SIZE - var positions_by_floor_tile: Array[PackedVector2Array] = [] + if map_area.has_point(map_coordinates): + var interior_floor := floor_map[map_row_offset + map_coordinates.x] - positions_by_floor_tile.resize(FloorTile.size()) - - # Find floor tile types. - for y in _CHUNK_SIZE: - for x in _CHUNK_SIZE: - var map_area := Rect2i(Vector2.ZERO, map_size) - var map_coordinates := offset + Vector2i(x, y) - - if map_area.has_point(map_coordinates) and floor_map.get_bitv(map_coordinates): + if interior_floor != null: var tile := 0 for i in Orientation.values().size(): @@ -106,42 +78,61 @@ class Chunk: roundi(cos(i * PI / 2.0)), roundi(sin(i * PI / 2.0))) if map_area.has_point(map_neighbor): - tile += int(floor_map.get_bitv(map_neighbor)) * 2 ** i + tile += int(floor_map[(map_size.y * map_neighbor.y) + map_neighbor.x] == interior_floor) * 2 ** i - positions_by_floor_tile[tile].append(Vector2(x, y)) + var mesh: Mesh = null - # (Re)-bake tiles into multimesh instances for the chunk. - var scenario_rid := _interior_map.get_world_3d().scenario + match tile: + FloorTile.ISLAND: mesh = interior_floor.island_mesh + FloorTile.ENDCAP_WEST: mesh = interior_floor.endcap_west_mesh + FloorTile.ENDCAP_NORTH: mesh = interior_floor.endcap_north_mesh + FloorTile.CORNER_NORTH_WEST: mesh = interior_floor.corner_north_west_mesh + FloorTile.ENDCAP_EAST: mesh = interior_floor.endcap_east_mesh + FloorTile.PATH_HORIZONTAL: mesh = interior_floor.path_horizontal_mesh + FloorTile.CORNER_NORTH_EAST: mesh = interior_floor.corner_north_east_mesh + FloorTile.EDGE_NORTH: mesh = interior_floor.edge_north_mesh + FloorTile.ENDCAP_SOUTH: mesh = interior_floor.endcap_south_mesh + FloorTile.CORNER_SOUTH_WEST: mesh = interior_floor.corner_south_west_mesh + FloorTile.PATH_VERTICAL: mesh = interior_floor.path_vertical_mesh + FloorTile.EDGE_WEST: mesh = interior_floor.edge_west_mesh + FloorTile.CORNER_SOUTH_EAST: mesh = interior_floor.corner_south_east_mesh + FloorTile.EDGE_SOUTH: mesh = interior_floor.edge_south_mesh + FloorTile.EDGE_EAST: mesh = interior_floor.edge_east_mesh + FloorTile.FILL: mesh = interior_floor.fill_mesh - for i in FloorTile.size(): - var floor_positions := positions_by_floor_tile[i] + if mesh != null: + if not(mesh in positions_by_mesh): + positions_by_mesh[mesh] = PackedVector2Array() - if not(floor_positions.is_empty()): - var mesh := _meshes_by_floor_tile[i] + positions_by_mesh[mesh].append(Vector2(x, y)) - if mesh != null: - var floor_position_count := floor_positions.size() - var renderable := Renderable.new(scenario_rid, _meshes_by_floor_tile[i].get_rid(), floor_position_count) + # (Re)-bake tiles into multimesh instances for the chunk. + var scenario_rid := _interior_map.get_world_3d().scenario - for j in floor_position_count: - var tile_position := floor_positions[j] + for mesh in positions_by_mesh: + var positions: PackedVector2Array = positions_by_mesh[mesh] - renderable.set_instance_transform(j, Transform3D(Basis.IDENTITY, Vector3( - ((float(offset.x) + tile_position.x) - (float(map_size.x) * _GRID_ORIGIN.x)) + 0.5, - 0.0, - ((float(offset.y) + tile_position.y) - (float(map_size.y) * _GRID_ORIGIN.y)) + 0.5))) + if not(positions.is_empty()): + var position_count := positions.size() + var renderable := Renderable.new(scenario_rid, mesh.get_rid(), position_count) - _renderable_by_floor_tile[i] = renderable + for i in position_count: + var position := positions[i] + + renderable.set_instance_transform(i, Transform3D(Basis.IDENTITY, Vector3( + ((float(offset.x) + position.x) - (float(map_size.x) * _GRID_ORIGIN.x)) + 0.5, + 0.0, + ((float(offset.y) + position.y) - (float(map_size.y) * _GRID_ORIGIN.y)) + 0.5))) + + _renderables_by_mesh[mesh] = renderable func set_transform(transform: Transform3D) -> void: - for renderable in _renderable_by_floor_tile: - if renderable != null: - renderable.set_transform(transform) + for mesh in _renderables_by_mesh: + _renderables_by_mesh[mesh].set_transform(transform) func set_visible(visible: bool) -> void: - for renderable in _renderable_by_floor_tile: - if renderable != null: - renderable.set_visible(visible) + for mesh in _renderables_by_mesh: + _renderables_by_mesh[mesh].set_visible(visible) ## ## @@ -188,13 +179,7 @@ var _chunks: Array[Chunk] = [] var _chunks_size := Vector2i.ZERO -var _floor_map := BitMap.new() - -## -## -## -@export -var interior_floor: InteriorFloor = null +var _floor_map: Array[InteriorFloor] = [] ## ## Size of the tile grid (in engine units). @@ -204,7 +189,7 @@ var size: Vector2i: set(value): _chunks_size = Vector2i((value / float(_CHUNK_SIZE)).ceil()) - _floor_map.resize(value) + _floor_map.resize(value.x * value.y) _chunks.resize(_chunks_size.x * _chunks_size.y) for y in _chunks_size.y: @@ -233,9 +218,8 @@ func _notification(what: int) -> void: ## For clearing a specific region of the mesh grid, see [method fill_mesh]. ## func clear() -> void: - for y in size.y: - for x in size.x: - _floor_map.set_bit(x, y, false) + for i in _floor_map.size(): + _floor_map[i] = null for y in _chunks_size.y: for x in _chunks_size.x: @@ -243,7 +227,7 @@ func clear() -> void: ## ## Clears the region of the tile grid at [code]area[/code] to only contain instances of -## [code]tile[/code] pointing in the orientation of [code]orientation[/code]. +## [code]interior_floor[/code]. ## ## *Note* that [code]area[/code] *must* be within the area of the of the mesh grid, where ## [code]Vector2i.ZERO[/code] is the top-left and [member size] [code]- 1[/code] is the bottom- @@ -251,7 +235,7 @@ func clear() -> void: ## ## For clearing the whole of the mesh grid, see [method clear_mesh]. ## -func fill_floor(area: Rect2i, exists: bool) -> void: +func fill_floor(area: Rect2i, interior_floor: InteriorFloor) -> void: assert(Rect2i(Vector2i.ZERO, size).encloses(area), "area must be within grid") var filled_chunks := BitMap.new() @@ -260,8 +244,7 @@ func fill_floor(area: Rect2i, exists: bool) -> void: for y in range(area.position.y, area.end.y): for x in range(area.position.x, area.end.x): - _floor_map.set_bit(x, y, exists) - filled_chunks.set_bitv(Vector2i(x, y) / _CHUNK_SIZE, true) + _floor_map[(size.y * (y / _CHUNK_SIZE)) + (x / _CHUNK_SIZE)] = interior_floor for y in _chunks_size.y: for x in _chunks_size.x: @@ -269,8 +252,8 @@ func fill_floor(area: Rect2i, exists: bool) -> void: _get_chunk(Vector2i(x, y)).invalidate() ## -## Plots a single tile at [code]coordinates[/code] to be an instance of [code]tile[/code] pointing -## in the orientation of [code]orientation[/code], overwriting whatever it previously contained. +## Plots a single tile at [code]coordinates[/code] to be an instance of [code]interior_floor[/code], +## overwriting whatever it previously contained. ## ## *Note* that [code]coordinates[/code] *must* be within the area of the of the mesh grid, where ## [code]Vector2i.ZERO[/code] is the top-left and [member size] [code]- 1[/code] is the bottom- @@ -278,7 +261,9 @@ func fill_floor(area: Rect2i, exists: bool) -> void: ## ## For bulk-setting many meshes at once, see [method fill_mesh] and [method clear_mesh]. ## -func plot_floor(coordinates: Vector2i, exists: bool) -> void: +func plot_floor(coordinates: Vector2i, interior_floor: InteriorFloor) -> void: assert(Rect2i(Vector2i.ZERO, size).has_point(coordinates), "coordinate must be within grid") - _floor_map.set_bitv(coordinates, exists) + + _floor_map[(size.y * coordinates.y) + coordinates.x] = interior_floor + _get_chunk(coordinates / _CHUNK_SIZE).invalidate() diff --git a/map_editor.scn b/map_editor.scn index cb425e2..9e92548 100644 --- a/map_editor.scn +++ b/map_editor.scn @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fade16a9713f46ed71eec62081880231b6f5be125c6401cf0944abc443f1b2c7 +oid sha256:694680bfd25ec5fe6cf430e75f44baedc03518579877989d97f33f605ef92fa3 size 13516