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

Renaming area in mapeditor still fails sometimes #402

Closed
snipercup opened this issue Sep 23, 2024 · 1 comment · Fixed by #404
Closed

Renaming area in mapeditor still fails sometimes #402

snipercup opened this issue Sep 23, 2024 · 1 comment · Fixed by #404
Assignees
Labels
bug Something isn't working

Comments

@snipercup
Copy link
Collaborator

Renaming an area in the mapeditor will fail sometimes. The area gets a new name, but the tiles that it covers do not have their assigned area renamed with them.

Steps to reproduce:

  • Have the area set to none
  • Add a tile to the brushcomposer and paint an area
  • Rename the area in the area editor and press OK. the area selector in the brushcomposer will now change to "none"
  • Change the level by two (up or down) (the selected area is still none
  • Add a brush to the brushcomposer and paint an area
  • Rename the area in the area editor and press OK
  • Observe the area was renamed in the area editor, but when hovering over the tile that you painted the area on, it says under "areas" that the old area name is still assigned.
@snipercup snipercup added the bug Something isn't working label Sep 23, 2024
@snipercup
Copy link
Collaborator Author

snipercup commented Sep 25, 2024

The problem is that we're writing to mapeditortile.tiledata and to mapEditor.currentMap.levels. I think we need to change it so we only write to mapEditor.currentMap.levels and have the mapeditortile only visualize the data.

Here's a suggestion from chatgpt but he's using python instead of gdscript so we need modifications:

Based on your requirements, here's the relevant code with changes to make mapEditor.currentMap.levels the single source of data. The tiles now only display data from mapEditor.currentMap.levels and do not store or modify their own tileData.


Changes in the main script:

  1. Modify apply_paint_to_tile to update mapEditor.currentMap.levels directly:
# 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":
                tileData.erase("mob")
            elif brush.entityType == "furniture":
                tileData.erase("furniture")
            elif brush.entityType == "itemgroup":
                tileData.erase("itemgroups")
            else:
                tileData.erase("id")
                tileData.erase("rotation")
        else:
            tileData = {}
    elif brush:
        selected_brush = brushcomposer.get_random_brush()
        var tilerotation = brushcomposer.get_tilerotation(tilerotate)
        if brush.entityType == "mob":
            tileData.erase("furniture")
            tileData.erase("itemgroups")
            tileData["mob"] = {"id": brush.entityID, "rotation": tilerotation}
        elif brush.entityType == "furniture":
            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":
            tileData.erase("mob")
            tileData.erase("furniture")
            tileData["itemgroups"] = brushcomposer.get_itemgroup_entity_ids()
        else:
            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)

Explanation:

  • Instead of modifying the tile's tileData, we update the corresponding entry in mapEditor.currentMap.levels[currentLevel].
  • After updating the data, we call tile.update_display(tileData) to refresh the tile's display.
  1. Assign an index to each tile in create_level_tiles:
# Helper function to create tiles for a specific level grid
func create_level_tiles(grid: GridContainer, connect_signals: bool):
    var index = 0
    for x in range(mapEditor.mapWidth):
        for y in range(mapEditor.mapHeight):
            var tile_instance = tileScene.instantiate()
            grid.add_child(tile_instance)
            tile_instance.tileIndex = index  # Assign index to tile
            index += 1
            if connect_signals:
                tile_instance.tile_clicked.connect(grid_tile_clicked)
            tile_instance.set_clickable(connect_signals)

Explanation:

  • Each tile now knows its index within the grid, which is used to access its data in mapEditor.currentMap.levels.
  1. Update loadLevel to use update_display:
# Loads one of the levels into the grid
func loadLevel(level: int, grid: GridContainer) -> void:
    var levelData: Array = mapEditor.currentMap.levels[level]
    var i: int = 0
    for tile in grid.get_children():
        i = tile.get_index()
        var tileData = levelData[i] if i < levelData.size() else {}
        tile.update_display(tileData)

Explanation:

  • Instead of setting tile.tileData, we call tile.update_display(tileData) to update the tile's display based on the data in mapEditor.currentMap.levels.
  1. Remove storeLevelData function:
# Remove this function as it's no longer needed
func storeLevelData() -> void:
    pass  # Function body is no longer necessary

Explanation:

  • Since we're always updating mapEditor.currentMap.levels, there's no need to store level data separately.
  1. Adjust functions that previously accessed tile.get_tileData() or modified tile.tileData:

For example, in copy_selected_tiles_to_memory:

# Copy selected tiles to memory without accessing tile.get_tileData()
func copy_selected_tiles_to_memory():
    reset_rotation()
    reset_copied_tiles_info()
    var selection_dimensions = get_selection_dimensions(start_point, end_point)
    var selected_tiles = get_tiles_in_rectangle(start_point, end_point)
    copied_tiles_info["width"] = selection_dimensions["width"]
    copied_tiles_info["height"] = selection_dimensions["height"]

    for tile in selected_tiles:
        var index = tile.get_index()
        if index != -1:
            var tileData: Dictionary = mapEditor.currentMap.levels[currentLevel][index]
            copied_tiles_info["tiles_data"].append(tileData.duplicate())

Explanation:

  • We now get the tile data directly from mapEditor.currentMap.levels using the tile's index.

Changes in the mapeditortile script:

  1. Remove tileData as a settable property and related methods:
# Remove tileData setter and related functions
var tileData: Dictionary  # Remove setter methods

# Remove methods like set_tile_id, set_mob_id, set_furniture_id, etc.

Explanation:

  • The tile no longer holds its own tileData that can be modified externally.
  1. Add update_display method to refresh the tile's visuals:
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)

Explanation:

  • This method updates the tile's sprites based on the provided tileData.
  • It replaces the previous property setter and individual setter methods.
  1. Adjust set_tooltip method to accept tileData:
func set_tooltip(tileData: Dictionary) -> void:
    # Use tileData to build tooltip text

Explanation:

  • Since tileData is no longer a property of the tile, we pass it as a parameter.
  1. Remove methods that modify tileData directly:
  • Remove methods like set_tile_id, set_mob_id, set_furniture_id, etc.

Explanation:

  • The tile no longer modifies its own data; it only displays data from mapEditor.currentMap.levels.

General Explanation:

  • Data Flow Change: The authoritative data now resides solely in mapEditor.currentMap.levels. Tiles are purely visual representations that update their display when told to.
  • Tile Indexing: Each tile knows its index (tileIndex), allowing it to access its data in mapEditor.currentMap.levels.
  • Updating Tiles: Whenever the map data changes (e.g., painting a tile, rotating the map), we update mapEditor.currentMap.levels and then instruct the relevant tiles to update their display using tile.update_display(tileData).
  • Eliminated Redundancy: By removing the need to read from or write to tile.get_tileData() and tile.tileData, we ensure there's a single source of truth, reducing the risk of data inconsistency.

Note: Remember to adjust any other parts of your code that interact with tileData, ensuring they reference mapEditor.currentMap.levels instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant