2025-05-02 00:46:20 -07:00
/* Copyright (C) 2025 Wildfire Games.
2023-12-02 16:30:12 -08:00
* This file is part of 0 A . D .
2011-05-27 14:56:43 -07:00
*
2023-12-02 16:30:12 -08:00
* 0 A . D . is free software : you can redistribute it and / or modify
2011-05-27 14:56:43 -07:00
* 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 .
*
2023-12-02 16:30:12 -08:00
* 0 A . D . is distributed in the hope that it will be useful ,
2011-05-27 14:56:43 -07:00
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
2023-12-02 16:30:12 -08:00
* along with 0 A . D . If not , see < http : //www.gnu.org/licenses/>.
2011-05-27 14:56:43 -07:00
*/
# include "precompiled.h"
2011-05-27 14:48:23 -07:00
# include "Map.h"
2025-08-09 03:01:01 -07:00
# include "tools/atlas/AtlasObject/AtlasObject.h"
# include "tools/atlas/AtlasUI/CustomControls/MapResizeDialog/MapResizeDialog.h"
# include "tools/atlas/AtlasUI/General/AtlasWindowCommandProc.h"
# include "tools/atlas/AtlasUI/General/Observable.h"
# include "tools/atlas/AtlasUI/ScenarioEditor/ScenarioEditor.h"
# include "tools/atlas/AtlasUI/ScenarioEditor/Sections/Common/Sidebar.h"
# include "tools/atlas/AtlasUI/ScenarioEditor/Tools/Common/Tools.h"
# include "tools/atlas/GameInterface/MessagePasser.h"
# include "tools/atlas/GameInterface/Messages.h"
# include "tools/atlas/GameInterface/Shareable.h"
2011-05-27 14:48:23 -07:00
2020-07-24 11:53:03 -07:00
# include <algorithm>
2025-08-09 03:01:01 -07:00
# include <cstdint>
2022-01-02 14:35:17 -08:00
# include <ctime>
2025-08-09 03:01:01 -07:00
# include <list>
# include <map>
2022-01-02 14:35:17 -08:00
# include <random>
2025-08-09 03:01:01 -07:00
# include <set>
2024-09-21 04:45:48 -07:00
# include <string>
2025-08-09 03:01:01 -07:00
# include <utility>
2024-09-21 04:45:48 -07:00
# include <vector>
2025-08-09 03:01:01 -07:00
# include <wx/busyinfo.h>
# include <wx/button.h>
# include <wx/chartype.h>
# include <wx/checkbox.h>
# include <wx/choice.h>
# include <wx/clntdata.h>
# include <wx/collpane.h>
# include <wx/debug.h>
# include <wx/gdicmn.h>
# include <wx/log.h>
# include <wx/object.h>
# include <wx/panel.h>
# include <wx/scrolwin.h>
# include <wx/sizer.h>
2025-08-17 10:56:35 -07:00
# include <wx/statbox.h>
2025-08-09 03:01:01 -07:00
# include <wx/stattext.h>
# include <wx/string.h>
# include <wx/textctrl.h>
# include <wx/toolbar.h>
# include <wx/translation.h>
# include <wx/utils.h>
# include <wx/valtext.h>
# include <wx/window.h>
# include <wx/wxcrt.h>
2011-05-27 14:48:23 -07:00
2018-02-24 12:19:59 -08:00
# define CREATE_CHECKBOX(window, parentSizer, name, description, ID) \
parentSizer - > Add ( new wxStaticText ( window , wxID_ANY , _ ( name ) ) , wxSizerFlags ( ) . Align ( wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT ) ) ; \
parentSizer - > Add ( Tooltipped ( new wxCheckBox ( window , ID , wxEmptyString ) , _ ( description ) ) ) ;
2018-02-23 12:47:46 -08:00
2011-05-27 14:48:23 -07:00
enum
{
2011-05-29 08:02:02 -07:00
ID_MapName ,
ID_MapDescription ,
ID_MapReveal ,
2021-08-27 23:15:36 -07:00
ID_MapAlly ,
2011-05-29 08:02:02 -07:00
ID_MapType ,
Implements skirmish maps, based on patch by sanderd17, fixes #1198. Skirmish maps are like scenarios, except the player can choose their civ during match setup. To create a skirmish map: place some skirmish entities for each player in Atlas (see templates/skirmish/* for examples), uncheck the player's civ in Atlas' player panel if desired, and save in the maps/skirmishes directory. The map will appear in match setup under the "Skirmish" match type.
Implements custom, VFS-based map load/save dialogs for Atlas (replaces
broken native file dialogs), fixes #631, #889.
Fixes map loading/saving to handle arbitrary subdirectories for better
organization.
Adds default settings to Atlas player panel, fixes #1872. Each setting
now has a checkbox to choose whether it should be saved with the map
(avoids writing lots of useless default data for each map).
Adds map preview setting to Atlas, refs #1745.
Cleans up and simplifies some duplicate code.
Fixes optional serialization performance test.
This was SVN commit r13938.
2013-10-03 19:29:16 -07:00
ID_MapPreview ,
2011-06-09 16:45:12 -07:00
ID_MapTeams ,
2011-05-29 08:02:02 -07:00
ID_MapKW_Demo ,
Implements skirmish maps, based on patch by sanderd17, fixes #1198. Skirmish maps are like scenarios, except the player can choose their civ during match setup. To create a skirmish map: place some skirmish entities for each player in Atlas (see templates/skirmish/* for examples), uncheck the player's civ in Atlas' player panel if desired, and save in the maps/skirmishes directory. The map will appear in match setup under the "Skirmish" match type.
Implements custom, VFS-based map load/save dialogs for Atlas (replaces
broken native file dialogs), fixes #631, #889.
Fixes map loading/saving to handle arbitrary subdirectories for better
organization.
Adds default settings to Atlas player panel, fixes #1872. Each setting
now has a checkbox to choose whether it should be saved with the map
(avoids writing lots of useless default data for each map).
Adds map preview setting to Atlas, refs #1745.
Cleans up and simplifies some duplicate code.
Fixes optional serialization performance test.
This was SVN commit r13938.
2013-10-03 19:29:16 -07:00
ID_MapKW_Naval ,
2019-06-24 22:05:06 -07:00
ID_MapKW_New ,
ID_MapKW_Trigger ,
2011-05-29 08:02:02 -07:00
ID_RandomScript ,
ID_RandomSize ,
2024-09-21 04:45:48 -07:00
ID_RandomBiome ,
2018-02-19 14:30:09 -08:00
ID_RandomNomad ,
2011-05-29 08:02:02 -07:00
ID_RandomSeed ,
ID_RandomReseed ,
ID_RandomGenerate ,
2020-07-20 19:08:50 -07:00
ID_ResizeMap ,
2011-05-27 14:48:23 -07:00
ID_SimPlay ,
ID_SimFast ,
ID_SimSlow ,
ID_SimPause ,
2011-06-23 15:38:26 -07:00
ID_SimReset ,
2024-10-06 16:11:30 -07:00
ID_PlayerPlacement ,
2011-06-23 15:38:26 -07:00
ID_OpenPlayerPanel
2011-05-27 14:48:23 -07:00
} ;
enum
{
SimInactive ,
SimPlaying ,
SimPlayingFast ,
SimPlayingSlow ,
SimPaused
} ;
2011-06-09 16:45:12 -07:00
2011-05-27 14:48:23 -07:00
bool IsPlaying ( int s ) { return ( s = = SimPlaying | | s = = SimPlayingFast | | s = = SimPlayingSlow ) ; }
2011-06-09 16:45:12 -07:00
// TODO: Some of these helper things should be moved out of this file
// and into shared locations
2011-05-29 08:02:02 -07:00
// Helper function for adding tooltips
static wxWindow * Tooltipped ( wxWindow * window , const wxString & tip )
{
window - > SetToolTip ( tip ) ;
return window ;
}
// Helper class for storing AtObjs
class AtObjClientData : public wxClientData
{
public :
AtObjClientData ( const AtObj & obj ) : obj ( obj ) { }
virtual ~ AtObjClientData ( ) { }
AtObj GetValue ( ) { return obj ; }
private :
AtObj obj ;
} ;
2011-06-09 16:45:12 -07:00
class MapSettingsControl : public wxPanel
2011-05-29 08:02:02 -07:00
{
public :
2011-06-09 16:45:12 -07:00
MapSettingsControl ( wxWindow * parent , ScenarioEditor & scenarioEditor ) ;
2011-05-29 08:02:02 -07:00
void CreateWidgets ( ) ;
void ReadFromEngine ( ) ;
2012-05-10 16:11:42 -07:00
void SetMapSettings ( const AtObj & obj ) ;
2011-05-29 08:02:02 -07:00
AtObj UpdateSettingsObject ( ) ;
private :
void SendToEngine ( ) ;
2020-07-18 10:39:59 -07:00
void OnVictoryConditionChanged ( long controlId ) ;
2011-05-29 08:02:02 -07:00
2018-03-09 13:51:18 -08:00
void OnEdit ( wxCommandEvent & evt )
2011-05-29 08:02:02 -07:00
{
2020-07-24 11:53:03 -07:00
long id = static_cast < long > ( evt . GetId ( ) ) ;
if ( std : : any_of ( m_VictoryConditions . begin ( ) , m_VictoryConditions . end ( ) , [ id ] ( const std : : pair < long , AtObj > & vc ) {
return vc . first = = id ;
} ) )
OnVictoryConditionChanged ( id ) ;
2011-05-29 08:02:02 -07:00
SendToEngine ( ) ;
}
2020-07-18 10:39:59 -07:00
std : : map < long , AtObj > m_VictoryConditions ;
2019-06-03 13:19:53 -07:00
std : : set < std : : string > m_MapSettingsKeywords ;
std : : set < std : : string > m_MapSettingsVictoryConditions ;
2011-05-29 08:02:02 -07:00
std : : vector < wxChoice * > m_PlayerCivChoices ;
2011-06-09 16:45:12 -07:00
Observable < AtObj > & m_MapSettings ;
2011-05-29 08:02:02 -07:00
DECLARE_EVENT_TABLE ( ) ;
} ;
2011-06-09 16:45:12 -07:00
BEGIN_EVENT_TABLE ( MapSettingsControl , wxPanel )
EVT_TEXT ( ID_MapName , MapSettingsControl : : OnEdit )
EVT_TEXT ( ID_MapDescription , MapSettingsControl : : OnEdit )
Implements skirmish maps, based on patch by sanderd17, fixes #1198. Skirmish maps are like scenarios, except the player can choose their civ during match setup. To create a skirmish map: place some skirmish entities for each player in Atlas (see templates/skirmish/* for examples), uncheck the player's civ in Atlas' player panel if desired, and save in the maps/skirmishes directory. The map will appear in match setup under the "Skirmish" match type.
Implements custom, VFS-based map load/save dialogs for Atlas (replaces
broken native file dialogs), fixes #631, #889.
Fixes map loading/saving to handle arbitrary subdirectories for better
organization.
Adds default settings to Atlas player panel, fixes #1872. Each setting
now has a checkbox to choose whether it should be saved with the map
(avoids writing lots of useless default data for each map).
Adds map preview setting to Atlas, refs #1745.
Cleans up and simplifies some duplicate code.
Fixes optional serialization performance test.
This was SVN commit r13938.
2013-10-03 19:29:16 -07:00
EVT_TEXT ( ID_MapPreview , MapSettingsControl : : OnEdit )
2011-06-09 16:45:12 -07:00
EVT_CHECKBOX ( wxID_ANY , MapSettingsControl : : OnEdit )
EVT_CHOICE ( wxID_ANY , MapSettingsControl : : OnEdit )
2011-05-29 08:02:02 -07:00
END_EVENT_TABLE ( ) ;
2011-06-09 16:45:12 -07:00
MapSettingsControl : : MapSettingsControl ( wxWindow * parent , ScenarioEditor & scenarioEditor )
2014-09-13 12:34:04 -07:00
: wxPanel ( parent , wxID_ANY ) , m_MapSettings ( scenarioEditor . GetMapSettings ( ) )
2011-05-29 08:02:02 -07:00
{
wxStaticBoxSizer * sizer = new wxStaticBoxSizer ( wxVERTICAL , this , _ ( " Map settings " ) ) ;
SetSizer ( sizer ) ;
}
2011-06-09 16:45:12 -07:00
void MapSettingsControl : : CreateWidgets ( )
2011-05-29 08:02:02 -07:00
{
2025-08-17 10:56:35 -07:00
wxStaticBoxSizer * sizer = static_cast < wxStaticBoxSizer * > ( GetSizer ( ) ) ;
2011-05-29 08:02:02 -07:00
2011-06-23 15:38:26 -07:00
/////////////////////////////////////////////////////////////////////////
// Map settings
2011-05-29 08:02:02 -07:00
wxBoxSizer * nameSizer = new wxBoxSizer ( wxHORIZONTAL ) ;
2025-08-17 10:56:35 -07:00
nameSizer - > Add ( new wxStaticText ( sizer - > GetStaticBox ( ) , wxID_ANY , _ ( " Name " ) ) , wxSizerFlags ( ) . Align ( wxALIGN_CENTER_VERTICAL ) ) ;
2011-05-29 08:02:02 -07:00
nameSizer - > Add ( 8 , 0 ) ;
2025-08-17 10:56:35 -07:00
nameSizer - > Add ( Tooltipped ( new wxTextCtrl ( sizer - > GetStaticBox ( ) , ID_MapName ) ,
2011-05-29 08:02:02 -07:00
_ ( " Displayed name of the map " ) ) , wxSizerFlags ( ) . Proportion ( 1 ) ) ;
sizer - > Add ( nameSizer , wxSizerFlags ( ) . Expand ( ) ) ;
sizer - > Add ( 0 , 2 ) ;
2025-08-17 10:56:35 -07:00
sizer - > Add ( new wxStaticText ( sizer - > GetStaticBox ( ) , wxID_ANY , _ ( " Description " ) ) ) ;
sizer - > Add ( Tooltipped ( new wxTextCtrl ( sizer - > GetStaticBox ( ) , ID_MapDescription , wxEmptyString , wxDefaultPosition , wxSize ( - 1 , 100 ) , wxTE_MULTILINE ) ,
2011-05-29 08:02:02 -07:00
_ ( " Short description used on the map selection screen " ) ) , wxSizerFlags ( ) . Expand ( ) ) ;
2011-06-09 16:45:12 -07:00
sizer - > AddSpacer ( 5 ) ;
2011-08-18 16:38:11 -07:00
wxFlexGridSizer * gridSizer = new wxFlexGridSizer ( 2 , 5 , 5 ) ;
2011-08-22 14:45:39 -07:00
gridSizer - > AddGrowableCol ( 1 ) ;
2018-03-09 13:51:18 -08:00
Implements skirmish maps, based on patch by sanderd17, fixes #1198. Skirmish maps are like scenarios, except the player can choose their civ during match setup. To create a skirmish map: place some skirmish entities for each player in Atlas (see templates/skirmish/* for examples), uncheck the player's civ in Atlas' player panel if desired, and save in the maps/skirmishes directory. The map will appear in match setup under the "Skirmish" match type.
Implements custom, VFS-based map load/save dialogs for Atlas (replaces
broken native file dialogs), fixes #631, #889.
Fixes map loading/saving to handle arbitrary subdirectories for better
organization.
Adds default settings to Atlas player panel, fixes #1872. Each setting
now has a checkbox to choose whether it should be saved with the map
(avoids writing lots of useless default data for each map).
Adds map preview setting to Atlas, refs #1745.
Cleans up and simplifies some duplicate code.
Fixes optional serialization performance test.
This was SVN commit r13938.
2013-10-03 19:29:16 -07:00
// TODO: have preview selector tool?
2025-08-17 10:56:35 -07:00
gridSizer - > Add ( new wxStaticText ( sizer - > GetStaticBox ( ) , wxID_ANY , _ ( " Preview " ) ) , wxSizerFlags ( ) . Align ( wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT ) ) ;
gridSizer - > Add ( Tooltipped ( new wxTextCtrl ( sizer - > GetStaticBox ( ) , ID_MapPreview , wxEmptyString ) ,
Implements skirmish maps, based on patch by sanderd17, fixes #1198. Skirmish maps are like scenarios, except the player can choose their civ during match setup. To create a skirmish map: place some skirmish entities for each player in Atlas (see templates/skirmish/* for examples), uncheck the player's civ in Atlas' player panel if desired, and save in the maps/skirmishes directory. The map will appear in match setup under the "Skirmish" match type.
Implements custom, VFS-based map load/save dialogs for Atlas (replaces
broken native file dialogs), fixes #631, #889.
Fixes map loading/saving to handle arbitrary subdirectories for better
organization.
Adds default settings to Atlas player panel, fixes #1872. Each setting
now has a checkbox to choose whether it should be saved with the map
(avoids writing lots of useless default data for each map).
Adds map preview setting to Atlas, refs #1745.
Cleans up and simplifies some duplicate code.
Fixes optional serialization performance test.
This was SVN commit r13938.
2013-10-03 19:29:16 -07:00
_ ( " Texture used for map preview " ) ) , wxSizerFlags ( ) . Expand ( ) ) ;
2025-08-17 10:56:35 -07:00
CREATE_CHECKBOX ( sizer - > GetStaticBox ( ) , gridSizer , " Reveal map " , " If checked, players won't need to explore " , ID_MapReveal ) ;
CREATE_CHECKBOX ( sizer - > GetStaticBox ( ) , gridSizer , " Ally view " , " If checked, players will be able to see what their teammates see and won't need to research cartography " , ID_MapAlly ) ;
CREATE_CHECKBOX ( sizer - > GetStaticBox ( ) , gridSizer , " Lock teams " , " If checked, teams will be locked " , ID_MapTeams ) ;
2011-08-22 14:45:39 -07:00
sizer - > Add ( gridSizer , wxSizerFlags ( ) . Expand ( ) ) ;
2011-05-29 08:02:02 -07:00
2011-06-09 16:45:12 -07:00
sizer - > AddSpacer ( 5 ) ;
2011-05-29 08:02:02 -07:00
2018-03-09 13:51:18 -08:00
wxStaticBoxSizer * victoryConditionSizer = new wxStaticBoxSizer ( wxVERTICAL , this , _ ( " Victory Conditions " ) ) ;
wxFlexGridSizer * vcGridSizer = new wxFlexGridSizer ( 2 , 0 , 5 ) ;
vcGridSizer - > AddGrowableCol ( 1 ) ;
2020-07-18 10:39:59 -07:00
AtlasMessage : : qGetVictoryConditionData qryVictoryCondition ;
qryVictoryCondition . Post ( ) ;
std : : vector < std : : string > victoryConditionData = * qryVictoryCondition . data ;
for ( const std : : string & victoryConditionJson : victoryConditionData )
{
AtObj victoryCondition = AtlasObject : : LoadFromJSON ( victoryConditionJson ) ;
long index = wxWindow : : NewControlId ( ) ;
wxString title = wxString : : FromUTF8 ( victoryCondition [ " Data " ] [ " Title " ] ) ;
2021-06-29 05:41:31 -07:00
std : : string escapedTitle = title . Lower ( ) . ToStdString ( ) ;
2020-09-20 02:33:18 -07:00
std : : replace ( escapedTitle . begin ( ) , escapedTitle . end ( ) , ' ' , ' _ ' ) ;
AtObj updateCondition = * ( victoryCondition [ " Data " ] [ " Title " ] ) ;
updateCondition . setString ( escapedTitle . c_str ( ) ) ;
2020-07-18 10:39:59 -07:00
m_VictoryConditions . insert ( std : : pair < long , AtObj > ( index , victoryCondition ) ) ;
2025-08-17 10:56:35 -07:00
CREATE_CHECKBOX ( victoryConditionSizer - > GetStaticBox ( ) , vcGridSizer , title , " Select " + title + " victory condition. " , index ) ;
2020-07-18 10:39:59 -07:00
}
2018-03-09 13:51:18 -08:00
victoryConditionSizer - > Add ( vcGridSizer ) ;
sizer - > Add ( victoryConditionSizer , wxSizerFlags ( ) . Expand ( ) ) ;
sizer - > AddSpacer ( 5 ) ;
2011-05-29 08:02:02 -07:00
wxStaticBoxSizer * keywordsSizer = new wxStaticBoxSizer ( wxVERTICAL , this , _ ( " Keywords " ) ) ;
2019-06-24 22:05:06 -07:00
wxFlexGridSizer * kwGridSizer = new wxFlexGridSizer ( 4 , 5 , 15 ) ;
2025-08-17 10:56:35 -07:00
CREATE_CHECKBOX ( keywordsSizer - > GetStaticBox ( ) , kwGridSizer , " Demo " , " If checked, map will only be visible using filters in game setup " , ID_MapKW_Demo ) ;
CREATE_CHECKBOX ( keywordsSizer - > GetStaticBox ( ) , kwGridSizer , " Naval " , " If checked, map will only be visible using filters in game setup " , ID_MapKW_Naval ) ;
CREATE_CHECKBOX ( keywordsSizer - > GetStaticBox ( ) , kwGridSizer , " New " , " If checked, the map will appear in the list of new maps " , ID_MapKW_New ) ;
CREATE_CHECKBOX ( keywordsSizer - > GetStaticBox ( ) , kwGridSizer , " Trigger " , " If checked, the map will appear in the list of maps with trigger scripts " , ID_MapKW_Trigger ) ;
2019-06-24 22:05:06 -07:00
2011-05-29 08:02:02 -07:00
keywordsSizer - > Add ( kwGridSizer ) ;
sizer - > Add ( keywordsSizer , wxSizerFlags ( ) . Expand ( ) ) ;
}
2011-06-09 16:45:12 -07:00
void MapSettingsControl : : ReadFromEngine ( )
2011-05-29 08:02:02 -07:00
{
AtlasMessage : : qGetMapSettings qry ;
qry . Post ( ) ;
2011-06-09 16:45:12 -07:00
if ( ! ( * qry . settings ) . empty ( ) )
{
// Prevent error if there's no map settings to parse
2014-02-24 12:22:02 -08:00
m_MapSettings = AtlasObject : : LoadFromJSON ( * qry . settings ) ;
2011-06-09 16:45:12 -07:00
}
2011-05-29 08:02:02 -07:00
2011-06-23 15:38:26 -07:00
// map name
2019-06-03 13:19:53 -07:00
wxDynamicCast ( FindWindow ( ID_MapName ) , wxTextCtrl ) - > ChangeValue ( wxString : : FromUTF8 ( m_MapSettings [ " Name " ] ) ) ;
2011-05-29 08:02:02 -07:00
2011-06-23 15:38:26 -07:00
// map description
2019-06-03 13:19:53 -07:00
wxDynamicCast ( FindWindow ( ID_MapDescription ) , wxTextCtrl ) - > ChangeValue ( wxString : : FromUTF8 ( m_MapSettings [ " Description " ] ) ) ;
2011-05-29 08:02:02 -07:00
Implements skirmish maps, based on patch by sanderd17, fixes #1198. Skirmish maps are like scenarios, except the player can choose their civ during match setup. To create a skirmish map: place some skirmish entities for each player in Atlas (see templates/skirmish/* for examples), uncheck the player's civ in Atlas' player panel if desired, and save in the maps/skirmishes directory. The map will appear in match setup under the "Skirmish" match type.
Implements custom, VFS-based map load/save dialogs for Atlas (replaces
broken native file dialogs), fixes #631, #889.
Fixes map loading/saving to handle arbitrary subdirectories for better
organization.
Adds default settings to Atlas player panel, fixes #1872. Each setting
now has a checkbox to choose whether it should be saved with the map
(avoids writing lots of useless default data for each map).
Adds map preview setting to Atlas, refs #1745.
Cleans up and simplifies some duplicate code.
Fixes optional serialization performance test.
This was SVN commit r13938.
2013-10-03 19:29:16 -07:00
// map preview
2019-06-03 13:19:53 -07:00
wxDynamicCast ( FindWindow ( ID_MapPreview ) , wxTextCtrl ) - > ChangeValue ( wxString : : FromUTF8 ( m_MapSettings [ " Preview " ] ) ) ;
Implements skirmish maps, based on patch by sanderd17, fixes #1198. Skirmish maps are like scenarios, except the player can choose their civ during match setup. To create a skirmish map: place some skirmish entities for each player in Atlas (see templates/skirmish/* for examples), uncheck the player's civ in Atlas' player panel if desired, and save in the maps/skirmishes directory. The map will appear in match setup under the "Skirmish" match type.
Implements custom, VFS-based map load/save dialogs for Atlas (replaces
broken native file dialogs), fixes #631, #889.
Fixes map loading/saving to handle arbitrary subdirectories for better
organization.
Adds default settings to Atlas player panel, fixes #1872. Each setting
now has a checkbox to choose whether it should be saved with the map
(avoids writing lots of useless default data for each map).
Adds map preview setting to Atlas, refs #1745.
Cleans up and simplifies some duplicate code.
Fixes optional serialization performance test.
This was SVN commit r13938.
2013-10-03 19:29:16 -07:00
2011-06-23 15:38:26 -07:00
// reveal map
2019-06-03 13:19:53 -07:00
wxDynamicCast ( FindWindow ( ID_MapReveal ) , wxCheckBox ) - > SetValue ( wxString : : FromUTF8 ( m_MapSettings [ " RevealMap " ] ) = = " true " ) ;
2011-05-29 08:02:02 -07:00
2021-08-27 23:15:36 -07:00
// ally view
wxDynamicCast ( FindWindow ( ID_MapAlly ) , wxCheckBox ) - > SetValue ( wxString : : FromUTF8 ( m_MapSettings [ " AllyView " ] ) = = " true " ) ;
2018-03-09 13:51:18 -08:00
// victory conditions
m_MapSettingsVictoryConditions . clear ( ) ;
for ( AtIter victoryCondition = m_MapSettings [ " VictoryConditions " ] [ " item " ] ; victoryCondition . defined ( ) ; + + victoryCondition )
2019-06-03 13:19:53 -07:00
m_MapSettingsVictoryConditions . insert ( std : : string ( victoryCondition ) ) ;
2018-03-09 13:51:18 -08:00
2020-07-18 10:39:59 -07:00
// Clear Checkboxes before loading data. We don't update victory condition just yet because it might reenable some of the checkboxes.
2020-12-31 06:25:37 -08:00
for ( const std : : pair < const long , AtObj > & vc : m_VictoryConditions )
2020-07-18 10:39:59 -07:00
{
wxCheckBox * checkBox = wxDynamicCast ( FindWindow ( vc . first ) , wxCheckBox ) ;
if ( ! checkBox )
continue ;
checkBox - > SetValue ( false ) ;
checkBox - > Enable ( true ) ;
}
2020-12-31 06:25:37 -08:00
for ( const std : : pair < const long , AtObj > & vc : m_VictoryConditions )
2020-07-18 10:39:59 -07:00
{
2020-09-20 02:33:18 -07:00
std : : string escapedTitle = wxString : : FromUTF8 ( vc . second [ " Data " ] [ " Title " ] ) . Lower ( ) . ToStdString ( ) ;
std : : replace ( escapedTitle . begin ( ) , escapedTitle . end ( ) , ' ' , ' _ ' ) ;
if ( m_MapSettingsVictoryConditions . find ( escapedTitle ) = = m_MapSettingsVictoryConditions . end ( ) )
2020-07-18 10:39:59 -07:00
continue ;
wxCheckBox * checkBox = wxDynamicCast ( FindWindow ( vc . first ) , wxCheckBox ) ;
if ( ! checkBox )
continue ;
2018-03-09 13:51:18 -08:00
2020-07-18 10:39:59 -07:00
checkBox - > SetValue ( true ) ;
OnVictoryConditionChanged ( vc . first ) ;
}
2011-05-29 08:02:02 -07:00
2011-06-23 15:38:26 -07:00
// lock teams
2019-06-03 13:19:53 -07:00
wxDynamicCast ( FindWindow ( ID_MapTeams ) , wxCheckBox ) - > SetValue ( wxString : : FromUTF8 ( m_MapSettings [ " LockTeams " ] ) = = " true " ) ;
2011-05-29 08:02:02 -07:00
2011-06-23 15:38:26 -07:00
// keywords
{
m_MapSettingsKeywords . clear ( ) ;
for ( AtIter keyword = m_MapSettings [ " Keywords " ] [ " item " ] ; keyword . defined ( ) ; + + keyword )
2019-06-03 13:19:53 -07:00
m_MapSettingsKeywords . insert ( std : : string ( keyword ) ) ;
2020-07-18 10:39:59 -07:00
wxWindow * window ;
# define INIT_CHECKBOX(ID, mapSettings, value) \
window = FindWindow ( ID ) ; \
if ( window ! = nullptr ) \
wxDynamicCast ( window , wxCheckBox ) - > SetValue ( mapSettings . count ( value ) ! = 0 ) ;
2019-06-03 13:19:53 -07:00
INIT_CHECKBOX ( ID_MapKW_Demo , m_MapSettingsKeywords , " demo " ) ;
INIT_CHECKBOX ( ID_MapKW_Naval , m_MapSettingsKeywords , " naval " ) ;
2019-06-24 22:05:06 -07:00
INIT_CHECKBOX ( ID_MapKW_New , m_MapSettingsKeywords , " new " ) ;
INIT_CHECKBOX ( ID_MapKW_Trigger , m_MapSettingsKeywords , " trigger " ) ;
2020-07-18 10:39:59 -07:00
# undef INIT_CHECKBOX
2011-06-23 15:38:26 -07:00
}
2011-05-29 08:02:02 -07:00
}
2012-05-10 16:11:42 -07:00
void MapSettingsControl : : SetMapSettings ( const AtObj & obj )
{
m_MapSettings = obj ;
m_MapSettings . NotifyObservers ( ) ;
SendToEngine ( ) ;
}
2020-07-18 10:39:59 -07:00
void MapSettingsControl : : OnVictoryConditionChanged ( long controlId )
2018-03-09 13:51:18 -08:00
{
2020-07-18 10:39:59 -07:00
AtObj victoryCondition ;
2020-07-24 11:53:03 -07:00
wxCheckBox * modifiedCheckbox = wxDynamicCast ( FindWindow ( controlId ) , wxCheckBox ) ;
2020-07-18 10:39:59 -07:00
2020-12-31 06:25:37 -08:00
for ( const std : : pair < const long , AtObj > & vc : m_VictoryConditions )
2020-07-18 10:39:59 -07:00
{
2020-12-31 06:25:37 -08:00
if ( vc . first ! = controlId )
2020-07-18 10:39:59 -07:00
continue ;
2020-12-31 06:25:37 -08:00
victoryCondition = vc . second ;
2020-07-18 10:39:59 -07:00
break ;
}
2020-12-31 06:25:37 -08:00
if ( modifiedCheckbox - > GetValue ( ) )
2020-07-18 10:39:59 -07:00
{
2020-07-24 11:53:03 -07:00
for ( AtIter victoryConditionPair = victoryCondition [ " Data " ] [ " ChangeOnChecked " ] ; victoryConditionPair . defined ( ) ; + + victoryConditionPair )
2020-07-18 10:39:59 -07:00
{
2020-12-31 06:25:37 -08:00
for ( const std : : pair < const long , AtObj > & vc : m_VictoryConditions )
2020-07-18 10:39:59 -07:00
{
2020-07-24 11:53:03 -07:00
std : : string escapedTitle = wxString : : FromUTF8 ( vc . second [ " Data " ] [ " Title " ] ) . Lower ( ) . ToStdString ( ) ;
std : : replace ( escapedTitle . begin ( ) , escapedTitle . end ( ) , ' ' , ' _ ' ) ;
if ( victoryConditionPair [ escapedTitle . c_str ( ) ] . defined ( ) )
{
wxCheckBox * victoryConditionCheckBox = wxDynamicCast ( FindWindow ( vc . first ) , wxCheckBox ) ;
victoryConditionCheckBox - > SetValue ( wxString : : FromUTF8 ( victoryConditionPair [ escapedTitle . c_str ( ) ] ) . Lower ( ) . ToStdString ( ) = = " true " ) ;
}
2020-07-18 10:39:59 -07:00
}
}
}
2018-03-09 13:51:18 -08:00
2020-12-31 06:25:37 -08:00
for ( const std : : pair < const long , AtObj > & vc : m_VictoryConditions )
2018-03-09 13:51:18 -08:00
{
2020-07-24 11:53:03 -07:00
if ( vc . first = = controlId )
continue ;
2020-07-18 10:39:59 -07:00
2020-07-24 11:53:03 -07:00
wxCheckBox * otherCheckbox = wxDynamicCast ( FindWindow ( vc . first ) , wxCheckBox ) ;
otherCheckbox - > Enable ( true ) ;
2020-12-31 06:25:37 -08:00
for ( const std : : pair < const long , AtObj > & vc2 : m_VictoryConditions )
2020-07-24 11:53:03 -07:00
{
for ( AtIter victoryConditionTitle = vc2 . second [ " Data " ] [ " DisabledWhenChecked " ] ; victoryConditionTitle . defined ( ) ; + + victoryConditionTitle )
2020-07-18 10:39:59 -07:00
{
2020-07-24 11:53:03 -07:00
std : : string escapedTitle = wxString : : FromUTF8 ( vc . second [ " Data " ] [ " Title " ] ) . Lower ( ) . ToStdString ( ) ;
std : : replace ( escapedTitle . begin ( ) , escapedTitle . end ( ) , ' ' , ' _ ' ) ;
if ( escapedTitle = = wxString : : FromUTF8 ( victoryConditionTitle [ " item " ] ) . ToStdString ( ) & & wxDynamicCast ( FindWindow ( vc2 . first ) , wxCheckBox ) - > GetValue ( ) )
{
otherCheckbox - > Enable ( false ) ;
otherCheckbox - > SetValue ( false ) ;
break ;
}
2020-07-18 10:39:59 -07:00
}
}
2018-03-09 13:51:18 -08:00
}
}
2011-06-09 16:45:12 -07:00
AtObj MapSettingsControl : : UpdateSettingsObject ( )
2011-05-29 08:02:02 -07:00
{
2011-06-23 15:38:26 -07:00
// map name
2019-06-03 13:19:53 -07:00
m_MapSettings . set ( " Name " , wxDynamicCast ( FindWindow ( ID_MapName ) , wxTextCtrl ) - > GetValue ( ) . utf8_str ( ) ) ;
2011-05-29 08:02:02 -07:00
2011-06-23 15:38:26 -07:00
// map description
2019-06-03 13:19:53 -07:00
m_MapSettings . set ( " Description " , wxDynamicCast ( FindWindow ( ID_MapDescription ) , wxTextCtrl ) - > GetValue ( ) . utf8_str ( ) ) ;
2011-05-29 08:02:02 -07:00
Implements skirmish maps, based on patch by sanderd17, fixes #1198. Skirmish maps are like scenarios, except the player can choose their civ during match setup. To create a skirmish map: place some skirmish entities for each player in Atlas (see templates/skirmish/* for examples), uncheck the player's civ in Atlas' player panel if desired, and save in the maps/skirmishes directory. The map will appear in match setup under the "Skirmish" match type.
Implements custom, VFS-based map load/save dialogs for Atlas (replaces
broken native file dialogs), fixes #631, #889.
Fixes map loading/saving to handle arbitrary subdirectories for better
organization.
Adds default settings to Atlas player panel, fixes #1872. Each setting
now has a checkbox to choose whether it should be saved with the map
(avoids writing lots of useless default data for each map).
Adds map preview setting to Atlas, refs #1745.
Cleans up and simplifies some duplicate code.
Fixes optional serialization performance test.
This was SVN commit r13938.
2013-10-03 19:29:16 -07:00
// map preview
2019-06-03 13:19:53 -07:00
m_MapSettings . set ( " Preview " , wxDynamicCast ( FindWindow ( ID_MapPreview ) , wxTextCtrl ) - > GetValue ( ) . utf8_str ( ) ) ;
Implements skirmish maps, based on patch by sanderd17, fixes #1198. Skirmish maps are like scenarios, except the player can choose their civ during match setup. To create a skirmish map: place some skirmish entities for each player in Atlas (see templates/skirmish/* for examples), uncheck the player's civ in Atlas' player panel if desired, and save in the maps/skirmishes directory. The map will appear in match setup under the "Skirmish" match type.
Implements custom, VFS-based map load/save dialogs for Atlas (replaces
broken native file dialogs), fixes #631, #889.
Fixes map loading/saving to handle arbitrary subdirectories for better
organization.
Adds default settings to Atlas player panel, fixes #1872. Each setting
now has a checkbox to choose whether it should be saved with the map
(avoids writing lots of useless default data for each map).
Adds map preview setting to Atlas, refs #1745.
Cleans up and simplifies some duplicate code.
Fixes optional serialization performance test.
This was SVN commit r13938.
2013-10-03 19:29:16 -07:00
2011-06-23 15:38:26 -07:00
// reveal map
2011-05-29 08:02:02 -07:00
m_MapSettings . setBool ( " RevealMap " , wxDynamicCast ( FindWindow ( ID_MapReveal ) , wxCheckBox ) - > GetValue ( ) ) ;
2021-08-27 23:15:36 -07:00
// ally view
m_MapSettings . setBool ( " AllyView " , wxDynamicCast ( FindWindow ( ID_MapAlly ) , wxCheckBox ) - > GetValue ( ) ) ;
2018-03-09 13:51:18 -08:00
// victory conditions
# define INSERT_VICTORY_CONDITION_CHECKBOX(name, ID) \
if ( wxDynamicCast ( FindWindow ( ID ) , wxCheckBox ) - > GetValue ( ) ) \
m_MapSettingsVictoryConditions . insert ( name ) ; \
else \
m_MapSettingsVictoryConditions . erase ( name ) ;
2020-12-31 06:25:37 -08:00
for ( const std : : pair < const long , AtObj > & vc : m_VictoryConditions )
2020-09-20 02:33:18 -07:00
{
std : : string escapedTitle = wxString : : FromUTF8 ( vc . second [ " Data " ] [ " Title " ] ) . Lower ( ) . ToStdString ( ) ;
std : : replace ( escapedTitle . begin ( ) , escapedTitle . end ( ) , ' ' , ' _ ' ) ;
INSERT_VICTORY_CONDITION_CHECKBOX ( escapedTitle , vc . first )
}
2018-03-09 13:51:18 -08:00
# undef INSERT_VICTORY_CONDITION_CHECKBOX
AtObj victoryConditions ;
2019-06-03 13:19:53 -07:00
victoryConditions . set ( " @array " , " " ) ;
for ( const std : : string & victoryCondition : m_MapSettingsVictoryConditions )
victoryConditions . add ( " item " , victoryCondition . c_str ( ) ) ;
2018-03-09 13:51:18 -08:00
m_MapSettings . set ( " VictoryConditions " , victoryConditions ) ;
2011-05-29 08:02:02 -07:00
2011-06-23 15:38:26 -07:00
// keywords
{
2019-06-24 22:05:06 -07:00
# define INSERT_KEYWORDS_CHECKBOX(name, ID) \
if ( wxDynamicCast ( FindWindow ( ID ) , wxCheckBox ) - > GetValue ( ) ) \
m_MapSettingsKeywords . insert ( name ) ; \
else \
m_MapSettingsKeywords . erase ( name ) ;
INSERT_KEYWORDS_CHECKBOX ( " demo " , ID_MapKW_Demo ) ;
INSERT_KEYWORDS_CHECKBOX ( " naval " , ID_MapKW_Naval ) ;
INSERT_KEYWORDS_CHECKBOX ( " new " , ID_MapKW_New ) ;
INSERT_KEYWORDS_CHECKBOX ( " trigger " , ID_MapKW_Trigger ) ;
# undef INSERT_KEYWORDS_CHECKBOX
2011-06-23 15:38:26 -07:00
AtObj keywords ;
2019-06-03 13:19:53 -07:00
keywords . set ( " @array " , " " ) ;
for ( const std : : string & keyword : m_MapSettingsKeywords )
keywords . add ( " item " , keyword . c_str ( ) ) ;
2011-06-23 15:38:26 -07:00
m_MapSettings . set ( " Keywords " , keywords ) ;
}
2011-05-29 08:02:02 -07:00
2011-06-23 15:38:26 -07:00
// teams locked
2011-06-09 16:45:12 -07:00
m_MapSettings . setBool ( " LockTeams " , wxDynamicCast ( FindWindow ( ID_MapTeams ) , wxCheckBox ) - > GetValue ( ) ) ;
2017-12-30 06:02:09 -08:00
// default AI RNG seed
m_MapSettings . setInt ( " AISeed " , 0 ) ;
2011-05-29 08:02:02 -07:00
return m_MapSettings ;
}
2011-06-09 16:45:12 -07:00
void MapSettingsControl : : SendToEngine ( )
2011-05-29 08:02:02 -07:00
{
UpdateSettingsObject ( ) ;
2014-02-24 12:22:02 -08:00
std : : string json = AtlasObject : : SaveToJSON ( m_MapSettings ) ;
2011-05-29 08:02:02 -07:00
// TODO: would be nice if we supported undo for settings changes
2011-06-09 16:45:12 -07:00
POST_COMMAND ( SetMapSettings , ( json ) ) ;
2011-05-29 08:02:02 -07:00
}
2011-05-27 14:56:43 -07:00
MapSidebar : : MapSidebar ( ScenarioEditor & scenarioEditor , wxWindow * sidebarContainer , wxWindow * bottomBarContainer )
: Sidebar ( scenarioEditor , sidebarContainer , bottomBarContainer ) , m_SimState ( SimInactive )
2011-05-27 14:48:23 -07:00
{
2017-08-27 11:47:39 -07:00
wxSizer * scrollSizer = new wxBoxSizer ( wxVERTICAL ) ;
wxScrolledWindow * scrolledWindow = new wxScrolledWindow ( this ) ;
scrolledWindow - > SetScrollRate ( 10 , 10 ) ;
scrolledWindow - > SetSizer ( scrollSizer ) ;
m_MainSizer - > Add ( scrolledWindow , wxSizerFlags ( ) . Expand ( ) . Proportion ( 1 ) ) ;
m_MapSettingsCtrl = new MapSettingsControl ( scrolledWindow , m_ScenarioEditor ) ;
scrollSizer - > Add ( m_MapSettingsCtrl , wxSizerFlags ( ) . Expand ( ) ) ;
2011-05-27 14:48:23 -07:00
{
2011-06-23 15:38:26 -07:00
/////////////////////////////////////////////////////////////////////////
// Random map settings
2017-08-27 11:47:39 -07:00
wxStaticBoxSizer * sizer = new wxStaticBoxSizer ( wxVERTICAL , scrolledWindow , _ ( " Random map " ) ) ;
scrollSizer - > Add ( sizer , wxSizerFlags ( ) . Expand ( ) ) ;
2011-05-29 08:02:02 -07:00
2025-08-17 10:56:35 -07:00
sizer - > Add ( new wxChoice ( sizer - > GetStaticBox ( ) , ID_RandomScript ) , wxSizerFlags ( ) . Expand ( ) ) ;
2011-05-29 08:02:02 -07:00
2011-06-09 16:45:12 -07:00
sizer - > AddSpacer ( 5 ) ;
2025-08-17 10:56:35 -07:00
sizer - > Add ( new wxButton ( sizer - > GetStaticBox ( ) , ID_OpenPlayerPanel , _T ( " Change players " ) ) , wxSizerFlags ( ) . Expand ( ) ) ;
2011-08-28 20:50:29 -07:00
sizer - > AddSpacer ( 5 ) ;
2011-08-18 16:38:11 -07:00
wxFlexGridSizer * gridSizer = new wxFlexGridSizer ( 2 , 5 , 5 ) ;
2011-05-29 08:02:02 -07:00
gridSizer - > AddGrowableCol ( 1 ) ;
2025-08-17 10:56:35 -07:00
gridSizer - > Add ( new wxStaticText ( sizer - > GetStaticBox ( ) , wxID_ANY , _ ( " Biome " ) ) ,
2024-09-21 04:45:48 -07:00
wxSizerFlags ( ) . Align ( wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT ) ) ;
2025-08-17 10:56:35 -07:00
gridSizer - > Add ( new wxChoice ( sizer - > GetStaticBox ( ) , ID_RandomBiome ) , wxSizerFlags ( ) . Expand ( ) ) ;
2024-09-21 04:45:48 -07:00
2025-08-17 10:56:35 -07:00
gridSizer - > Add ( new wxStaticText ( sizer - > GetStaticBox ( ) , wxID_ANY , _ ( " Player Placement " ) ) ,
2024-09-20 08:57:53 -07:00
wxSizerFlags ( ) . Align ( wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT ) ) ;
2025-08-17 10:56:35 -07:00
gridSizer - > Add ( new wxChoice ( sizer - > GetStaticBox ( ) , ID_PlayerPlacement ) , wxSizerFlags ( ) . Expand ( ) ) ;
2024-09-20 08:57:53 -07:00
2025-08-17 10:56:35 -07:00
wxChoice * sizeChoice = new wxChoice ( sizer - > GetStaticBox ( ) , ID_RandomSize ) ;
gridSizer - > Add ( new wxStaticText ( sizer - > GetStaticBox ( ) , wxID_ANY , _ ( " Map size " ) ) , wxSizerFlags ( ) . Align ( wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT ) ) ;
2011-05-29 08:02:02 -07:00
gridSizer - > Add ( sizeChoice , wxSizerFlags ( ) . Expand ( ) ) ;
2025-08-17 10:56:35 -07:00
CREATE_CHECKBOX ( sizer - > GetStaticBox ( ) , gridSizer , " Nomad " , " Place only some units instead of starting bases. " , ID_RandomNomad ) ;
2018-02-19 14:30:09 -08:00
2025-08-17 10:56:35 -07:00
gridSizer - > Add ( new wxStaticText ( sizer - > GetStaticBox ( ) , wxID_ANY , _ ( " Random seed " ) ) , wxSizerFlags ( ) . Align ( wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT ) ) ;
2011-05-29 08:02:02 -07:00
wxBoxSizer * seedSizer = new wxBoxSizer ( wxHORIZONTAL ) ;
2025-08-17 10:56:35 -07:00
seedSizer - > Add ( Tooltipped ( new wxTextCtrl ( sizer - > GetStaticBox ( ) , ID_RandomSeed , _T ( " 0 " ) , wxDefaultPosition , wxDefaultSize , 0 , wxTextValidator ( wxFILTER_NUMERIC ) ) ,
2011-08-28 20:50:29 -07:00
_ ( " Seed value for random map " ) ) , wxSizerFlags ( 1 ) . Expand ( ) ) ;
2025-08-17 10:56:35 -07:00
seedSizer - > Add ( Tooltipped ( new wxButton ( sizer - > GetStaticBox ( ) , ID_RandomReseed , _ ( " R " ) , wxDefaultPosition , wxSize ( 40 , - 1 ) ) ,
2011-08-28 20:50:29 -07:00
_ ( " New random seed " ) ) ) ;
2011-05-29 08:02:02 -07:00
gridSizer - > Add ( seedSizer , wxSizerFlags ( ) . Expand ( ) ) ;
sizer - > Add ( gridSizer , wxSizerFlags ( ) . Expand ( ) ) ;
2011-06-09 16:45:12 -07:00
sizer - > AddSpacer ( 5 ) ;
2025-08-17 10:56:35 -07:00
sizer - > Add ( Tooltipped ( new wxButton ( sizer - > GetStaticBox ( ) , ID_RandomGenerate , _ ( " Generate map " ) ) ,
2011-08-28 20:50:29 -07:00
_ ( " Run selected random map script " ) ) , wxSizerFlags ( ) . Expand ( ) ) ;
2011-05-27 14:48:23 -07:00
}
2020-07-20 19:08:50 -07:00
{
/////////////////////////////////////////////////////////////////////////
// Misc tools
2025-08-17 10:56:35 -07:00
wxStaticBoxSizer * sizer = new wxStaticBoxSizer ( wxVERTICAL , scrolledWindow , _ ( " Misc tools " ) ) ;
sizer - > Add ( new wxButton ( sizer - > GetStaticBox ( ) , ID_ResizeMap , _ ( " Resize/Recenter map " ) ) , wxSizerFlags ( ) . Expand ( ) ) ;
2020-07-20 19:08:50 -07:00
scrollSizer - > Add ( sizer , wxSizerFlags ( ) . Expand ( ) . Border ( wxTOP , 10 ) ) ;
}
2011-05-27 14:48:23 -07:00
{
2011-06-23 15:38:26 -07:00
/////////////////////////////////////////////////////////////////////////
// Simulation buttons
2017-08-27 11:47:39 -07:00
wxStaticBoxSizer * sizer = new wxStaticBoxSizer ( wxVERTICAL , scrolledWindow , _ ( " Simulation test " ) ) ;
scrollSizer - > Add ( sizer , wxSizerFlags ( ) . Expand ( ) . Border ( wxTOP , 8 ) ) ;
2011-08-27 16:43:18 -07:00
wxGridSizer * gridSizer = new wxGridSizer ( 5 ) ;
2025-08-17 10:56:35 -07:00
gridSizer - > Add ( Tooltipped ( new wxButton ( sizer - > GetStaticBox ( ) , ID_SimPlay , _ ( " Play " ) , wxDefaultPosition , wxSize ( 48 , - 1 ) ) ,
2011-08-28 20:50:29 -07:00
_ ( " Run the simulation at normal speed " ) ) , wxSizerFlags ( ) . Expand ( ) ) ;
2025-08-17 10:56:35 -07:00
gridSizer - > Add ( Tooltipped ( new wxButton ( sizer - > GetStaticBox ( ) , ID_SimFast , _ ( " Fast " ) , wxDefaultPosition , wxSize ( 48 , - 1 ) ) ,
2011-08-28 20:50:29 -07:00
_ ( " Run the simulation at 8x speed " ) ) , wxSizerFlags ( ) . Expand ( ) ) ;
2025-08-17 10:56:35 -07:00
gridSizer - > Add ( Tooltipped ( new wxButton ( sizer - > GetStaticBox ( ) , ID_SimSlow , _ ( " Slow " ) , wxDefaultPosition , wxSize ( 48 , - 1 ) ) ,
2011-08-28 20:50:29 -07:00
_ ( " Run the simulation at 1/8x speed " ) ) , wxSizerFlags ( ) . Expand ( ) ) ;
2025-08-17 10:56:35 -07:00
gridSizer - > Add ( Tooltipped ( new wxButton ( sizer - > GetStaticBox ( ) , ID_SimPause , _ ( " Pause " ) , wxDefaultPosition , wxSize ( 48 , - 1 ) ) ,
2011-08-28 20:50:29 -07:00
_ ( " Pause the simulation " ) ) , wxSizerFlags ( ) . Expand ( ) ) ;
2025-08-17 10:56:35 -07:00
gridSizer - > Add ( Tooltipped ( new wxButton ( sizer - > GetStaticBox ( ) , ID_SimReset , _ ( " Reset " ) , wxDefaultPosition , wxSize ( 48 , - 1 ) ) ,
2011-08-28 20:50:29 -07:00
_ ( " Reset the editor to initial state " ) ) , wxSizerFlags ( ) . Expand ( ) ) ;
2011-08-27 16:43:18 -07:00
sizer - > Add ( gridSizer , wxSizerFlags ( ) . Expand ( ) ) ;
2011-05-27 14:48:23 -07:00
UpdateSimButtons ( ) ;
}
}
2011-05-29 08:02:02 -07:00
void MapSidebar : : OnCollapse ( wxCollapsiblePaneEvent & WXUNUSED ( evt ) )
2011-05-27 14:48:23 -07:00
{
2011-05-29 11:14:52 -07:00
Freeze ( ) ;
2011-05-29 08:02:02 -07:00
// Toggling the collapsing doesn't seem to update the sidebar layout
// automatically, so do it explicitly here
Layout ( ) ;
2011-05-29 11:14:52 -07:00
Refresh ( ) ; // fixes repaint glitch on Windows
Thaw ( ) ;
2011-05-27 14:48:23 -07:00
}
2011-05-29 08:02:02 -07:00
void MapSidebar : : OnFirstDisplay ( )
2011-05-27 14:48:23 -07:00
{
2011-06-09 16:45:12 -07:00
// We do this here becase messages are used which requires simulation to be init'd
m_MapSettingsCtrl - > CreateWidgets ( ) ;
m_MapSettingsCtrl - > ReadFromEngine ( ) ;
// Load the map sizes list
AtlasMessage : : qGetMapSizes qrySizes ;
qrySizes . Post ( ) ;
2014-02-24 12:22:02 -08:00
AtObj sizes = AtlasObject : : LoadFromJSON ( * qrySizes . sizes ) ;
2011-06-09 16:45:12 -07:00
wxChoice * sizeChoice = wxDynamicCast ( FindWindow ( ID_RandomSize ) , wxChoice ) ;
2015-12-04 08:37:30 -08:00
for ( AtIter s = sizes [ " Data " ] [ " item " ] ; s . defined ( ) ; + + s )
2025-05-02 00:46:20 -07:00
sizeChoice - > Append ( wxString : : FromUTF8 ( s [ " Name " ] ) , reinterpret_cast < void * > ( static_cast < intptr_t > ( ( * s [ " Tiles " ] ) . getLong ( ) ) ) ) ;
2011-06-09 16:45:12 -07:00
sizeChoice - > SetSelection ( 0 ) ;
2011-05-27 14:48:23 -07:00
2011-06-09 16:45:12 -07:00
// Load the RMS script list
2011-05-29 08:02:02 -07:00
AtlasMessage : : qGetRMSData qry ;
qry . Post ( ) ;
std : : vector < std : : string > scripts = * qry . data ;
wxChoice * scriptChoice = wxDynamicCast ( FindWindow ( ID_RandomScript ) , wxChoice ) ;
scriptChoice - > Clear ( ) ;
for ( size_t i = 0 ; i < scripts . size ( ) ; + + i )
{
2014-02-24 12:22:02 -08:00
AtObj data = AtlasObject : : LoadFromJSON ( scripts [ i ] ) ;
2019-06-03 13:19:53 -07:00
wxString name = wxString : : FromUTF8 ( data [ " settings " ] [ " Name " ] ) ;
2018-02-16 08:42:46 -08:00
if ( ! name . IsEmpty ( ) )
scriptChoice - > Append ( name , new AtObjClientData ( * data [ " settings " ] ) ) ;
2011-05-29 08:02:02 -07:00
}
scriptChoice - > SetSelection ( 0 ) ;
2011-05-29 11:14:52 -07:00
Layout ( ) ;
2011-05-29 08:02:02 -07:00
}
2011-05-27 14:48:23 -07:00
2011-05-29 08:02:02 -07:00
void MapSidebar : : OnMapReload ( )
{
2011-06-09 16:45:12 -07:00
m_MapSettingsCtrl - > ReadFromEngine ( ) ;
2013-02-22 15:20:59 -08:00
// Reset sim test buttons
POST_MESSAGE ( SimPlay , ( 0.f , false ) ) ;
2014-12-30 09:27:18 -08:00
POST_MESSAGE ( SimStopMusic , ( ) ) ;
2013-02-22 15:20:59 -08:00
POST_MESSAGE ( GuiSwitchPage , ( L " page_atlas.xml " ) ) ;
m_SimState = SimInactive ;
UpdateSimButtons ( ) ;
2011-05-27 14:48:23 -07:00
}
void MapSidebar : : UpdateSimButtons ( )
{
wxButton * button ;
button = wxDynamicCast ( FindWindow ( ID_SimPlay ) , wxButton ) ;
wxCHECK ( button , ) ;
button - > Enable ( m_SimState ! = SimPlaying ) ;
button = wxDynamicCast ( FindWindow ( ID_SimFast ) , wxButton ) ;
wxCHECK ( button , ) ;
button - > Enable ( m_SimState ! = SimPlayingFast ) ;
button = wxDynamicCast ( FindWindow ( ID_SimSlow ) , wxButton ) ;
wxCHECK ( button , ) ;
button - > Enable ( m_SimState ! = SimPlayingSlow ) ;
button = wxDynamicCast ( FindWindow ( ID_SimPause ) , wxButton ) ;
wxCHECK ( button , ) ;
button - > Enable ( IsPlaying ( m_SimState ) ) ;
button = wxDynamicCast ( FindWindow ( ID_SimReset ) , wxButton ) ;
wxCHECK ( button , ) ;
button - > Enable ( m_SimState ! = SimInactive ) ;
}
void MapSidebar : : OnSimPlay ( wxCommandEvent & event )
{
float speed = 1.f ;
int newState = SimPlaying ;
if ( event . GetId ( ) = = ID_SimFast )
{
speed = 8.f ;
newState = SimPlayingFast ;
}
else if ( event . GetId ( ) = = ID_SimSlow )
{
speed = 0.125f ;
newState = SimPlayingSlow ;
}
if ( m_SimState = = SimInactive )
{
2011-08-22 14:45:39 -07:00
// Force update of player settings
POST_MESSAGE ( LoadPlayerSettings , ( false ) ) ;
2011-05-27 14:56:43 -07:00
POST_MESSAGE ( SimStateSave , ( L " default " ) ) ;
2011-05-29 08:02:02 -07:00
POST_MESSAGE ( GuiSwitchPage , ( L " page_session.xml " ) ) ;
2013-02-22 15:20:59 -08:00
POST_MESSAGE ( SimPlay , ( speed , true ) ) ;
2011-05-27 14:48:23 -07:00
m_SimState = newState ;
}
else // paused or already playing at a different speed
{
2013-02-22 15:20:59 -08:00
POST_MESSAGE ( SimPlay , ( speed , true ) ) ;
2011-05-27 14:48:23 -07:00
m_SimState = newState ;
}
UpdateSimButtons ( ) ;
}
void MapSidebar : : OnSimPause ( wxCommandEvent & WXUNUSED ( event ) )
{
if ( IsPlaying ( m_SimState ) )
{
2013-02-22 15:20:59 -08:00
POST_MESSAGE ( SimPlay , ( 0.f , true ) ) ;
2011-05-27 14:48:23 -07:00
m_SimState = SimPaused ;
}
UpdateSimButtons ( ) ;
}
void MapSidebar : : OnSimReset ( wxCommandEvent & WXUNUSED ( event ) )
{
if ( IsPlaying ( m_SimState ) )
{
2013-02-22 15:20:59 -08:00
POST_MESSAGE ( SimPlay , ( 0.f , true ) ) ;
2011-05-27 14:48:23 -07:00
POST_MESSAGE ( SimStateRestore , ( L " default " ) ) ;
2014-12-30 09:27:18 -08:00
POST_MESSAGE ( SimStopMusic , ( ) ) ;
2013-02-22 15:20:59 -08:00
POST_MESSAGE ( SimPlay , ( 0.f , false ) ) ;
2011-05-29 08:02:02 -07:00
POST_MESSAGE ( GuiSwitchPage , ( L " page_atlas.xml " ) ) ;
2011-05-27 14:48:23 -07:00
m_SimState = SimInactive ;
}
else if ( m_SimState = = SimPaused )
{
2013-02-22 15:20:59 -08:00
POST_MESSAGE ( SimPlay , ( 0.f , true ) ) ;
2011-05-27 14:48:23 -07:00
POST_MESSAGE ( SimStateRestore , ( L " default " ) ) ;
2014-12-30 09:27:18 -08:00
POST_MESSAGE ( SimStopMusic , ( ) ) ;
2013-02-22 15:20:59 -08:00
POST_MESSAGE ( SimPlay , ( 0.f , false ) ) ;
2011-05-29 08:02:02 -07:00
POST_MESSAGE ( GuiSwitchPage , ( L " page_atlas.xml " ) ) ;
2011-05-27 14:48:23 -07:00
m_SimState = SimInactive ;
}
UpdateSimButtons ( ) ;
}
2024-09-21 04:45:48 -07:00
void MapSidebar : : OnRandomScript ( wxCommandEvent & WXUNUSED ( evt ) )
{
wxChoice * biomeChoice = wxDynamicCast ( FindWindow ( ID_RandomBiome ) , wxChoice ) ;
wxChoice * scriptChoice = wxDynamicCast ( FindWindow ( ID_RandomScript ) , wxChoice ) ;
if ( scriptChoice - > GetSelection ( ) < 0 )
return ;
biomeChoice - > Clear ( ) ;
AtObj mapSettings = dynamic_cast < AtObjClientData * > ( scriptChoice - > GetClientObject (
scriptChoice - > GetSelection ( ) ) ) - > GetValue ( ) ;
std : : vector < std : : string > biomes ;
if ( mapSettings [ " SupportedBiomes " ] [ " @array " ] . defined ( ) )
{
for ( AtIter it = mapSettings [ " SupportedBiomes " ] [ " item " ] ; it . defined ( ) ; + + it )
biomes . push_back ( static_cast < const char * > ( * it ) ) ;
}
else
{
std : : string singleBiome { static_cast < const char * > ( * mapSettings [ " SupportedBiomes " ] ) } ;
if ( ! singleBiome . empty ( ) )
biomes . push_back ( singleBiome ) ;
}
if ( std : : any_of ( biomes . begin ( ) , biomes . end ( ) , [ ] ( const std : : string & biome )
{
return ! biome . empty ( ) & & biome . back ( ) = = ' / ' ;
} ) )
{
AtlasMessage : : qExpandBiomes qry ;
qry . biomes = std : : move ( biomes ) ;
qry . Post ( ) ;
biomes = * qry . biomes ;
}
for ( const std : : string & biome : biomes )
biomeChoice - > Append ( wxString : : FromUTF8 ( biome . c_str ( ) ) ) ;
biomeChoice - > SetSelection ( 0 ) ;
2024-09-20 08:57:53 -07:00
2024-10-06 16:11:30 -07:00
wxChoice * playerPlacementChoice = wxDynamicCast ( FindWindow ( ID_PlayerPlacement ) , wxChoice ) ;
playerPlacementChoice - > Clear ( ) ;
for ( AtIter it = mapSettings [ " PlayerPlacements " ] [ " item " ] ; it . defined ( ) ; + + it )
playerPlacementChoice - > Append ( wxString : : FromUTF8 ( static_cast < const char * > ( * it ) ) ) ;
playerPlacementChoice - > SetSelection ( 0 ) ;
2024-09-21 04:45:48 -07:00
}
2011-05-29 08:02:02 -07:00
void MapSidebar : : OnRandomReseed ( wxCommandEvent & WXUNUSED ( evt ) )
{
2022-01-02 14:35:17 -08:00
std : : mt19937 engine ( std : : time ( nullptr ) ) ;
std : : uniform_int_distribution < int > distribution ( 0 , 10000 ) ;
2011-05-29 08:02:02 -07:00
// Pick a shortish randomish value
wxString seed ;
2022-01-02 14:35:17 -08:00
seed < < distribution ( engine ) ;
2011-05-29 08:02:02 -07:00
wxDynamicCast ( FindWindow ( ID_RandomSeed ) , wxTextCtrl ) - > SetValue ( seed ) ;
}
void MapSidebar : : OnRandomGenerate ( wxCommandEvent & WXUNUSED ( evt ) )
{
2015-01-08 13:29:27 -08:00
if ( m_ScenarioEditor . DiscardChangesDialog ( ) )
return ;
2011-05-29 08:02:02 -07:00
wxChoice * scriptChoice = wxDynamicCast ( FindWindow ( ID_RandomScript ) , wxChoice ) ;
if ( scriptChoice - > GetSelection ( ) < 0 )
return ;
// TODO: this settings thing seems a bit of a mess,
// since it's mixing data from three different sources
2011-06-09 16:45:12 -07:00
AtObj settings = m_MapSettingsCtrl - > UpdateSettingsObject ( ) ;
2011-05-29 08:02:02 -07:00
AtObj scriptSettings = dynamic_cast < AtObjClientData * > ( scriptChoice - > GetClientObject ( scriptChoice - > GetSelection ( ) ) ) - > GetValue ( ) ;
settings . addOverlay ( scriptSettings ) ;
wxChoice * sizeChoice = wxDynamicCast ( FindWindow ( ID_RandomSize ) , wxChoice ) ;
wxString size ;
size < < ( intptr_t ) sizeChoice - > GetClientData ( sizeChoice - > GetSelection ( ) ) ;
2011-06-13 16:32:41 -07:00
settings . setInt ( " Size " , wxAtoi ( size ) ) ;
2018-02-19 14:30:09 -08:00
settings . setBool ( " Nomad " , wxDynamicCast ( FindWindow ( ID_RandomNomad ) , wxCheckBox ) - > GetValue ( ) ) ;
2011-06-13 16:32:41 -07:00
settings . setInt ( " Seed " , wxAtoi ( wxDynamicCast ( FindWindow ( ID_RandomSeed ) , wxTextCtrl ) - > GetValue ( ) ) ) ;
2011-05-29 08:02:02 -07:00
2024-09-21 04:45:48 -07:00
const wxString biome { wxDynamicCast ( FindWindow ( ID_RandomBiome ) , wxChoice ) - > GetStringSelection ( ) } ;
if ( ! biome . IsEmpty ( ) )
settings . set ( " Biome " , biome . utf8_str ( ) ) ;
2024-10-06 16:11:30 -07:00
const wxString playerPlacement {
wxDynamicCast ( FindWindow ( ID_PlayerPlacement ) , wxChoice ) - > GetStringSelection ( ) } ;
if ( ! playerPlacement . empty ( ) )
settings . set ( " PlayerPlacement " , playerPlacement . utf8_str ( ) ) ;
2024-09-20 08:57:53 -07:00
2014-02-24 12:22:02 -08:00
std : : string json = AtlasObject : : SaveToJSON ( settings ) ;
2011-05-29 08:02:02 -07:00
2011-08-13 23:11:35 -07:00
wxBusyInfo busy ( _ ( " Generating map " ) ) ;
2011-08-10 15:23:35 -07:00
wxBusyCursor busyc ;
2011-05-29 08:02:02 -07:00
2019-06-03 13:19:53 -07:00
wxString scriptName = wxString : : FromUTF8 ( settings [ " Script " ] ) ;
2011-05-29 08:02:02 -07:00
2012-05-10 16:11:42 -07:00
// Copy the old map settings, so we don't lose them if the map generation fails
AtObj oldSettings = settings ;
2023-01-28 14:42:00 -08:00
// Deactivate tools, so they don't carry forwards into the new CWorld
// and crash.
m_ScenarioEditor . GetToolManager ( ) . SetCurrentTool ( _T ( " " ) ) ;
// TODO: clear the undo buffer, etc
2011-08-18 16:38:11 -07:00
AtlasMessage : : qGenerateMap qry ( ( std : : wstring ) scriptName . wc_str ( ) , json ) ;
2011-05-29 08:02:02 -07:00
qry . Post ( ) ;
if ( qry . status < 0 )
2011-08-18 16:38:11 -07:00
{
2012-05-10 16:11:42 -07:00
// Display error message and revert to old map settings
2019-06-03 13:19:53 -07:00
wxLogError ( _ ( " Random map script '%s' failed " ) , scriptName . c_str ( ) ) ;
2012-05-10 16:11:42 -07:00
m_MapSettingsCtrl - > SetMapSettings ( oldSettings ) ;
2011-08-18 16:38:11 -07:00
}
2011-05-29 08:02:02 -07:00
m_ScenarioEditor . NotifyOnMapReload ( ) ;
2023-01-28 14:42:00 -08:00
m_ScenarioEditor . GetCommandProc ( ) . ClearCommands ( ) ;
2011-05-29 08:02:02 -07:00
}
2011-06-23 15:38:26 -07:00
void MapSidebar : : OnOpenPlayerPanel ( wxCommandEvent & WXUNUSED ( evt ) )
{
m_ScenarioEditor . SelectPage ( _T ( " PlayerSidebar " ) ) ;
}
2020-07-20 19:08:50 -07:00
void MapSidebar : : OnResizeMap ( wxCommandEvent & WXUNUSED ( evt ) )
{
MapResizeDialog dlg ( this ) ;
if ( dlg . ShowModal ( ) ! = wxID_OK )
return ;
wxPoint offset = dlg . GetOffset ( ) ;
POST_COMMAND ( ResizeMap , ( dlg . GetNewSize ( ) , offset . x , offset . y ) ) ;
}
2011-05-27 14:48:23 -07:00
BEGIN_EVENT_TABLE ( MapSidebar , Sidebar )
2011-05-29 08:02:02 -07:00
EVT_COLLAPSIBLEPANE_CHANGED ( wxID_ANY , MapSidebar : : OnCollapse )
2011-05-27 14:48:23 -07:00
EVT_BUTTON ( ID_SimPlay , MapSidebar : : OnSimPlay )
EVT_BUTTON ( ID_SimFast , MapSidebar : : OnSimPlay )
EVT_BUTTON ( ID_SimSlow , MapSidebar : : OnSimPlay )
EVT_BUTTON ( ID_SimPause , MapSidebar : : OnSimPause )
EVT_BUTTON ( ID_SimReset , MapSidebar : : OnSimReset )
2011-05-29 08:02:02 -07:00
EVT_BUTTON ( ID_RandomReseed , MapSidebar : : OnRandomReseed )
EVT_BUTTON ( ID_RandomGenerate , MapSidebar : : OnRandomGenerate )
2020-07-20 19:08:50 -07:00
EVT_BUTTON ( ID_ResizeMap , MapSidebar : : OnResizeMap )
2011-06-23 15:38:26 -07:00
EVT_BUTTON ( ID_OpenPlayerPanel , MapSidebar : : OnOpenPlayerPanel )
2024-09-21 04:45:48 -07:00
EVT_CHOICE ( ID_RandomScript , MapSidebar : : OnRandomScript )
2011-05-27 14:48:23 -07:00
END_EVENT_TABLE ( ) ;