Files
oboe/src/scenedit/scen.undo.cpp

567 lines
14 KiB
C++

#include "scen.undo.hpp"
#include "scenario/scenario.hpp"
#include "scenario/area.hpp"
#include "scen.actions.hpp"
extern bool editing_town;
extern short cur_town;
extern cTown* town;
extern location cur_out;
extern short cen_x;
extern short cen_y;
extern cScenario scenario;
extern cArea* get_current_area();
extern void start_town_edit();
extern void start_out_edit();
extern void redraw_screen();
extern void set_current_town(int,bool first_restore = false);
extern eScenMode overall_mode;
extern eDrawMode draw_mode;
extern void apply_outdoor_shift(rectangle mod);
extern void clamp_current_section();
cTerrainAction::cTerrainAction(std::string name, short town_num, location where, bool reversed) : cAction(name, reversed) {
area.is_town = true;
area.town_num = town_num;
area.where = where;
}
cTerrainAction::cTerrainAction(std::string name, location out_sec, location where, bool reversed) : cAction(name, reversed) {
area.is_town = false;
area.out_sec = out_sec;
area.where = where;
}
cTerrainAction::cTerrainAction(std::string name, location where, bool reversed) : cAction(name, reversed) {
area.is_town = editing_town;
// One of these two will be ignored
area.town_num = cur_town;
area.out_sec = cur_out;
area.where = where;
}
void cTerrainAction::showChangeSite() {
if(area.is_town){
cur_town = area.town_num;
}else{
cur_out = area.out_sec;
}
editing_town = area.is_town;
// TODO this isn't working and I don't know why:
cen_x = area.where.x;
cen_y = area.where.y;
redraw_screen();
}
void cTerrainAction::undo() {
showChangeSite();
cAction::undo();
}
void cTerrainAction::redo() {
showChangeSite();
cAction::redo();
}
// Undo/Redo implementations for actions:
bool aEraseSpecial::undo_me() {
cArea* cur_area = get_current_area();
auto& specials = cur_area->special_locs;
specials.push_back(for_redo);
return true;
}
bool aEraseSpecial::redo_me() {
cArea* cur_area = get_current_area();
auto& specials = cur_area->special_locs;
specials.pop_back();
return true;
}
aCreateDeleteTown::aCreateDeleteTown(bool create, cTown* t)
: cAction(create ? "Create Town" : "Delete Last Town", !create)
, theTown(t)
{}
bool aCreateDeleteTown::undo_me() {
scenario.towns.resize(scenario.towns.size() - 1);
set_current_town(min(cur_town, scenario.towns.size() - 1));
return true;
}
bool aCreateDeleteTown::redo_me() {
scenario.towns.push_back(theTown);
set_current_town(scenario.towns.size() - 1);
return true;
}
// If the town isn't part of the scenario when this action gets discarded,
// delete the object
aCreateDeleteTown::~aCreateDeleteTown() {
if(isDone() == reversed) delete theTown;
}
bool aCreateDeleteTerrain::undo_me() {
// if not in MODE_EDIT_TYPES, show it
if(!(overall_mode == MODE_EDIT_TYPES && draw_mode == DRAW_TERRAIN)){
start_type_editing(DRAW_TERRAIN);
// TODO Go to scroll maximum
}
for(cTerrain ter : terrains){
scenario.ter_types.pop_back();
}
return true;
}
bool aCreateDeleteTerrain::redo_me() {
// if not in MODE_EDIT_TYPES, show it
if(!(overall_mode == MODE_EDIT_TYPES && draw_mode == DRAW_TERRAIN)){
start_type_editing(DRAW_TERRAIN);
// TODO Go to scroll maximum
}
for(cTerrain ter : terrains){
scenario.ter_types.push_back(ter);
}
return true;
}
bool aEditClearTerrain::undo_me() {
// if not in MODE_EDIT_TYPES, show it
if(!(overall_mode == MODE_EDIT_TYPES && draw_mode == DRAW_TERRAIN)){
start_type_editing(DRAW_TERRAIN);
// TODO scroll to show the type
}
scenario.ter_types[which] = before;
return true;
}
bool aEditClearTerrain::redo_me() {
// if not in MODE_EDIT_TYPES, show it
if(!(overall_mode == MODE_EDIT_TYPES && draw_mode == DRAW_TERRAIN)){
start_type_editing(DRAW_TERRAIN);
// TODO scroll to show the type
}
scenario.ter_types[which] = after;
return true;
}
bool aEditClearMonster::undo_me() {
// if not in MODE_EDIT_TYPES, show it
if(!(overall_mode == MODE_EDIT_TYPES && draw_mode == DRAW_MONST)){
start_type_editing(DRAW_MONST);
// TODO scroll to show the type
}
scenario.scen_monsters[which] = before;
return true;
}
bool aEditClearMonster::redo_me() {
// if not in MODE_EDIT_TYPES, show it
if(!(overall_mode == MODE_EDIT_TYPES && draw_mode == DRAW_MONST)){
start_type_editing(DRAW_MONST);
// TODO scroll to show the type
}
scenario.scen_monsters[which] = after;
return true;
}
bool aEditClearItem::undo_me() {
// if not in MODE_EDIT_TYPES, show it
if(!(overall_mode == MODE_EDIT_TYPES && draw_mode == DRAW_ITEM)){
start_type_editing(DRAW_ITEM);
// TODO scroll to show the type
}
scenario.scen_items[which] = before;
return true;
}
bool aEditClearItem::redo_me() {
// if not in MODE_EDIT_TYPES, show it
if(!(overall_mode == MODE_EDIT_TYPES && draw_mode == DRAW_ITEM)){
start_type_editing(DRAW_ITEM);
// TODO scroll to show the type
}
scenario.scen_items[which] = after;
return true;
}
bool aCreateDeleteMonster::undo_me() {
// if not in MODE_EDIT_TYPES, show it
if(!(overall_mode == MODE_EDIT_TYPES && draw_mode == DRAW_MONST)){
start_type_editing(DRAW_MONST);
// TODO Go to scroll maximum
}
for(cMonster monst : monsters){
scenario.scen_monsters.pop_back();
}
return true;
}
bool aCreateDeleteMonster::redo_me() {
// if not in MODE_EDIT_TYPES, show it
if(!(overall_mode == MODE_EDIT_TYPES && draw_mode == DRAW_MONST)){
start_type_editing(DRAW_MONST);
// TODO Go to scroll maximum
}
for(cMonster monst : monsters){
scenario.scen_monsters.push_back(monst);
}
return true;
}
bool aCreateDeleteItem::undo_me() {
// if not in MODE_EDIT_TYPES, show it
if(!(overall_mode == MODE_EDIT_TYPES && draw_mode == DRAW_ITEM)){
start_type_editing(DRAW_ITEM);
// TODO Go to scroll max
}
for(cItem item : items){
scenario.scen_items.pop_back();
}
return true;
}
bool aCreateDeleteItem::redo_me() {
// if not in MODE_EDIT_TYPES, show it
if(!(overall_mode == MODE_EDIT_TYPES && draw_mode == DRAW_ITEM)){
start_type_editing(DRAW_ITEM);
// TODO Go to scroll max
}
for(cItem item : items){
scenario.scen_items.push_back(item);
}
return true;
}
bool aDrawTerrain::undo_me() {
cArea* cur_area = get_current_area();
for(auto change : changes){
cur_area->terrain(change.first.x, change.first.y) = change.second.old_num;
}
return true;
}
bool aDrawTerrain::redo_me() {
cArea* cur_area = get_current_area();
for(auto change : changes){
cur_area->terrain(change.first.x, change.first.y) = change.second.new_num;
}
return true;
}
aPlaceEraseItem::aPlaceEraseItem(std::string name, bool place, size_t index, cTown::cItem item)
: cTerrainAction(name, item.loc, !place)
, items({{index, item}})
{}
aPlaceEraseItem::aPlaceEraseItem(std::string name, bool place, item_changes_t items)
: cTerrainAction(name, items.begin()->second.loc, !place)
, items(items)
{}
bool aPlaceEraseItem::undo_me() {
auto& town_items = scenario.towns[cur_town]->preset_items;
for(auto change : items){
town_items[change.first].code = -1;
}
return true;
}
bool aPlaceEraseItem::redo_me() {
auto& town_items = scenario.towns[cur_town]->preset_items;
for(auto change : items){
town_items[change.first] = change.second;
}
return true;
}
aPlaceEraseCreature::aPlaceEraseCreature(std::string name, bool place, size_t index, cTownperson creature)
: cTerrainAction(name, creature.start_loc, !place)
, creatures({{index, creature}})
{}
aPlaceEraseCreature::aPlaceEraseCreature(std::string name, bool place, creature_changes_t creatures)
: cTerrainAction(name, creatures.begin()->second.start_loc, !place)
, creatures(creatures)
{}
bool aPlaceEraseCreature::undo_me() {
auto& town_creatures = scenario.towns[cur_town]->creatures;
for(auto change : creatures){
town_creatures[change.first].number = 0;
}
return true;
}
bool aPlaceEraseCreature::redo_me() {
auto& town_creatures = scenario.towns[cur_town]->creatures;
for(auto change : creatures){
town_creatures[change.first] = change.second;
}
return true;
}
bool aPlaceEraseVehicle::undo_me() {
auto& all = is_boat ? scenario.boats : scenario.horses;
all[which] = cVehicle();
return true;
}
bool aPlaceEraseVehicle::redo_me() {
auto& all = is_boat ? scenario.boats : scenario.horses;
all[which] = vehicle;
return true;
}
bool aEditVehicle::undo_me() {
auto& all = is_boat ? scenario.boats : scenario.horses;
all[which] = old_vehicle;
return true;
}
bool aEditVehicle::redo_me() {
auto& all = is_boat ? scenario.boats : scenario.horses;
all[which] = new_vehicle;
return true;
}
bool aEditSignText::undo_me() {
cArea* cur_area = get_current_area();
auto& signs = cur_area->sign_locs;
auto iter = std::find(signs.begin(), signs.end(), area.where);
iter->text = old_text;
return true;
}
bool aEditSignText::redo_me() {
cArea* cur_area = get_current_area();
auto& signs = cur_area->sign_locs;
auto iter = std::find(signs.begin(), signs.end(), area.where);
iter->text = new_text;
return true;
}
// cTerrainAction makes sure current_terrain properly references the outdoor section where the edit happened
bool aEditTownEntrance::undo_me() {
set_town_entrance(area.where, old_town);
return true;
}
bool aEditTownEntrance::redo_me() {
set_town_entrance(area.where, new_town);
return true;
}
bool aClearProperty::undo_me() {
for(size_t i = 0; i < town->preset_items.size(); ++i){
town->preset_items[i].property = old_property[i];
}
return true;
}
bool aClearProperty::redo_me() {
for(cTown::cItem& item : town->preset_items){
item.property = false;
}
return true;
}
bool aEditPlacedItem::undo_me() {
town->preset_items[which] = old_item;
return true;
}
bool aEditPlacedItem::redo_me() {
town->preset_items[which] = new_item;
return true;
}
bool aEditPlacedCreature::undo_me() {
town->creatures[which] = old_creature;
return true;
}
bool aEditPlacedCreature::redo_me() {
town->creatures[which] = new_creature;
return true;
}
bool aCreateDeleteSpecialItem::undo_me() {
// If not editing special items, show it
if(overall_mode != MODE_EDIT_SPECIAL_ITEMS){
start_special_item_editing();
// TODO Go to scroll maximum
}
scenario.special_items.pop_back();
return true;
}
bool aCreateDeleteSpecialItem::redo_me() {
// If not editing special items, show it
if(overall_mode != MODE_EDIT_SPECIAL_ITEMS){
start_special_item_editing();
// TODO Go to scroll maximum
}
scenario.special_items.push_back(item);
return true;
}
bool aCreateDeleteQuest::undo_me() {
// If not editing quests, show it
if(overall_mode != MODE_EDIT_QUESTS){
start_quest_editing();
// TODO Go to scroll maximum
}
scenario.quests.pop_back();
return true;
}
bool aCreateDeleteQuest::redo_me() {
// If not editing quests, show it
if(overall_mode != MODE_EDIT_QUESTS){
start_quest_editing();
// TODO Go to scroll maximum
}
scenario.quests.push_back(quest);
return true;
}
bool aCreateDeleteShop::undo_me() {
// If not editing shops, show it
if(overall_mode != MODE_EDIT_SHOPS){
start_shops_editing();
// TODO Go to scroll maximum
}
scenario.shops.pop_back();
return true;
}
bool aCreateDeleteShop::redo_me() {
// If not editing shops, show it
if(overall_mode != MODE_EDIT_SHOPS){
start_shops_editing();
// TODO Go to scroll maximum
}
scenario.shops.push_back(shop);
return true;
}
bool aEditClearSpecialItem::undo_me() {
// If not editing special items, show it
if(overall_mode != MODE_EDIT_SPECIAL_ITEMS){
start_special_item_editing();
// TODO scroll to show the item
}
scenario.special_items[which] = before;
return true;
}
bool aEditClearSpecialItem::redo_me() {
// If not editing special items, show it
if(overall_mode != MODE_EDIT_SPECIAL_ITEMS){
start_special_item_editing();
// TODO scroll to show the item
}
scenario.special_items[which] = after;
return true;
}
bool aEditClearQuest::undo_me() {
// If not editing quests, show it
if(overall_mode != MODE_EDIT_QUESTS){
start_quest_editing();
// TODO scroll to show the quest
}
scenario.quests[which] = before;
return true;
}
bool aEditClearQuest::redo_me() {
// If not editing quests, show it
if(overall_mode != MODE_EDIT_QUESTS){
start_quest_editing();
// TODO scroll to show the quest
}
scenario.quests[which] = after;
return true;
}
bool aEditClearShop::undo_me() {
// If not editing shops, show it
if(overall_mode != MODE_EDIT_SHOPS){
start_shops_editing();
// TODO scroll to show the shop
}
scenario.shops[which] = before;
return true;
}
bool aEditClearShop::redo_me() {
// If not editing shops, show it
if(overall_mode != MODE_EDIT_SHOPS){
start_shops_editing();
// TODO scroll to show the shop
}
scenario.shops[which] = after;
return true;
}
// The action is cleared from the tree, so erase objects it owns
aResizeOutdoors::~aResizeOutdoors() {
// If the resize happened, delete sections it deleted
if(isDone()){
for(auto sec : sections_removed) delete sec.second;
}
// If it was undone, delete sections it created
else{
for(auto sec : sections_added) delete sec.second;
}
}
bool aResizeOutdoors::undo_me() {
rectangle reverse_mod = { -mod.top, -mod.left, -mod.bottom, -mod.right };
apply_outdoor_shift(reverse_mod);
for(auto sec : sections_removed){
scenario.outdoors[sec.first.x][sec.first.y] = sec.second;
}
// Update current location - point to same sector if possible
cur_out.x += reverse_mod.left;
cur_out.y += reverse_mod.top;
clamp_current_section();
return true;
}
bool aResizeOutdoors::redo_me() {
apply_outdoor_shift(mod);
for(auto sec : sections_added){
scenario.outdoors[sec.first.x][sec.first.y] = sec.second;
}
// Update current location - point to same sector if possible
cur_out.x += mod.left;
cur_out.y += mod.top;
clamp_current_section();
return true;
}
// The action is cleared from the tree, so erase objects it owns
aImportTown::~aImportTown() {
// If the import happened, delete the old town
if(isDone()){
delete old_town;
}
// If it was undone, delete the new town
else{
delete new_town;
}
}
bool aImportTown::undo_me() {
scenario.towns[which] = old_town;
set_current_town(which);
return true;
}
bool aImportTown::redo_me() {
scenario.towns[which] = new_town;
set_current_town(which);
return true;
}