Skip to content

Commit

Permalink
Change the logic to handle the future map loading (#8342)
Browse files Browse the repository at this point in the history
  • Loading branch information
ihhub authored Jan 27, 2024
1 parent 3f3ffeb commit 04b7efd
Show file tree
Hide file tree
Showing 9 changed files with 155 additions and 56 deletions.
72 changes: 53 additions & 19 deletions src/fheroes2/editor/editor_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -475,16 +475,20 @@ namespace Interface
if ( isCursorOverGamearea && _editorPanel.getBrushArea().width == 0 ) {
if ( _editorPanel.isTerrainEdit() ) {
// Fill the selected area in terrain edit mode.
const fheroes2::ActionCreator action( _historyManager, _mapFormat );
fheroes2::ActionCreator action( _historyManager, _mapFormat );

const int groundId = _editorPanel.selectedGroundType();
Maps::setTerrainOnTiles( _selectedTile, _tileUnderCursor, groundId );

action.commit();
}
else if ( _editorPanel.isEraseMode() ) {
// Erase objects in the selected area.
const fheroes2::ActionCreator action( _historyManager, _mapFormat );
fheroes2::ActionCreator action( _historyManager, _mapFormat );

Maps::eraseObjectsOnTiles( _selectedTile, _tileUnderCursor, _editorPanel.getEraseTypes() );

action.commit();
}
}

Expand Down Expand Up @@ -670,7 +674,7 @@ namespace Interface

const int groundId = _editorPanel.selectedGroundType();

const fheroes2::ActionCreator action( _historyManager, _mapFormat );
fheroes2::ActionCreator action( _historyManager, _mapFormat );

if ( brushSize.width > 0 ) {
const fheroes2::Point indices = getBrushAreaIndicies( brushSize, tileIndex );
Expand All @@ -687,37 +691,47 @@ namespace Interface
}

_redraw |= mapUpdateFlags;

action.commit();
}
else if ( _editorPanel.isRoadDraw() ) {
const fheroes2::ActionCreator action( _historyManager, _mapFormat );
fheroes2::ActionCreator action( _historyManager, _mapFormat );

if ( Maps::updateRoadOnTile( tile, true ) ) {
_redraw |= mapUpdateFlags;

action.commit();
}
}
else if ( _editorPanel.isStreamDraw() ) {
const fheroes2::ActionCreator action( _historyManager, _mapFormat );
fheroes2::ActionCreator action( _historyManager, _mapFormat );

if ( Maps::updateStreamOnTile( tile, true ) ) {
_redraw |= mapUpdateFlags;

action.commit();
}
}
else if ( _editorPanel.isEraseMode() ) {
const fheroes2::Rect brushSize = _editorPanel.getBrushArea();
assert( brushSize.width == brushSize.height );

const fheroes2::ActionCreator action( _historyManager, _mapFormat );
fheroes2::ActionCreator action( _historyManager, _mapFormat );

if ( brushSize.width > 1 ) {
const fheroes2::Point indices = getBrushAreaIndicies( brushSize, tileIndex );

if ( Maps::eraseObjectsOnTiles( indices.x, indices.y, _editorPanel.getEraseTypes() ) ) {
_redraw |= mapUpdateFlags;

action.commit();
}
}
else {
if ( Maps::eraseOjects( tile, _editorPanel.getEraseTypes() ) ) {
_redraw |= mapUpdateFlags;

action.commit();
}

if ( brushSize.width == 0 ) {
Expand Down Expand Up @@ -1016,9 +1030,11 @@ namespace Interface
return;
}

const fheroes2::ActionCreator action( _historyManager, _mapFormat );
fheroes2::ActionCreator action( _historyManager, _mapFormat );

setObjectOnTile( tile, Maps::ObjectGroup::LANDSCAPE_TOWN_BASEMENTS, basementId );
if ( !setObjectOnTile( tile, Maps::ObjectGroup::LANDSCAPE_TOWN_BASEMENTS, basementId ) ) {
return;
}

// Since the whole object consists of multiple "objects" we have to put the same ID for all of them.
// Every time an object is being placed on a map the counter is going to be increased by 1.
Expand All @@ -1028,17 +1044,25 @@ namespace Interface

Maps::setLastObjectUID( objectId );

setObjectOnTile( tile, groupType, type );
if ( !setObjectOnTile( tile, groupType, type ) ) {
return;
}

// Add flags.
assert( tile.GetIndex() > 0 && tile.GetIndex() < world.w() * world.h() - 1 );
Maps::setLastObjectUID( objectId );

setObjectOnTile( world.GetTiles( tile.GetIndex() - 1 ), Maps::ObjectGroup::LANDSCAPE_FLAGS, color * 2 );
if ( !setObjectOnTile( world.GetTiles( tile.GetIndex() - 1 ), Maps::ObjectGroup::LANDSCAPE_FLAGS, color * 2 ) ) {
return;
}

Maps::setLastObjectUID( objectId );

setObjectOnTile( world.GetTiles( tile.GetIndex() + 1 ), Maps::ObjectGroup::LANDSCAPE_FLAGS, color * 2 + 1 );
if ( !setObjectOnTile( world.GetTiles( tile.GetIndex() + 1 ), Maps::ObjectGroup::LANDSCAPE_FLAGS, color * 2 + 1 ) ) {
return;
}

action.commit();
}
else if ( groupType == Maps::ObjectGroup::ADVENTURE_MINES ) {
int32_t type = -1;
Expand Down Expand Up @@ -1068,11 +1092,14 @@ namespace Interface
return;
}

const fheroes2::ActionCreator action( _historyManager, _mapFormat );
fheroes2::ActionCreator action( _historyManager, _mapFormat );

setObjectOnTile( tile, groupType, type );
if ( !setObjectOnTile( tile, groupType, type ) ) {
return;
}

// TODO: Place owner flag according to the color state.
action.commit();
}
else if ( groupType == Maps::ObjectGroup::ADVENTURE_DWELLINGS ) {
const auto & objectInfo = getObjectInfo( groupType, _editorPanel.getSelectedObjectType() );
Expand Down Expand Up @@ -1151,26 +1178,33 @@ namespace Interface
}
}

