New Unit Type Editor UI in Scenario Editor

This commit is contained in:
Subhraman Sarkar 2024-03-23 10:44:55 +05:30 committed by Pentarctagon
parent 2993757315
commit 0b646dec8a
15 changed files with 2684 additions and 0 deletions

View File

@ -554,6 +554,13 @@
alt=yes
[/hotkey]
[hotkey]
command="editor-edit-unit"
key="u"
alt=yes
shift=yes
[/hotkey]
[hotkey]
command="editor-tool-next"
key="n"

File diff suppressed because it is too large Load Diff

View File

@ -136,6 +136,16 @@
items=editor-assign-local-schedule
[/menu]
[menu]
id=menu-editor-unit
title= _ "Unit"
image=button_menu/menu_button_copper_H20
items=editor-edit-unit
rect="+0,=,+100,="
xanchor=fixed
yanchor=fixed
[/menu]
[menu]
id=menu-editor-side
title= _ "Side"

View File

@ -615,6 +615,8 @@
<Unit filename="../../src/gui/dialogs/editor/edit_scenario.hpp" />
<Unit filename="../../src/gui/dialogs/editor/edit_side.cpp" />
<Unit filename="../../src/gui/dialogs/editor/edit_side.hpp" />
<Unit filename="../../src/gui/dialogs/editor/edit_unit.cpp" />
<Unit filename="../../src/gui/dialogs/editor/edit_unit.hpp" />
<Unit filename="../../src/gui/dialogs/editor/generate_map.cpp" />
<Unit filename="../../src/gui/dialogs/editor/generate_map.hpp" />
<Unit filename="../../src/gui/dialogs/editor/generator_settings.cpp" />

View File

@ -23,6 +23,7 @@
285C4E7A9E891E1DCB215683 /* back_edge_detector.hpp in Headers */ = {isa = PBXBuildFile; fileRef = DA034C90BB2E6C060B0A0B93 /* back_edge_detector.hpp */; };
36B146FAA79A55E9F43723B1 /* general.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84234C54BB84519421FD4136 /* general.cpp */; };
36D74F7F8D7655ACCABE562D /* edit_pbl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6FA542D78393E8FF067775DA /* edit_pbl.cpp */; };
393E4C9DAEE19E12B2B168B5 /* edit_unit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A05D48F0A2C022FC128C8B3E /* edit_unit.cpp */; };
3C254DF5B7DF196F2041955F /* mp_report.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 58C649488B3014E6F7254B62 /* mp_report.cpp */; };
3E9A4297B4A2828C569C8927 /* statistics_record.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27764FB68F02032F1C0B6748 /* statistics_record.cpp */; };
4291489DA38012477DA3BA7C /* general.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84234C54BB84519421FD4136 /* general.cpp */; };
@ -1119,6 +1120,7 @@
95EB8A59287B139800B09F95 /* top_level_drawable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95EB8A54287A02EC00B09F95 /* top_level_drawable.cpp */; };
97714C7A9FF444E29DCEF0BA /* carryover_show_gold.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09A440B1A671C45BE2924FB4 /* carryover_show_gold.cpp */; };
9B4B41D29C90B05F03DE21B0 /* edit_pbl_translation.hpp in Headers */ = {isa = PBXBuildFile; fileRef = C679447D91FD3623CC852FF8 /* edit_pbl_translation.hpp */; };
AC4242F78B39C571E34AF48F /* edit_unit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A05D48F0A2C022FC128C8B3E /* edit_unit.cpp */; };
B508D193100146E300B12852 /* engine_fai.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B508D191100146E300B12852 /* engine_fai.cpp */; };
B513B2290ED36BFB0006E551 /* libcairo.2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B513B2270ED36BFB0006E551 /* libcairo.2.dylib */; };
B52EE8841213585300CFBDAB /* tod_manager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B52EE8821213585300CFBDAB /* tod_manager.cpp */; };
@ -2395,6 +2397,7 @@
95EB8A51287A02B800B09F95 /* draw_manager.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = draw_manager.hpp; sourceTree = "<group>"; };
95EB8A53287A02EC00B09F95 /* top_level_drawable.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = top_level_drawable.hpp; path = gui/core/top_level_drawable.hpp; sourceTree = "<group>"; };
95EB8A54287A02EC00B09F95 /* top_level_drawable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = top_level_drawable.cpp; path = gui/core/top_level_drawable.cpp; sourceTree = "<group>"; };
A05D48F0A2C022FC128C8B3E /* edit_unit.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = edit_unit.cpp; path = edit_unit.cpp; sourceTree = "<group>"; };
B2CC45FEA71445AE817CAA6B /* edit_pbl.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = edit_pbl.hpp; sourceTree = "<group>"; };
B508D191100146E300B12852 /* engine_fai.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = engine_fai.cpp; sourceTree = "<group>"; };
B508D192100146E300B12852 /* engine_fai.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = engine_fai.hpp; sourceTree = "<group>"; };
@ -3941,6 +3944,7 @@
C679447D91FD3623CC852FF8 /* edit_pbl_translation.hpp */,
C61F473D9AC43768A445E218 /* tod_new_schedule.cpp */,
5D46466DBCD81B13621C7342 /* tod_new_schedule.hpp */,
A05D48F0A2C022FC128C8B3E /* edit_unit.cpp */,
);
path = editor;
sourceTree = "<group>";
@ -5901,6 +5905,7 @@
179D4E93A08C5A67B071C6C1 /* spinner.cpp in Sources */,
77D94146A5FA29849D1A9BD8 /* multiline_text.cpp in Sources */,
E1DA41878F0C255769B8239D /* scroll_text.cpp in Sources */,
AC4242F78B39C571E34AF48F /* edit_unit.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -6582,6 +6587,7 @@
D1254FCA82471825B83AA786 /* multiline_text.cpp in Sources */,
E6CF415F9FD04C35A55FB24D /* scroll_text.cpp in Sources */,
62714C2FBE84B66CF14E3722 /* test_sdl.cpp in Sources */,
393E4C9DAEE19E12B2B168B5 /* edit_unit.cpp in Sources */,
529242A8856DE8D00988B9BD /* test_schema_self_validator.cpp in Sources */,
7A7146D7893AA09891352019 /* test_schema_validator.cpp in Sources */,
);

