WIP: Streamline Interiors System #16
| @ -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() | ||||
|  | ||||
							
								
								
									
										
											BIN
										
									
								
								map_editor.scn
									 (Stored with Git LFS)
									
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								map_editor.scn
									 (Stored with Git LFS)
									
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user