From 5dbe4a2fca22262332fb5571f610669ce5b78ce0 Mon Sep 17 00:00:00 2001 From: snipercup <50166150+snipercup@users.noreply.github.com> Date: Wed, 25 Sep 2024 23:19:11 +0200 Subject: [PATCH 1/3] Remove tiledata from tile --- .../Mapeditor/Scripts/GridContainer.gd | 62 ++++------------ .../Mapeditor/Scripts/mapeditor.gd | 2 +- .../Mapeditor/Scripts/mapeditortile.gd | 74 +++++++++---------- 3 files changed, 53 insertions(+), 85 deletions(-) diff --git a/Scenes/ContentManager/Mapeditor/Scripts/GridContainer.gd b/Scenes/ContentManager/Mapeditor/Scripts/GridContainer.gd index a0ca5d5e..5a0a407a 100644 --- a/Scenes/ContentManager/Mapeditor/Scripts/GridContainer.gd +++ b/Scenes/ContentManager/Mapeditor/Scripts/GridContainer.gd @@ -292,59 +292,31 @@ func apply_paint_to_tile(tile: Control, brush: Control, tilerotate: int): tile.set_rotation_amount(tilerotation) -# Store the data of the current level before changing levels -func storeLevelData() -> void: - currentLevelData.clear() - var has_significant_data = false - - # First pass: Check if any tile has significant data - for child in get_children(): - if child.tileData and (child.tileData.has("id") or \ - child.tileData.has("mob") or child.tileData.has("furniture")\ - or child.tileData.has("itemgroups") or child.tileData.has("areas")): - has_significant_data = true - break - - # Second pass: Add all tiles to currentLevelData if any significant data is found - if has_significant_data: - for child in get_children(): - currentLevelData.append(child.get_tileData()) - else: - # If no tile has significant data, consider adding a special marker or log - print_debug("No significant tile data found for the current level") - - mapEditor.currentMap.levels[currentLevel] = currentLevelData.duplicate(true) - - # Load the level data from the map data. If no data exists, use the default to create a new map. func loadLevelData(newLevel: int) -> void: + print_debug("loadLevelData: loading data for level " + str(newLevel)) if newLevel > 0: - loadLevel(newLevel - 1, levelgrid_below) + refresh_grid(newLevel - 1, levelgrid_below) else: levelgrid_below.hide() if newLevel < 20: - loadLevel(newLevel + 1, levelgrid_above) + refresh_grid(newLevel + 1, levelgrid_above) for tile in levelgrid_above.get_children(): tile.set_above() else: levelgrid_above.hide() - loadLevel(newLevel, self) + refresh_grid(newLevel, self) update_area_visibility() # Loads one of the levels into the grid -func loadLevel(level: int, grid: GridContainer) -> void: - var newLevelData: Array = mapEditor.currentMap.levels[level] +func refresh_grid(level: int, grid: GridContainer) -> void: + var levelData: Array = mapEditor.currentMap.levels[level] var i: int = 0 - # If any data exists on this level, we load it - if newLevelData != []: - for tile in grid.get_children(): - tile.tileData = newLevelData[i] - i += 1 - else: - #No data is present on this level. apply the default value for each tile - for tile in grid.get_children(): - tile.set_default() + for tile in grid.get_children(): + i = tile.get_index() + var tileData = levelData[i] if i < levelData.size() else {} + tile.update_display(tileData) # We change from one level to another. For exmple from ground level (0) to 1 @@ -352,10 +324,8 @@ func loadLevel(level: int, grid: GridContainer) -> void: # Then load the data from mapData if it exists for that level # If no data exists for that level, create new level data func change_level(newlevel: int) -> void: - storeLevelData() loadLevelData(newlevel) currentLevel = newlevel - storeLevelData() # We need to add 10 since the scrollbar starts at -10 @@ -592,7 +562,6 @@ func _on_show_above_toggled(button_pressed): #This function takes the mapData property and saves all of it as a json file. func save_map_json_file(): # Convert the TileGrid.mapData to a JSON string - storeLevelData() mapEditor.update_settings_values() mapEditor.currentMap.save_data_to_disk() mapEditor.currentMap.data_changed(oldmap) @@ -650,8 +619,6 @@ func _on_create_preview_image_button_button_up(): # Loop over all levels and rotate them if they contain tile data func rotate_map() -> void: - # Store the data of the current level before rotating the map - storeLevelData() for i in range(mapEditor.currentMap.levels.size()): # Load each level's data into currentLevelData currentLevelData = mapEditor.currentMap.levels[i] @@ -718,11 +685,14 @@ func copy_selected_tiles_to_memory(): # Copy each tile's data to the copied_tiles_info dictionary for tile in selected_tiles: - copied_tiles_info["tiles_data"].append(tile.tileData.duplicate()) - + var index = tile.get_index() + if index != -1: + var tileData: Dictionary = mapEditor.currentMap.levels[currentLevel][index] + copied_tiles_info["tiles_data"].append(tileData.duplicate()) # Update a preview texture or other UI element to visualize the copied data update_preview_texture_with_copied_data() + # Return the index if the child matches the clicked_tile func get_index_of_child(clicked_tile: Node) -> int: var children = get_children() # Get all children of this GridContainer @@ -1129,7 +1099,7 @@ func rename_area_in_tiles(previd: String, new_id: String, level: int) -> void: # each tile so they are the same again. TODO: Find a way to make sure that if we write to # mapEditor.currentMap.levels[level], we also write to each mapeditortile instance if tiles_with_previd.size() > 0 and level == currentLevel: - loadLevel(currentLevel,self) + refresh_grid(currentLevel,self) # Function to remove a area from all tiles on a specific level diff --git a/Scenes/ContentManager/Mapeditor/Scripts/mapeditor.gd b/Scenes/ContentManager/Mapeditor/Scripts/mapeditor.gd index bb7deeac..1357c910 100644 --- a/Scenes/ContentManager/Mapeditor/Scripts/mapeditor.gd +++ b/Scenes/ContentManager/Mapeditor/Scripts/mapeditor.gd @@ -92,7 +92,7 @@ func _on_rotate_map_button_up(): # When the user presses the map preview button func _on_preview_map_button_up(): - map_preview.mapData = tileGrid.mapEditor.currentMap.get_data() + map_preview.mapData = currentMap.get_data() map_preview.show() diff --git a/Scenes/ContentManager/Mapeditor/Scripts/mapeditortile.gd b/Scenes/ContentManager/Mapeditor/Scripts/mapeditortile.gd index 2cbaa31c..bfcd598c 100644 --- a/Scenes/ContentManager/Mapeditor/Scripts/mapeditortile.gd +++ b/Scenes/ContentManager/Mapeditor/Scripts/mapeditortile.gd @@ -1,45 +1,8 @@ extends Control -#If a tile has no data, we save an empty object. Tiledata can have: -# id, rotation, mob, furniture, itemgroup and areas -const defaultTileData: Dictionary = {} const defaultTexture: String = "res://Scenes/ContentManager/Mapeditor/Images/emptyTile.png" const aboveTexture: String = "res://Scenes/ContentManager/Mapeditor/Images/tileAbove.png" const areaTexture: String = "res://Scenes/ContentManager/Mapeditor/Images/areatile.png" -var tileData: Dictionary = defaultTileData.duplicate(): - set(data): - if (tileData.has("id") and tileData.id == "null") or (tileData.has("id") and tileData.id == null): - return - tileData = data - if tileData.has("id") and not tileData.id == "" and not tileData.id == "null": - $TileSprite.texture = Gamedata.tiles.sprite_by_id(tileData.id) - set_rotation_amount(tileData.get("rotation", 0)) - $ObjectSprite.hide() - $ObjectSprite.rotation_degrees = 0 - $AreaSprite.hide() - $AreaSprite.rotation_degrees = 0 - if tileData.has("mob"): - if tileData.mob.has("rotation"): - $ObjectSprite.rotation_degrees = tileData.mob.rotation - $ObjectSprite.texture = Gamedata.mobs.sprite_by_id(tileData.mob.id) - $ObjectSprite.show() - elif tileData.has("furniture"): - if tileData.furniture.has("rotation"): - $ObjectSprite.rotation_degrees = tileData.furniture.rotation - $ObjectSprite.texture = Gamedata.furnitures.sprite_by_id(tileData.furniture.id) - $ObjectSprite.show() - elif tileData.has("itemgroups"): - var random_itemgroup: String = tileData.itemgroups.pick_random() - $ObjectSprite.texture = Gamedata.itemgroups.sprite_by_id(random_itemgroup) - $ObjectSprite.show() - if tileData.has("areas"): - $AreaSprite.show() - else: - $TileSprite.texture = load(defaultTexture) - $ObjectSprite.texture = null - $ObjectSprite.hide() - $AreaSprite.hide() - set_tooltip() signal tile_clicked(clicked_tile: Control) @@ -260,7 +223,7 @@ func remove_area_from_tile(area_id: String) -> void: # Sets the tooltip for this tile. The user can use this to see what's on this tile. -func set_tooltip() -> void: +func set_tooltip(tileData: Dictionary) -> void: var tooltiptext = "Tile Overview:\n" # Display tile ID @@ -342,3 +305,38 @@ func get_tileData() -> Dictionary: if tileData.has("rotation") and tileData.rotation == 0: tileData.erase("rotation") return tileData + + +# Updates the tile visuals based on the provided data +# Tiledata can have: +# id, rotation, mob, furniture, itemgroup and areas +func update_display(tileData: Dictionary): + if tileData.has("id") and tileData["id"] != "" and tileData["id"] != "null": + $TileSprite.texture = Gamedata.tiles.sprite_by_id(tileData["id"]) + $TileSprite.rotation_degrees = tileData.get("rotation", 0) + $ObjectSprite.hide() + $ObjectSprite.rotation_degrees = 0 + $AreaSprite.hide() + $AreaSprite.rotation_degrees = 0 + if tileData.has("mob"): + if tileData["mob"].has("rotation"): + $ObjectSprite.rotation_degrees = tileData["mob"]["rotation"] + $ObjectSprite.texture = Gamedata.mobs.sprite_by_id(tileData["mob"]["id"]) + $ObjectSprite.show() + elif tileData.has("furniture"): + if tileData["furniture"].has("rotation"): + $ObjectSprite.rotation_degrees = tileData["furniture"]["rotation"] + $ObjectSprite.texture = Gamedata.furnitures.sprite_by_id(tileData["furniture"]["id"]) + $ObjectSprite.show() + elif tileData.has("itemgroups"): + var random_itemgroup: String = tileData["itemgroups"].pick_random() + $ObjectSprite.texture = Gamedata.itemgroups.sprite_by_id(random_itemgroup) + $ObjectSprite.show() + if tileData.has("areas"): + $AreaSprite.show() + else: + $TileSprite.texture = load(defaultTexture) + $ObjectSprite.texture = null + $ObjectSprite.hide() + $AreaSprite.hide() + set_tooltip(tileData) From 8a89042b6e0628421d6daba13b670edb60e2185e Mon Sep 17 00:00:00 2001 From: snipercup <50166150+snipercup@users.noreply.github.com> Date: Wed, 25 Sep 2024 23:21:04 +0200 Subject: [PATCH 2/3] Update apply_paint_to_tile --- .../Mapeditor/Scripts/GridContainer.gd | 47 ++++++++++++------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/Scenes/ContentManager/Mapeditor/Scripts/GridContainer.gd b/Scenes/ContentManager/Mapeditor/Scripts/GridContainer.gd index 5a0a407a..b0483afa 100644 --- a/Scenes/ContentManager/Mapeditor/Scripts/GridContainer.gd +++ b/Scenes/ContentManager/Mapeditor/Scripts/GridContainer.gd @@ -258,38 +258,51 @@ func paint_single_tile(clicked_tile: Control) -> void: apply_paint_to_tile(clicked_tile, selected_brush, rotationAmount) -# Helper function to apply paint or erase logic to a single tile +# Function to apply paint or erase logic to a single tile func apply_paint_to_tile(tile: Control, brush: Control, tilerotate: int): + # Since the grid is always completely filled, the index should be reliable. This assumes + # that mapEditor.currentMap.levels[currentLevel] assumes the same number of items as the grid. + var index = tile.get_index() + if index == -1: + return + var tileData = mapEditor.currentMap.levels[currentLevel][index] + if erase: if brush: if brush.entityType == "mob": - tile.set_mob_id("") + tileData.erase("mob") elif brush.entityType == "furniture": - tile.set_furniture_id("") + tileData.erase("furniture") elif brush.entityType == "itemgroup": - tile.set_tile_itemgroups([]) # erase by passing an empty array + tileData.erase("itemgroups") else: - tile.set_tile_id("") - tile.set_rotation_amount(0) + tileData.erase("id") + tileData.erase("rotation") else: - tile.set_default() + tileData = {} elif brush: selected_brush = brushcomposer.get_random_brush() var tilerotation = brushcomposer.get_tilerotation(tilerotate) if brush.entityType == "mob": - tile.set_mob_id(brush.entityID) - tile.set_mob_rotation(tilerotation) + tileData.erase("furniture") + tileData.erase("itemgroups") + tileData["mob"] = {"id": brush.entityID, "rotation": tilerotation} elif brush.entityType == "furniture": - tile.set_furniture_id(brush.entityID) - tile.set_furniture_rotation(tilerotation) - tile.set_tile_itemgroups(brushcomposer.get_itemgroup_entity_ids()) + tileData.erase("mob") + tileData.erase("itemgroups") + tileData["furniture"] = {"id": brush.entityID, "rotation": tilerotation} + tileData["furniture"]["itemgroups"] = brushcomposer.get_itemgroup_entity_ids() elif brush.entityType == "itemgroup": - # The brushcomposer only returns a brush of this type if there are only - # itemgroup brushes in the brushcomposer. We apply the itemgroups to the tile - tile.set_tile_itemgroups(brushcomposer.get_itemgroup_entity_ids()) + tileData.erase("mob") + tileData.erase("furniture") + tileData["itemgroups"] = brushcomposer.get_itemgroup_entity_ids() else: - tile.set_tile_id(brush.entityID) - tile.set_rotation_amount(tilerotation) + tileData["id"] = brush.entityID + tileData["rotation"] = tilerotation + # Update the map data + mapEditor.currentMap.levels[currentLevel][index] = tileData + # Tell the tile to update its display + tile.update_display(tileData) # Load the level data from the map data. If no data exists, use the default to create a new map. From c0abd273718dfe33c85dea161b0abac7a17ce757 Mon Sep 17 00:00:00 2001 From: snipercup <50166150+snipercup@users.noreply.github.com> Date: Fri, 27 Sep 2024 23:42:27 +0200 Subject: [PATCH 3/3] Data is only stored in mapdata.levels --- .../Mapeditor/Scripts/GridContainer.gd | 176 +++++++++--- .../Scripts/Map_Editor_Preview_Popup.gd | 4 +- .../Mapeditor/Scripts/mapeditortile.gd | 263 ++++-------------- .../ContentManager/Mapeditor/mapeditor.tscn | 3 + 4 files changed, 202 insertions(+), 244 deletions(-) diff --git a/Scenes/ContentManager/Mapeditor/Scripts/GridContainer.gd b/Scenes/ContentManager/Mapeditor/Scripts/GridContainer.gd index b0483afa..d340efc5 100644 --- a/Scenes/ContentManager/Mapeditor/Scripts/GridContainer.gd +++ b/Scenes/ContentManager/Mapeditor/Scripts/GridContainer.gd @@ -286,40 +286,39 @@ func apply_paint_to_tile(tile: Control, brush: Control, tilerotate: int): if brush.entityType == "mob": tileData.erase("furniture") tileData.erase("itemgroups") - tileData["mob"] = {"id": brush.entityID, "rotation": tilerotation} + tileData["mob"] = {"id": brush.entityID} + set_entity_rotation(tileData,"mob",tilerotation) elif brush.entityType == "furniture": tileData.erase("mob") tileData.erase("itemgroups") - tileData["furniture"] = {"id": brush.entityID, "rotation": tilerotation} + tileData["furniture"] = {"id": brush.entityID} + set_entity_rotation(tileData,"furniture",tilerotation) tileData["furniture"]["itemgroups"] = brushcomposer.get_itemgroup_entity_ids() elif brush.entityType == "itemgroup": tileData.erase("mob") tileData.erase("furniture") tileData["itemgroups"] = brushcomposer.get_itemgroup_entity_ids() else: - tileData["id"] = brush.entityID - tileData["rotation"] = tilerotation + set_tile_id(tileData,brush.entityID) + set_rotation_amount(tileData, tilerotation) # Update the map data mapEditor.currentMap.levels[currentLevel][index] = tileData # Tell the tile to update its display - tile.update_display(tileData) + tile.update_display(tileData, brushcomposer.get_selected_area_name()) # Load the level data from the map data. If no data exists, use the default to create a new map. func loadLevelData(newLevel: int) -> void: print_debug("loadLevelData: loading data for level " + str(newLevel)) - if newLevel > 0: + if newLevel > 0: # Refresh below refresh_grid(newLevel - 1, levelgrid_below) else: levelgrid_below.hide() - if newLevel < 20: + if newLevel < 20: # Refresh above refresh_grid(newLevel + 1, levelgrid_above) - for tile in levelgrid_above.get_children(): - tile.set_above() else: levelgrid_above.hide() refresh_grid(newLevel, self) - update_area_visibility() # Loads one of the levels into the grid @@ -329,7 +328,7 @@ func refresh_grid(level: int, grid: GridContainer) -> void: for tile in grid.get_children(): i = tile.get_index() var tileData = levelData[i] if i < levelData.size() else {} - tile.update_display(tileData) + tile.update_display(tileData, brushcomposer.get_selected_area_name()) # We change from one level to another. For exmple from ground level (0) to 1 @@ -441,9 +440,9 @@ func paint_area_in_rectangle(): for tile in tiles: if erase: - tile.remove_area_from_tile(area_data["id"]) + remove_area_from_tile(tile, area_data["id"]) else: - tile.add_area_to_tile(area_data, tilerotation) + add_area_to_tile(tile, area_data, tilerotation) if not erase: add_area_to_map_data(area_data) @@ -451,6 +450,36 @@ func paint_area_in_rectangle(): update_rectangle() +# Removes a area dictionary from the areas list of the tile by its id +func remove_area_from_tile(tile: Control, area_id: String) -> void: + if area_id == "": + return + var tileData: Dictionary = get_tile_data(tile,currentLevel) + if tileData.has("areas"): + for area in tileData.areas: + if area.id == area_id: + tileData.areas.erase(area) + break + if tileData.areas.is_empty(): + tileData.erase("areas") # leave no empty array + tile.update_display(tileData, brushcomposer.get_selected_area_name()) + +# Adds a area dictionary to the areas list of the tile +func add_area_to_tile(tile: Control, area: Dictionary, tilerotation: int) -> void: + if area.is_empty(): + return + + var tileData: Dictionary = get_tile_data(tile,currentLevel) + if not tileData.has("areas"): + tileData.areas = [] + # Check if the area id already exists + for existing_area in tileData.areas: + if existing_area.id == area.id: + return + # Since the area definition is stored in the main mapdata, + # we only need to remember the id and rotation + tileData.areas.append({"id": area.id, "rotation": tilerotation}) + tile.update_display(tileData, brushcomposer.get_selected_area_name()) #The user has pressed the erase toggle button in the editor @@ -525,16 +554,13 @@ func _on_draw_area_toggled(toggled_on) -> void: currentMode = EditorMode.DRAW_AREA if selected_brush: set_brush_preview_texture(selected_brush.get_texture()) - - # Tiles will show the area sprite if the selected area is in the data - set_area_visibility_for_all_tiles(true,brushcomposer.get_selected_area_name()) else: currentMode = EditorMode.NONE - set_area_visibility_for_all_tiles(false,"") if selected_brush: set_brush_preview_texture(selected_brush.get_texture()) else: set_brush_preview_texture(null) + update_area_visibility() # When the user has selected one of the tile brushes to paint with @@ -1066,8 +1092,7 @@ func update_map_areas(areas_clone: Array) -> void: var selected_area_name = brushcomposer.get_selected_area_name() if selected_area_name in missing_area_ids or selected_area_name in renamed_areas or selected_area_name == "None": for tile in get_children(): - tile.set_area_sprite_visibility(false, "") - tile.set_tooltip() + tile.set_area_sprite_visibility(false) # Remove missing area IDs from the chance_modifications lists in all areas for missing_area_id in missing_area_ids: @@ -1109,8 +1134,7 @@ func rename_area_in_tiles(previd: String, new_id: String, level: int) -> void: # We are writing to mapEditor.currentMap.levels, but this data is somehow separate from # data set in mapeditortile.gd's set_data function. When we loadLevel, the data is set to - # each tile so they are the same again. TODO: Find a way to make sure that if we write to - # mapEditor.currentMap.levels[level], we also write to each mapeditortile instance + # each tile so they are the same again. if tiles_with_previd.size() > 0 and level == currentLevel: refresh_grid(currentLevel,self) @@ -1136,33 +1160,105 @@ func remove_area_from_tiles(area_id: String, level: int) -> void: # When the user selects an option in the areas optionbutton in the brushcomposer -func on_areas_option_button_item_selected(optionbutton: Control, index: int): - # Get the selected area name - var selected_area_name = optionbutton.get_item_text(index) - if selected_area_name == "None": - set_area_visibility_for_all_tiles(false, selected_area_name) - else: - set_area_visibility_for_all_tiles(true, selected_area_name) +func on_areas_option_button_item_selected(_optionbutton: Control, _index: int): + update_area_visibility() # Function to update the visibility of area sprites based on the selected area name func update_area_visibility() -> void: var selected_area_name = brushcomposer.get_selected_area_name() - if selected_area_name != "None": - set_area_visibility_for_all_tiles(true, selected_area_name) + if selected_area_name == "None": + for tile in get_children(): + tile.set_area_sprite_visibility(false) else: - set_area_visibility_for_all_tiles(false, "") - - -# Function to set the visibility of area sprites for all tiles in the current level -func set_area_visibility_for_all_tiles(isvisible: bool, areaname: String) -> void: - # Loop over each tile in the current level - for tile in get_children(): - tile.set_area_sprite_visibility(isvisible, areaname) - + for tile in get_children(): + if is_area_in_tile(tile,currentLevel,selected_area_name): + tile.set_area_sprite_visibility(true) + else: + tile.set_area_sprite_visibility(false) # Load the areas from mapdata into the brushcomposer func load_area_data(): brushcomposer.set_area_data(get_map_areas()) - set_area_visibility_for_all_tiles(false, brushcomposer.get_selected_area_name()) + update_area_visibility() + + +# Function to get the tile data from mapEditor.currentMap.levels based on tile's index and level +func get_tile_data(tile: Control, level: int) -> Dictionary: + # Get the tile index using tile.get_index() + var index = tile.get_index() + + # Ensure the index is valid and within the bounds of the level data + if index >= 0 and index < mapEditor.currentMap.levels[level].size(): + # Return the tile data from the specified level and index + return mapEditor.currentMap.levels[level][index] + + # Return an empty dictionary if the index is invalid + return {} + +# Checks if a area with the specified id is in the areas list of the tile +func is_area_in_tile(tile: Control, level: int, area_id: String) -> bool: + var tileData: Dictionary = get_tile_data(tile, level) + if tileData.has("areas"): + for area in tileData.areas: + if area.id == area_id: + return true + return false + + +# Sets the rotation amount for the tile sprite and updates tile data +func set_rotation_amount(tileData: Dictionary, amount: int) -> void: + if amount == 0: + tileData.erase("rotation") + else: + tileData.rotation = amount + + +# Sets the id of the provided tiledata +func set_tile_id(tileData: Dictionary, id: String) -> void: + if id == "null": + return + if id == "": + tileData.erase("id") + else: + tileData["id"] = id + + +# Helper function to set entity rotation +func set_entity_rotation(tileData: Dictionary, key: String, rotationDegrees: int) -> void: + if rotationDegrees == 0: + tileData[key].erase("rotation") + else: + tileData[key].rotation = rotationDegrees + + +# Sets the itemgroups property for the furniture on this tile +# If the "container" property exists in the "Function" property of the furniture data, +# it sets the tileData.furniture.itemgroups property. +# If the "container" property or the "Function" property does not exist, it erases the "itemgroups" property. +# If no furniture is present, it applies the itemgroup to the tile and updates the ObjectSprite with a random sprite. +# If the tileData has the "mob" property, it returns without making any changes. +func set_tile_itemgroups(tileData: Dictionary, itemgroups: Array) -> void: + if tileData.has("mob"): + return + + # If the tile doesn't have furniture + if not tileData.has("furniture"): + if itemgroups.is_empty(): # Erase the itemgroups property if the itemgroups array is empty + tileData.erase("itemgroups") + else: # One of the itemgroups will spawn at random on this tile + tileData["itemgroups"] = itemgroups + return + + if itemgroups.is_empty(): + # Only erase the itemgroups property from furniture + tileData.furniture.erase("itemgroups") + return + + var furniture: DFurniture = Gamedata.furnitures.by_id(tileData.furniture.id) + if furniture.function.is_container: + # The furniture is a container and will get one of the itemgroups assigned at runtime + tileData.furniture.itemgroups = itemgroups + else: # The furniture is not a container so we erase the itemgroups + tileData.furniture.erase("itemgroups") diff --git a/Scenes/ContentManager/Mapeditor/Scripts/Map_Editor_Preview_Popup.gd b/Scenes/ContentManager/Mapeditor/Scripts/Map_Editor_Preview_Popup.gd index ef6f2062..2f04dbb7 100644 --- a/Scenes/ContentManager/Mapeditor/Scripts/Map_Editor_Preview_Popup.gd +++ b/Scenes/ContentManager/Mapeditor/Scripts/Map_Editor_Preview_Popup.gd @@ -54,12 +54,12 @@ func load_level_data(level: int) -> void: # If any data exists on this level, we load it if newLevelData != []: for tile in map_preview_grid.get_children(): - tile.tileData = newLevelData[i] # Assuming set_tile_data method exists in tileScene + tile.update_display(newLevelData[i]) # Assuming set_tile_data method exists in tileScene i += 1 else: # No data is present on this level. apply the default value for each tile for tile in map_preview_grid.get_children(): - tile.set_default() # Assuming set_default method exists in tileScene + tile.update_display() # Calling this without parameters resets the tile to default # Function to generate the map preview diff --git a/Scenes/ContentManager/Mapeditor/Scripts/mapeditortile.gd b/Scenes/ContentManager/Mapeditor/Scripts/mapeditortile.gd index bfcd598c..6ed9e491 100644 --- a/Scenes/ContentManager/Mapeditor/Scripts/mapeditortile.gd +++ b/Scenes/ContentManager/Mapeditor/Scripts/mapeditortile.gd @@ -13,16 +13,6 @@ func _on_texture_rect_gui_input(event: InputEvent) -> void: tile_clicked.emit(self) -# Sets the rotation amount for the tile sprite and updates tile data -func set_rotation_amount(amount: int) -> void: - $TileSprite.rotation_degrees = amount - if amount == 0: - tileData.erase("rotation") - else: - tileData.rotation = amount - set_tooltip() - - # Gets the rotation amount of the tile sprite func get_rotation_amount() -> int: return $TileSprite.rotation_degrees @@ -34,111 +24,6 @@ func set_scale_amount(scaleAmount: int) -> void: custom_minimum_size.y = scaleAmount -func set_tile_id(id: String) -> void: - if id == "null": - return - if id == "": - tileData.erase("id") - $TileSprite.texture = load(defaultTexture) - else: - tileData.id = id - $TileSprite.texture = Gamedata.tiles.sprite_by_id(id) - set_tooltip() - - -# Place a mob on this tile. We erase furniture and itemgroups since they can't exist on the same tile -func set_mob_id(id: String) -> void: - if id == "": - tileData.erase("mob") - if not tileData.has("furniture") and not tileData.has("itemgroups"): - $ObjectSprite.hide() - else: - # A tile can either have a mob or furniture. If we add a mob, remove furniture and itemgroups - tileData.erase("furniture") - tileData.erase("itemgroups") - if tileData.has("mob"): - tileData.mob.id = id - else: - tileData.mob = {"id": id} - $ObjectSprite.texture = Gamedata.mobs.sprite_by_id(id) - $ObjectSprite.show() - set_tooltip() - - -# Place a furniture on this tile. We erase mob and itemgroups since they can't exist on the same tile -func set_furniture_id(id: String) -> void: - if id == "": - tileData.erase("furniture") - if not tileData.has("mob") and not tileData.has("itemgroups"): - $ObjectSprite.hide() - else: - # A tile can either have a mob or furniture. If we add furniture, remove the mob and itemgroups - tileData.erase("mob") - tileData.erase("itemgroups") - if tileData.has("furniture"): - tileData.furniture.id = id - else: - tileData.furniture = {"id": id} - $ObjectSprite.texture = Gamedata.furnitures.sprite_by_id(id) - $ObjectSprite.show() - set_tooltip() - - -# Sets the rotation for the mob sprite -func set_mob_rotation(rotationDegrees: int) -> void: - set_entity_rotation("mob", rotationDegrees) - - -# Sets the rotation for the furniture sprite -func set_furniture_rotation(rotationDegrees: int) -> void: - set_entity_rotation("furniture", rotationDegrees) - - -# Helper function to set entity rotation -func set_entity_rotation(key: String, rotationDegrees: int) -> void: - $ObjectSprite.rotation_degrees = rotationDegrees - if rotationDegrees == 0: - tileData[key].erase("rotation") - else: - tileData[key].rotation = rotationDegrees - set_tooltip() - - -# Sets the itemgroups property for the furniture on this tile -# If the "container" property exists in the "Function" property of the furniture data, -# it sets the tileData.furniture.itemgroups property. -# If the "container" property or the "Function" property does not exist, it erases the "itemgroups" property. -# If no furniture is present, it applies the itemgroup to the tile and updates the ObjectSprite with a random sprite. -# If the tileData has the "mob" property, it returns without making any changes. -func set_tile_itemgroups(itemgroups: Array) -> void: - if tileData.has("mob"): - return - - # If the tile doesn't have furniture - if not tileData.has("furniture"): - if itemgroups.is_empty(): # Erase the itemgroups property if the itemgroups array is empty - tileData.erase("itemgroups") - $ObjectSprite.hide() - else: - # Apply the itemgroup to the tile and update ObjectSprite with a random sprite - var random_itemgroup: String = itemgroups.pick_random() - $ObjectSprite.texture = Gamedata.itemgroups.sprite_by_id(random_itemgroup) - $ObjectSprite.show() - $ObjectSprite.rotation_degrees = 0 - tileData["itemgroups"] = itemgroups - else: - if itemgroups.is_empty(): # Only erase the itemgroups property from furniture - tileData.furniture.erase("itemgroups") - else: - var furniture: DFurniture = Gamedata.furnitures.by_id(tileData.furniture.id) - if not itemgroups.is_empty() and furniture.function.is_container: - tileData.furniture.itemgroups = itemgroups - else: - tileData.furniture.erase("itemgroups") - - set_tooltip() - - # If the user holds the mouse button while entering this tile, we consider it clicked func _on_texture_rect_mouse_entered() -> void: @@ -146,11 +31,6 @@ func _on_texture_rect_mouse_entered() -> void: tile_clicked.emit(self) -# Resets the tiledata to the default -func set_default() -> void: - tileData = defaultTileData.duplicate() - - func highlight() -> void: $TileSprite.modulate = Color(0.227, 0.635, 0.757) @@ -167,18 +47,6 @@ func set_clickable(clickable: bool): $AreaSprite.mouse_filter = MOUSE_FILTER_IGNORE -#This function sets the texture to some static resource that helps the user visualize that something is above -#If this tile has a texture in its data, set it to the above texture instead -func set_above(): - $ObjectSprite.texture = null - $ObjectSprite.hide() - $AreaSprite.hide() - if tileData.has("id") and tileData.id != "": - $TileSprite.texture = load(aboveTexture) - else: - $TileSprite.texture = null - - func _on_texture_rect_resized(): $TileSprite.pivot_offset = size / 2 $ObjectSprite.pivot_offset = size / 2 @@ -189,39 +57,6 @@ func get_tile_texture(): return $TileSprite.texture -# Adds a area dictionary to the areas list of the tile -func add_area_to_tile(area: Dictionary, tilerotation: int) -> void: - if area.is_empty(): - return - if not tileData.has("areas"): - tileData.areas = [] - # Check if the area id already exists - for existing_area in tileData.areas: - if existing_area.id == area.id: - return - # Since the area definition is stored in the main mapdata, - # we only need to remember the id and rotation - tileData.areas.append({"id": area.id, "rotation": tilerotation}) - $AreaSprite.show() - set_tooltip() - - -# Removes a area dictionary from the areas list of the tile by its id -func remove_area_from_tile(area_id: String) -> void: - if area_id == "": - return - if tileData.has("areas"): - for area in tileData.areas: - if area.id == area_id: - tileData.areas.erase(area) - $AreaSprite.hide() - break - if tileData.areas.is_empty(): - tileData.erase("areas") # leave no empty array - $AreaSprite.hide() - set_tooltip() - - # Sets the tooltip for this tile. The user can use this to see what's on this tile. func set_tooltip(tileData: Dictionary) -> void: var tooltiptext = "Tile Overview:\n" @@ -280,44 +115,36 @@ func set_tooltip(tileData: Dictionary) -> void: # Sets the visibility of the area sprite based on the provided area name and visibility flag -func set_area_sprite_visibility(isvisible: bool, area_name: String) -> void: - if tileData.has("areas"): - for area in tileData["areas"]: - if area["id"] == area_name: - $AreaSprite.visible = isvisible - return - $AreaSprite.visible = false +func set_area_sprite_visibility(isvisible: bool) -> void: + $AreaSprite.visible = isvisible -# Checks if a area with the specified id is in the areas list of the tile -func is_area_in_tile(area_id: String) -> bool: - if tileData.has("areas"): - for area in tileData.areas: - if area.id == area_id: - return true - return false - - -# Gets the tileData with specific checks and returns it -func get_tileData() -> Dictionary: - if tileData.has("id") and tileData.id == "": - tileData.erase("id") - if tileData.has("rotation") and tileData.rotation == 0: - tileData.erase("rotation") - return tileData +# Updates the tile visuals based on the provided data +# Tiledata can have: id, rotation, mob, furniture, itemgroup, and areas +func update_display(tileData: Dictionary = {}, selected_area_name: String = "None"): + var parent_name = get_parent().get_name() + + # Will be made visible again if the conditions are right + $ObjectSprite.hide() + $AreaSprite.hide() + # If the parent node is "levelgrid_above", run the "set_above" logic + if parent_name == "Level_Above": + $ObjectSprite.texture = null + if tileData.has("id") and tileData.id != "": + $TileSprite.texture = load(aboveTexture) + else: + $TileSprite.texture = null + return # Exit early since we don't need to do further processing for the above layer -# Updates the tile visuals based on the provided data -# Tiledata can have: -# id, rotation, mob, furniture, itemgroup and areas -func update_display(tileData: Dictionary): + # Regular update logic for other grids if tileData.has("id") and tileData["id"] != "" and tileData["id"] != "null": - $TileSprite.texture = Gamedata.tiles.sprite_by_id(tileData["id"]) + set_tile_id(tileData["id"]) $TileSprite.rotation_degrees = tileData.get("rotation", 0) - $ObjectSprite.hide() $ObjectSprite.rotation_degrees = 0 - $AreaSprite.hide() $AreaSprite.rotation_degrees = 0 + + # Check for mob and furniture, and update accordingly if tileData.has("mob"): if tileData["mob"].has("rotation"): $ObjectSprite.rotation_degrees = tileData["mob"]["rotation"] @@ -329,14 +156,46 @@ func update_display(tileData: Dictionary): $ObjectSprite.texture = Gamedata.furnitures.sprite_by_id(tileData["furniture"]["id"]) $ObjectSprite.show() elif tileData.has("itemgroups"): - var random_itemgroup: String = tileData["itemgroups"].pick_random() - $ObjectSprite.texture = Gamedata.itemgroups.sprite_by_id(random_itemgroup) - $ObjectSprite.show() - if tileData.has("areas"): - $AreaSprite.show() + set_tile_itemgroups(tileData) + + # Show the area sprite if conditions are met + if tileData.has("areas") and selected_area_name != "None": + for area in tileData["areas"]: + if area["id"] == selected_area_name: + $AreaSprite.show() + break # Exit the loop once the area is found else: $TileSprite.texture = load(defaultTexture) $ObjectSprite.texture = null - $ObjectSprite.hide() - $AreaSprite.hide() + set_tooltip(tileData) + + + +# Update the sprite by id +func set_tile_id(id: String) -> void: + if id == "null": + return + if id == "": + $TileSprite.texture = load(defaultTexture) + else: + $TileSprite.texture = Gamedata.tiles.sprite_by_id(id) + + +# Manages the itemgroups property for the tile. +# If the tile has no mob or furniture, it applies itemgroups to the tile and assigns a random sprite to the ObjectSprite. +# If the itemgroups array is empty, it hides the ObjectSprite and removes the itemgroups property from the tile. +# If the tileData contains a mob or furniture, the function returns early without making any changes. +func set_tile_itemgroups(tileData: Dictionary) -> void: + if tileData.has("mob") or tileData.has("furniture"): + return + + var itemgroups: Array = tileData.get("itemgroups", []) + if itemgroups.is_empty(): # Erase the itemgroups property if the itemgroups array is empty + $ObjectSprite.hide() + else: + # Apply the itemgroup to the tile and update ObjectSprite with a random sprite + var random_itemgroup: String = itemgroups.pick_random() + $ObjectSprite.texture = Gamedata.itemgroups.sprite_by_id(random_itemgroup) + $ObjectSprite.show() + $ObjectSprite.rotation_degrees = 0 diff --git a/Scenes/ContentManager/Mapeditor/mapeditor.tscn b/Scenes/ContentManager/Mapeditor/mapeditor.tscn index 2c8d0450..2d500926 100644 --- a/Scenes/ContentManager/Mapeditor/mapeditor.tscn +++ b/Scenes/ContentManager/Mapeditor/mapeditor.tscn @@ -82,10 +82,12 @@ anchor_right = 1.0 anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 +current_tab = 0 [node name="Edit Map" type="HSplitContainer" parent="TabContainer"] layout_mode = 2 theme_override_icons/grabber = SubResource("GradientTexture2D_1xgu1") +metadata/_tab_index = 0 [node name="MapeditorContainer" type="VBoxContainer" parent="TabContainer/Edit Map"] layout_mode = 2 @@ -358,6 +360,7 @@ tileBrush = ExtResource("8_o4x7s") visible = false layout_mode = 2 columns = 2 +metadata/_tab_index = 1 [node name="NameLabel" type="Label" parent="TabContainer/Settings"] layout_mode = 2