View File

@ -193,6 +193,7 @@ gui/dialogs/editor/edit_pbl.cpp
gui/dialogs/editor/edit_pbl_translation.cpp
gui/dialogs/editor/edit_scenario.cpp
gui/dialogs/editor/edit_side.cpp
gui/dialogs/editor/edit_unit.cpp
gui/dialogs/editor/generate_map.cpp
gui/dialogs/editor/generator_settings.cpp
gui/dialogs/editor/new_map.cpp

View File

@ -30,6 +30,7 @@
#include "preferences/editor.hpp"
#include "gui/dialogs/edit_text.hpp"
#include "gui/dialogs/editor/edit_unit.hpp"
#include "gui/dialogs/editor/custom_tod.hpp"
#include "gui/dialogs/editor/tod_new_schedule.hpp"
#include "gui/dialogs/message.hpp"
@ -219,6 +220,14 @@ bool editor_controller::quit_confirm()
return quit_confirmation::show_prompt(message);
}
void editor_controller::unit_editor_dialog()
{
gui2::dialogs::editor_edit_unit unit_dlg(game_config_, current_addon_id_);
if (unit_dlg.show()) {
unit_dlg.write();
}
}
void editor_controller::custom_tods_dialog()
{
if (tods_.empty()) {
@ -387,6 +396,7 @@ bool editor_controller::can_execute_command(const hotkey::ui_command& cmd) const
return true;
// Only enable when editing a scenario
case HOTKEY_EDITOR_EDIT_UNIT:
case HOTKEY_EDITOR_CUSTOM_TODS:
return !get_current_map_context().is_pure_map();
@ -796,6 +806,9 @@ bool editor_controller::do_execute_command(const hotkey::ui_command& cmd, bool p
do_quit_ = true;
quit_mode_ = EXIT_RELOAD_DATA;
return true;
case HOTKEY_EDITOR_EDIT_UNIT:
unit_editor_dialog();
return true;
case HOTKEY_EDITOR_CUSTOM_TODS:
custom_tods_dialog();
return true;

View File

@ -83,6 +83,9 @@ class editor_controller : public controller_base,
/** Show a quit confirmation dialog and returns true if the user pressed 'yes' */
bool quit_confirm();
/** Show Unit Editor dialog */
void unit_editor_dialog();
/** Display the settings dialog, used to control e.g. the lighting settings */
void custom_tods_dialog();

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,161 @@
/*
Copyright (C) 2023 - 2024
by babaissarkar(Subhraman Sarkar) <suvrax@gmail.com>
Part of the Battle for Wesnoth Project https://www.wesnoth.org/
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#pragma once
#include "gui/dialogs/modal_dialog.hpp"
#include "gui/widgets/group.hpp"
#include "gui/widgets/menu_button.hpp"
#include "serialization/preprocessor.hpp"
#include "game_config_view.hpp"
#include <boost/dynamic_bitset.hpp>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
namespace gui2
{
namespace dialogs
{
/**
* @ingroup GUIWindowDefinitionWML
*
* Dialog that allows user to create custom unit types.
*/
class editor_edit_unit : public modal_dialog
{
public:
editor_edit_unit(const game_config_view& game_config, const std::string& addon_id);
/** The execute function. See @ref modal_dialog for more information. */
DEFINE_SIMPLE_EXECUTE_WRAPPER(editor_edit_unit);
/** Write the cfg file */
void write();
private:
const game_config_view& game_config_;
const std::string& addon_id_;
config type_cfg_;
config resistances_, defenses_, movement_;
preproc_map specials_map_, abilities_map_;
/** Used to control checkboxes, so that only specific values are overridden */
boost::dynamic_bitset<> res_toggles_, def_toggles_, move_toggles_;
std::vector<config> align_list_, race_list_, movetype_list_, defense_list_, resistances_list_, usage_type_list_;
std::vector<config> specials_list_, abilities_list_;
std::vector<std::pair<boost::dynamic_bitset<>, config>> attacks_;
/** Need this because can't store macros in config */
std::vector<std::string> sel_abilities_, sel_specials_;
/** Generated WML */
std::string generated_wml;
/** 0 means there are no attacks. 1 is the first attack, and so on.*/
unsigned int selected_attack_ = 0;
virtual void pre_show(window& window) override;
virtual const std::string& window_id() const override;
/** Load Unit Type data from cfg */
void load_unit_type();
/** Save Unit Type data to cfg */
void save_unit_type();
/** Check if width/height bigger
* than a specified size */
bool check_big(std::string img_abs_path, const int scale_size)
{
SDL_Surface * img_surf = IMG_Load(img_abs_path.c_str());
return (img_surf->w > scale_size) || (img_surf->h > scale_size);
}
/** Write macro to a stream at specified tab level */
void write_macro(std::ostream& out, int level, std::string macro_name);
/** Update wml preview */
void update_wml_view();
/** Callback for loading movetype data in UI */
void load_movetype();
/** Callback for resistance list */
void update_resistances();
void store_resistances();
void enable_resistances_slider();
/** Callbacks for defense list */
void update_defenses();
void store_defenses();
void enable_defense_slider();
/** Callbacks for movement list */
void update_movement_costs();
void store_movement_costs();
void enable_movement_slider();
/** Callbacks for attack page */
void store_attack();
void update_attacks();
void add_attack();
void delete_attack();
void update_index();
void next_attack();
void prev_attack();
void select_attack();
/** Callback when an tab item in the "page" listbox is selected */
void on_page_select();
/** Callback for file select button */
void select_file(const std::string& default_dir, const std::string& id_stem);
/** Callback for image update */
void update_image(const std::string& id_stem);
/** Callback to enable/disable OK button if ID/Name is invalid */
void button_state_change();
void button_state_change_id();
/** Utility method to check if ID contains any invalid characters */
bool check_id(std::string id);
/** Utility method to set state of menu_button from a string */
void set_selected_from_string(menu_button& list, std::vector<config> values, std::string item) {
for (unsigned i = 0; i < values.size(); ++i) {
if(values.at(i)["label"] == item) {
list.set_selected(i);
break;
}
}
}
/* signal handler for Ctrl+O shorcut */
void signal_handler_sdl_key_down(const event::ui_event /*event*/,
bool& handled,
const SDL_Keycode key,
SDL_Keymod modifier);
};
} // namespace dialogs
} // namespace gui2

View File

@ -173,6 +173,8 @@ constexpr std::array<hotkey_command_temp, HOTKEY_NULL - 1> master_hotkey_list {{
{ HOTKEY_EDITOR_MAP_SWITCH, "editor-switch-map", N_("Switch Map"), true, scope_editor, HKCAT_PLACEHOLDER, "" },
{ HOTKEY_EDITOR_LOCAL_TIME, "menu-editor-local-time", N_("Assign Local Time"), true, scope_editor, HKCAT_PLACEHOLDER, "" },
{ HOTKEY_EDITOR_EDIT_UNIT, "editor-edit-unit", N_("New Unit Type"), true, scope_editor, HKCAT_PLACEHOLDER, "" },
{ HOTKEY_EDITOR_CUSTOM_TODS, "editor-custom-tods", N_("Time Schedule Editor"), false, scope_editor, HKCAT_SCENARIO, "" },
{ HOTKEY_EDITOR_PARTIAL_UNDO, "editor-partial-undo", N_("Partial Undo"), false, scope_editor, HKCAT_SCENARIO, "" },
{ HOTKEY_EDITOR_MAP_NEW, "editor-map-new", N_("New Map"), false, scope_editor, HKCAT_SCENARIO, "" },

View File

@ -119,6 +119,7 @@ enum HOTKEY_COMMAND {
/* Editor commands */
HOTKEY_EDITOR_CUSTOM_TODS,
HOTKEY_EDITOR_PARTIAL_UNDO,
HOTKEY_EDITOR_EDIT_UNIT,
// Palette
HOTKEY_EDITOR_PALETTE_ITEM_SWAP, HOTKEY_EDITOR_PALETTE_ITEMS_CLEAR,

View File

@ -56,6 +56,7 @@
#include "gui/dialogs/editor/edit_pbl_translation.hpp"
#include "gui/dialogs/editor/edit_scenario.hpp"
#include "gui/dialogs/editor/edit_side.hpp"
#include "gui/dialogs/editor/edit_unit.hpp"
#include "gui/dialogs/editor/generate_map.hpp"
#include "gui/dialogs/editor/generator_settings.hpp"
#include "gui/dialogs/editor/new_map.hpp"
@ -643,6 +644,11 @@ BOOST_AUTO_TEST_CASE(modal_dialog_test_tod_new_schedule)
test<tod_new_schedule>();
}
BOOST_AUTO_TEST_CASE(modal_dialog_test_editor_edit_unit)
{
test<editor_edit_unit>();
}
// execute last - checks that there aren't any unaccounted for GUIs
BOOST_AUTO_TEST_CASE(test_last)
{
@ -1417,4 +1423,25 @@ struct dialog_tester<tod_new_schedule>
}
};
template<>
struct dialog_tester<editor_edit_unit>
{
config cfg;
game_config_view view;
dialog_tester() {}
editor_edit_unit* create()
{
config& units = cfg.add_child("units");
cfg.add_child("race");
config& movetype = units.add_child("movetype");
movetype["name"] = "Test Movetype";
movetype.add_child("defense");
movetype.add_child("resistance");
movetype.add_child("movement_costs");
view = game_config_view::wrap(cfg);
return new editor_edit_unit(view, "test_addon");
}
};
} // namespace

View File

@ -321,6 +321,7 @@ void unit_type::build_help_index(
// Set the movement type.
const std::string move_type = cfg["movement_type"];
movement_type_id_ = move_type;
const movement_type_map::const_iterator find_it = mv_types.find(move_type);
if(find_it != mv_types.end()) {

View File

@ -185,6 +185,7 @@ public:
const std::string& flag_rgb() const;
const_attack_itors attacks() const;
const std::string movement_type_id() const {return movement_type_id_; }
const movetype & movement_type() const { return movement_type_; }
int experience_needed(bool with_acceleration=true) const;
@ -368,6 +369,7 @@ private:
unit_alignments::type alignment_;
std::string movement_type_id_;
movetype movement_type_;
config possible_traits_;
@ -392,6 +394,7 @@ public:
const unit_type_map &types() const { return types_; }
const race_map &races() const { return races_; }
const movement_type_map &movement_types() const { return movement_types_; }
config_array_view traits() const { return units_cfg().child_range("trait"); }
void set_config(const game_config_view &cfg);