From 39ed4eb1f39840e8fc72f070e540bfb7e212370f Mon Sep 17 00:00:00 2001 From: Nat Quayle Nelson Date: Fri, 9 May 2025 11:52:40 -0500 Subject: [PATCH] while running, editor remember view states of towns and outdoors --- src/scenario/scenario.hpp | 16 ++++++ src/scenedit/scen.actions.cpp | 98 +++++++++++++++++++++----------- src/scenedit/scen.actions.hpp | 3 +- src/scenedit/scen.appleevents.mm | 2 +- src/scenedit/scen.main.cpp | 4 +- src/scenedit/scen.townout.cpp | 36 +++++++++++- src/scenedit/scen.townout.hpp | 5 +- 7 files changed, 124 insertions(+), 40 deletions(-) diff --git a/src/scenario/scenario.hpp b/src/scenario/scenario.hpp index 99f4344b..4bcf2e21 100644 --- a/src/scenario/scenario.hpp +++ b/src/scenario/scenario.hpp @@ -46,13 +46,29 @@ struct town_entrance_t { int town; }; +struct terrain_view_t { + location center; + short cur_viewing_mode; +}; + // This is completely unnecessary outside of the scenario editor, but harmless to load anyway, // and much easier to store in cScenario so readScenarioFromXML() doesn't need conditionally compiled // access to scenedit-specific global variables (which won't work unless we want to compile the common // sources 3 times), or globals redeclared for no reason in boe.main.cpp and pc.main.cpp struct editor_state_t { + bool drawing; + bool editing_town; + short last_town_edited; + // Remember last view and zoom for each town + std::map town_view_state; + location last_out_edited; + // Remember last view and zoom for each outdoor section-- + // but only for when the designer makes a discontinuous section change. + // When simply shifting over by 1 section we won't want to + // use this stored state, we want seamless transition. + std::map out_view_state; }; class cScenario { diff --git a/src/scenedit/scen.actions.cpp b/src/scenedit/scen.actions.cpp index 2b2c1e0e..0b375ac1 100644 --- a/src/scenedit/scen.actions.cpp +++ b/src/scenedit/scen.actions.cpp @@ -241,7 +241,7 @@ static bool handle_lb_action(location the_point) { case LB_LOAD_SCEN: file_to_load = nav_get_scenario(); if(!file_to_load.empty() && load_scenario(file_to_load, scenario)) { - restore_editor_state(); + restore_editor_state(true); } else if(!file_to_load.empty()) // If we tried to load but failed, the scenario record is messed up, so boot to start screen. set_up_start_screen(); @@ -279,7 +279,7 @@ static bool handle_lb_action(location the_point) { case LB_LOAD_OUT: spot_hit = pick_out(cur_out, scenario); if(spot_hit != cur_out) { - set_current_out(spot_hit); + set_current_out(spot_hit, false); } break; case LB_EDIT_OUT: @@ -305,6 +305,7 @@ static bool handle_lb_action(location the_point) { } } if((overall_mode < MODE_MAIN_SCREEN) && left_button_status[i].action == LB_RETURN) { + store_current_terrain_state(); set_up_main_screen(); } mouse_button_held = false; @@ -1864,7 +1865,7 @@ static bool handle_outdoor_sec_shift(int dx, int dy){ if(shift_prompt.show() == "yes"){ int last_cen_x = cen_x; int last_cen_y = cen_y; - set_current_out(new_out_sec); + set_current_out(new_out_sec, true); // match the terrain view to where we were start_out_edit(); if(dx < 0) { @@ -1918,7 +1919,7 @@ void handle_editor_screen_shift(int dx, int dy) { shift_prompt->getControl("out-sec").setText(boost::lexical_cast(only_entrance.out_sec)); if(shift_prompt.show() == "yes"){ - set_current_out(only_entrance.out_sec); + set_current_out(only_entrance.out_sec, true); start_out_edit(); cen_x = only_entrance.loc.x; cen_y = only_entrance.loc.y; @@ -1937,7 +1938,7 @@ void handle_editor_screen_shift(int dx, int dy) { size_t choice = dlog.show(-1); if(choice >= 0 && choice < town_entrances.size()){ town_entrance_t entrance = town_entrances[choice]; - set_current_out(entrance.out_sec); + set_current_out(entrance.out_sec, true); start_out_edit(); cen_x = entrance.loc.x; cen_y = entrance.loc.y; @@ -2475,6 +2476,17 @@ void set_up_main_screen() { update_mouse_spot(translate_mouse_coordinates(sf::Mouse::getPosition(mainPtr()))); } +static void restore_current_town_state() { + if(scenario.editor_state.town_view_state.find(cur_town) != scenario.editor_state.town_view_state.end()){ + location cen = scenario.editor_state.town_view_state[cur_town].center; + cen_x = cen.x; + cen_y = cen.y; + cur_viewing_mode = scenario.editor_state.town_view_state[cur_town].cur_viewing_mode; + }else{ + cur_viewing_mode = 0; + } +} + void start_town_edit() { std::ostringstream strb; small_any_drawn = false; @@ -2487,7 +2499,9 @@ void start_town_edit() { set_lb(NLS - 2,LB_TEXT,LB_RETURN,"Back to Main Menu"); set_lb(NLS - 1,LB_TEXT,LB_NO_ACTION,"(Click border to scroll view.)"); overall_mode = MODE_DRAWING; - editing_town = true; + scenario.editor_state.editing_town = editing_town = true; + scenario.editor_state.drawing = true; + restore_current_town_state(); set_up_terrain_buttons(true); shut_down_menus(4); shut_down_menus(2); @@ -2504,6 +2518,20 @@ void start_town_edit() { update_mouse_spot(translate_mouse_coordinates(sf::Mouse::getPosition(mainPtr()))); } +bool last_shift_continuous = false; + +static void restore_current_out_state() { + // Restore the last view state of the new outdoor section UNLESS we shifted to it continuously + if(!last_shift_continuous && scenario.editor_state.out_view_state.find(cur_out) != scenario.editor_state.out_view_state.end()){ + location cen = scenario.editor_state.out_view_state[cur_out].center; + cen_x = cen.x; + cen_y = cen.y; + cur_viewing_mode = scenario.editor_state.out_view_state[cur_out].cur_viewing_mode; + }else{ + cur_viewing_mode = 0; + } +} + void start_out_edit() { std::ostringstream strb; small_any_drawn = false; @@ -2517,7 +2545,9 @@ void start_out_edit() { set_lb(NLS - 1,LB_TEXT,LB_NO_ACTION,"(Click border to scroll view.)"); overall_mode = MODE_DRAWING; draw_mode = DRAW_TERRAIN; - editing_town = false; + scenario.editor_state.editing_town = editing_town = false; + scenario.editor_state.drawing = true; + restore_current_out_state(); set_up_terrain_buttons(true); right_sbar->hide(); pal_sbar->show(); @@ -2551,7 +2581,7 @@ void start_monster_editing(bool just_redo_text) { int num_options = scenario.scen_monsters.size() + 1; if(!just_redo_text) { - overall_mode = MODE_MAIN_SCREEN; + handle_close_terrain_view(MODE_MAIN_SCREEN); right_sbar->show(); pal_sbar->hide(); right_sbar->setPosition(0); @@ -2576,9 +2606,7 @@ void start_item_editing(bool just_redo_text) { int num_options = scenario.scen_items.size() + 1; if(!just_redo_text) { - if(overall_mode < MODE_MAIN_SCREEN) - set_up_main_screen(); - overall_mode = MODE_MAIN_SCREEN; + handle_close_terrain_view(MODE_MAIN_SCREEN); right_sbar->show(); pal_sbar->hide(); @@ -2603,9 +2631,7 @@ void start_special_item_editing(bool just_redo_text) { int num_options = scenario.special_items.size() + 1; if(!just_redo_text) { - if(overall_mode < MODE_MAIN_SCREEN) - set_up_main_screen(); - overall_mode = MODE_MAIN_SCREEN; + handle_close_terrain_view(MODE_MAIN_SCREEN); right_sbar->show(); pal_sbar->hide(); @@ -2629,9 +2655,7 @@ void start_special_item_editing(bool just_redo_text) { void start_quest_editing(bool just_redo_text) { int num_options = scenario.quests.size() + 1; if(!just_redo_text) { - if(overall_mode < MODE_MAIN_SCREEN) - set_up_main_screen(); - overall_mode = MODE_MAIN_SCREEN; + handle_close_terrain_view(MODE_MAIN_SCREEN); right_sbar->show(); pal_sbar->hide(); right_sbar->setPosition(0); @@ -2654,9 +2678,7 @@ void start_quest_editing(bool just_redo_text) { void start_shops_editing(bool just_redo_text) { int num_options = scenario.shops.size() + 1; if(!just_redo_text) { - if(overall_mode < MODE_MAIN_SCREEN) - set_up_main_screen(); - overall_mode = MODE_MAIN_SCREEN; + handle_close_terrain_view(MODE_MAIN_SCREEN); right_sbar->show(); pal_sbar->hide(); right_sbar->setPosition(0); @@ -2682,9 +2704,7 @@ extern size_t num_strs(short mode); // defined in scen.keydlgs.cpp // if just_redo_text not 0, simply need to update text portions void start_string_editing(eStrMode mode,short just_redo_text) { if(just_redo_text == 0) { - if(overall_mode < MODE_MAIN_SCREEN) - set_up_main_screen(); - overall_mode = MODE_MAIN_SCREEN; + handle_close_terrain_view(MODE_MAIN_SCREEN); right_sbar->show(); pal_sbar->hide(); @@ -2760,9 +2780,7 @@ void start_special_editing(short mode,short just_redo_text) { } if(just_redo_text == 0) { - if(overall_mode < MODE_MAIN_SCREEN) - set_up_main_screen(); - overall_mode = MODE_MAIN_SCREEN; + handle_close_terrain_view(MODE_MAIN_SCREEN); right_sbar->show(); pal_sbar->hide(); @@ -2802,9 +2820,7 @@ void start_special_editing(short mode,short just_redo_text) { void start_dialogue_editing(short restoring) { char s[15] = " , "; - if(overall_mode < MODE_MAIN_SCREEN) - set_up_main_screen(); - overall_mode = MODE_MAIN_SCREEN; + handle_close_terrain_view(MODE_MAIN_SCREEN); right_sbar->show(); pal_sbar->hide(); @@ -2881,7 +2897,25 @@ bool monst_on_space(location loc,short m_num) { } -void restore_editor_state() { - set_current_town(scenario.editor_state.last_town_edited); - set_current_out(scenario.editor_state.last_out_edited); +void restore_editor_state(bool first_time) { + set_current_town(scenario.editor_state.last_town_edited, first_time); + set_current_out(scenario.editor_state.last_out_edited, false, first_time); + if(first_time && scenario.editor_state.drawing){ + if(scenario.editor_state.editing_town) + start_town_edit(); + else + start_out_edit(); + } +} + +void handle_close_terrain_view(eScenMode new_mode) { + // When closing a terrain view, store its view state + store_current_terrain_state(); + scenario.editor_state.drawing = false; + + // set up the main screen if needed + if(new_mode == MODE_MAIN_SCREEN && overall_mode < MODE_MAIN_SCREEN) + set_up_main_screen(); + + overall_mode = new_mode; } \ No newline at end of file diff --git a/src/scenedit/scen.actions.hpp b/src/scenedit/scen.actions.hpp index 94165790..f3b3487b 100644 --- a/src/scenedit/scen.actions.hpp +++ b/src/scenedit/scen.actions.hpp @@ -2,7 +2,8 @@ #include "scen.global.hpp" #include "tools/undo.hpp" -void restore_editor_state(); +void handle_close_terrain_view(eScenMode new_mode); +void restore_editor_state(bool first_time = false); void init_screen_locs(); void handle_action(location the_point,sf::Event event); void flash_rect(rectangle to_flash); diff --git a/src/scenedit/scen.appleevents.mm b/src/scenedit/scen.appleevents.mm index 1970d2ca..e87dfe48 100644 --- a/src/scenedit/scen.appleevents.mm +++ b/src/scenedit/scen.appleevents.mm @@ -51,7 +51,7 @@ void set_up_apple_events() { std::copy(msg.get(), msg.get() + len, std::inserter(fileName, fileName.begin())); if(load_scenario(fileName, scenario)) { - restore_editor_state(); + restore_editor_state(true); change_made = false; ae_loading = true; } diff --git a/src/scenedit/scen.main.cpp b/src/scenedit/scen.main.cpp index 6bfcd8c5..082ba895 100644 --- a/src/scenedit/scen.main.cpp +++ b/src/scenedit/scen.main.cpp @@ -301,7 +301,7 @@ static void process_args(int argc, char* argv[]) { } if(!file.empty()) { if(load_scenario(file, scenario)) { - restore_editor_state(); + restore_editor_state(true); change_made = false; ae_loading = true; } else { @@ -448,7 +448,7 @@ void handle_menu_choice(eMenu item_hit) { break; file_to_load = item_hit == eMenu::FILE_OPEN ? nav_get_scenario() : scenario.scen_file; if(!file_to_load.empty() && load_scenario(file_to_load, scenario)) { - restore_editor_state(); + restore_editor_state(true); change_made = false; } else if(!file_to_load.empty()) set_up_start_screen(); // Failed to load file, dump to start diff --git a/src/scenedit/scen.townout.cpp b/src/scenedit/scen.townout.cpp index 211c4824..591628bc 100644 --- a/src/scenedit/scen.townout.cpp +++ b/src/scenedit/scen.townout.cpp @@ -44,6 +44,8 @@ extern cOutdoors* current_terrain; extern location cur_out; extern cUndoList undo_list; extern std::string help_text_rsrc; +extern bool editing_town; +extern bool last_shift_continuous; const char *day_str_1[] = {"Unused","Day creature appears","Day creature disappears", "Unused","Unused","Unused","Unused","Unused","Unused"}; @@ -1525,17 +1527,47 @@ location pick_out(location default_loc,cScenario& scenario) { return default_loc; } -void set_current_town(int to) { +static void store_current_town_state() { + scenario.editor_state.town_view_state[cur_town] = { + {cen_x, cen_y}, cur_viewing_mode + }; +} + +static void store_current_out_state() { + scenario.editor_state.out_view_state[cur_out] = { + {cen_x, cen_y}, cur_viewing_mode + }; +} + +void store_current_terrain_state() { + if(overall_mode < MODE_MAIN_SCREEN){ + if(editing_town){ + store_current_town_state(); + }else{ + store_current_out_state(); + } + } +} + +void set_current_town(int to, bool first_restore) { + if(!first_restore){ + store_current_terrain_state(); + } + if(to < 0 || to >= scenario.towns.size()) return; cur_town = to; town = scenario.towns[cur_town]; scenario.editor_state.last_town_edited = cur_town; } -void set_current_out(location out_sec) { +void set_current_out(location out_sec, bool continuous_shift, bool first_restore) { + if(!first_restore){ + store_current_terrain_state(); + } cur_out = out_sec; scenario.editor_state.last_out_edited = cur_out; current_terrain = scenario.outdoors[cur_out.x][cur_out.y]; + last_shift_continuous = continuous_shift; set_up_main_screen(); } diff --git a/src/scenedit/scen.townout.hpp b/src/scenedit/scen.townout.hpp index e3f89fce..d76c6879 100644 --- a/src/scenedit/scen.townout.hpp +++ b/src/scenedit/scen.townout.hpp @@ -22,5 +22,6 @@ void edit_placed_item(short which_i); void delete_last_town(); void edit_town_wand(); -void set_current_town(int to); -void set_current_out(location out_sec); +void set_current_town(int to, bool first_restore = false); +void set_current_out(location out_sec, bool continuous_shift, bool first_restore = false); +void store_current_terrain_state();