void EditorInterface::setObjectOnTile( Maps::Tiles & tile, const Maps::ObjectGroup groupType, const int32_t objectIndex )
bool EditorInterface::setObjectOnTile( Maps::Tiles & tile, const Maps::ObjectGroup groupType, const int32_t objectIndex )
{
const auto & objectInfo = getObjectInfo( groupType, objectIndex );
if ( objectInfo.empty() ) {
// Check your logic as you are trying to insert an empty object!
assert( 0 );
return;
return false;
}

_redraw |= mapUpdateFlags;

if ( !Maps::setObjectOnTile( tile, objectInfo, true ) ) {
return false;
}

Maps::setObjectOnTile( tile, objectInfo, true );
Maps::addObjectToMap( _mapFormat, tile.GetIndex(), groupType, static_cast<uint32_t>( objectIndex ) );

_redraw |= mapUpdateFlags;
return true;
}

void EditorInterface::setObjectOnTileAsAction( Maps::Tiles & tile, const Maps::ObjectGroup groupType, const int32_t objectIndex )
{
const fheroes2::ActionCreator action( _historyManager, _mapFormat );
fheroes2::ActionCreator action( _historyManager, _mapFormat );

setObjectOnTile( tile, groupType, objectIndex );
if ( setObjectOnTile( tile, groupType, objectIndex ) ) {
action.commit();
}
}

bool EditorInterface::loadMap( const std::string & filePath )
Expand Down
2 changes: 1 addition & 1 deletion src/fheroes2/editor/editor_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ namespace Interface
// Do nothing.
}

void setObjectOnTile( Maps::Tiles & tile, const Maps::ObjectGroup groupType, const int32_t objectIndex );
bool setObjectOnTile( Maps::Tiles & tile, const Maps::ObjectGroup groupType, const int32_t objectIndex );

void setObjectOnTileAsAction( Maps::Tiles & tile, const Maps::ObjectGroup groupType, const int32_t objectIndex );

Expand Down
16 changes: 5 additions & 11 deletions src/fheroes2/editor/history_manager.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/***************************************************************************
* fheroes2: https://github.com/ihhub/fheroes2 *
* Copyright (C) 2023 *
* Copyright (C) 2023 - 2024 *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
Expand Down Expand Up @@ -110,23 +110,17 @@ namespace fheroes2
_action = std::make_unique<MapAction>( mapFormat );
}

ActionCreator::~ActionCreator()
void ActionCreator::commit()
{
auto * action = dynamic_cast<MapAction *>( _action.get() );
if ( action == nullptr ) {
// How is it even possible?
// How is it even possible? Did you call this method twice?
assert( 0 );
return;
}

try {
if ( action->prepare() ) {
_manager.add( std::move( _action ) );
}
}
catch ( ... ) {
// If an exception happens here then something is very wrong with the code.
assert( 0 );
if ( action->prepare() ) {
_manager.add( std::move( _action ) );
}
}
}
12 changes: 10 additions & 2 deletions src/fheroes2/editor/history_manager.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/***************************************************************************
* fheroes2: https://github.com/ihhub/fheroes2 *
* Copyright (C) 2023 *
* Copyright (C) 2023 - 2024 *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
Expand Down Expand Up @@ -52,12 +52,20 @@ namespace fheroes2
public:
explicit ActionCreator( HistoryManager & manager, Maps::Map_Format::MapFormat & mapFormat );

~ActionCreator();
~ActionCreator()
{
if ( _action ) {
// The action wasn't committed. Undo all the changes.
_action->undo();
}
}

ActionCreator( const ActionCreator & ) = delete;

ActionCreator & operator=( const ActionCreator & ) = delete;

void commit();

private:
HistoryManager & _manager;

Expand Down
25 changes: 18 additions & 7 deletions src/fheroes2/maps/map_format_helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,17 @@ namespace Maps
{
world.generateForEditor( map.size );

if ( !readAllTiles( map ) ) {
return false;
}

world.updatePassabilities();

return true;
}

bool readAllTiles( const Map_Format::MapFormat & map )
{
assert( static_cast<size_t>( world.w() ) * world.h() == map.tiles.size() );

// We must clear all tiles before writing something on them.
Expand Down Expand Up @@ -90,11 +101,11 @@ namespace Maps

for ( const auto & info : sortedObjects ) {
assert( info.info != nullptr );
readTileObject( world.GetTiles( info.tileIndex ), *info.info );
if ( !readTileObject( world.GetTiles( info.tileIndex ), *info.info ) ) {
return false;
}
}

world.updatePassabilities();

return true;
}

Expand All @@ -120,26 +131,26 @@ namespace Maps
tile.setTerrain( info.terrainIndex, info.terrainFlag & 2, info.terrainFlag & 1 );
}

void readTileObject( Tiles & tile, const Map_Format::ObjectInfo & object )
bool readTileObject( Tiles & tile, const Map_Format::ObjectInfo & object )
{
const auto & objectInfos = getObjectsByGroup( object.group );
if ( object.index >= objectInfos.size() ) {
// This is a bad map format!
assert( 0 );
return;
return false;
}

// Object UID is set through global object UID counter. Therefore, we need to update it before running the operation.
if ( object.id == 0 ) {
// This object UID is not set!
assert( 0 );
return;
return false;
}

setLastObjectUID( object.id - 1 );
// We don't update map passabilities as it is a very expensive process.
// Let's do it once everything is being loaded.
setObjectOnTile( tile, objectInfos[object.index], false );
return setObjectOnTile( tile, objectInfos[object.index], false );
}

void writeTile( const Tiles & tile, Map_Format::TileInfo & info )
Expand Down
3 changes: 2 additions & 1 deletion src/fheroes2/maps/map_format_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,12 @@ namespace Maps
enum class ObjectGroup : int32_t;

bool readMapInEditor( const Map_Format::MapFormat & map );
bool readAllTiles( const Map_Format::MapFormat & map );

bool saveMapInEditor( Map_Format::MapFormat & map );

void readTileTerrain( Tiles & tile, const Map_Format::TileInfo & info );
void readTileObject( Tiles & tile, const Map_Format::ObjectInfo & object );
bool readTileObject( Tiles & tile, const Map_Format::ObjectInfo & object );

void writeTile( const Tiles & tile, Map_Format::TileInfo & info );

Expand Down
Loading

0 comments on commit 04b7efd

Please sign in to comment.