Fixes Atlas player panel getting out of sync with simulation. Fixes #927.
Fixes object panel not being notified of map loading. Fixes bug where opening a new map before using the player panel prevented default player data being displayed for new players. Fixes wxGTK 2.8 bug: wxChoicebook control doesn't update the choice control when adding/removing pages. Notifies player that deleting player in Atlas will delete all their objects (and gives them the option). Changes DeleteObject to DeleteObjects to support multiple selections. Implements undo for map resize (experimental). Removes annoying debug message from attempted undo of map settings. Tweaks a few Atlas UI controls. This was SVN commit r10064.
This commit is contained in:
parent
a4dc290c23
commit
27e5581d27
@ -36,4 +36,14 @@ PlayerManager.prototype.GetNumPlayers = function()
|
||||
return this.playerEntities.length;
|
||||
};
|
||||
|
||||
PlayerManager.prototype.RemoveAllPlayers = function()
|
||||
{
|
||||
// Destroy existing player entities
|
||||
for each (id in this.playerEntities)
|
||||
{
|
||||
Engine.DestroyEntity(id);
|
||||
}
|
||||
this.playerEntities = [];
|
||||
};
|
||||
|
||||
Engine.RegisterComponentType(IID_PlayerManager, "PlayerManager", PlayerManager);
|
||||
|
@ -3,8 +3,11 @@
|
||||
* Used to create player entities prior to reading the rest of a map,
|
||||
* all other initialization must be done after loading map (terrain/entities).
|
||||
* DO NOT use other components here, as they may fail unpredictably.
|
||||
* settings is the object containing settings for this map.
|
||||
* newPlayers if true will remove any old player entities and add new ones
|
||||
* (used when loading a map or when Atlas changes the number of players).
|
||||
*/
|
||||
function LoadPlayerSettings(settings)
|
||||
function LoadPlayerSettings(settings, newPlayers)
|
||||
{
|
||||
// Default settings
|
||||
if (!settings)
|
||||
@ -16,7 +19,7 @@ function LoadPlayerSettings(settings)
|
||||
var rawData = Engine.ReadJSONFile("player_defaults.json");
|
||||
if (!(rawData && rawData.PlayerData))
|
||||
{
|
||||
throw("Player.js: Error reading player default data (player_defaults.json)");
|
||||
throw("Player.js: Error reading player_defaults.json");
|
||||
}
|
||||
|
||||
var playerDefaults = rawData.PlayerData;
|
||||
@ -24,32 +27,47 @@ function LoadPlayerSettings(settings)
|
||||
// default number of players
|
||||
var numPlayers = 8;
|
||||
|
||||
if (settings.PlayerData)
|
||||
{ // Get number of players including gaia
|
||||
numPlayers = settings.PlayerData.length + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
warn("Player.js: Setup has no player data - using defaults");
|
||||
}
|
||||
|
||||
// Get player manager
|
||||
var cmpPlayerMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
|
||||
|
||||
for (var i = 0; i < numPlayers; ++i)
|
||||
var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
|
||||
|
||||
// Remove existing players and add new ones
|
||||
if (newPlayers)
|
||||
{
|
||||
// Add player entity to engine
|
||||
var entID = Engine.AddEntity("special/player");
|
||||
|
||||
// Retrieve entity
|
||||
var cmpPlayer = Engine.QueryInterface(entID, IID_Player);
|
||||
if (!cmpPlayer)
|
||||
cmpPlayerManager.RemoveAllPlayers();
|
||||
|
||||
if (settings.PlayerData)
|
||||
{ // Get number of players including gaia
|
||||
numPlayers = settings.PlayerData.length + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw("Player.js: Error creating player entity "+i);
|
||||
warn("Player.js: Setup has no player data - using defaults");
|
||||
}
|
||||
|
||||
cmpPlayer.SetPlayerID(i);
|
||||
|
||||
for (var i = 0; i < numPlayers; ++i)
|
||||
{
|
||||
// Add player entity to engine
|
||||
// TODO: Get player template name from civ data
|
||||
var entID = Engine.AddEntity("special/player");
|
||||
var cmpPlayer = Engine.QueryInterface(entID, IID_Player);
|
||||
if (!cmpPlayer)
|
||||
{
|
||||
throw("Player.js: Error creating player entity "+i);
|
||||
}
|
||||
|
||||
cmpPlayer.SetPlayerID(i);
|
||||
|
||||
// Add player to player manager
|
||||
cmpPlayerManager.AddPlayer(entID);
|
||||
}
|
||||
}
|
||||
|
||||
numPlayers = cmpPlayerManager.GetNumPlayers();
|
||||
|
||||
// Initialize the player data
|
||||
for (var i = 0; i < numPlayers; ++i)
|
||||
{
|
||||
var cmpPlayer = Engine.QueryInterface(cmpPlayerManager.GetPlayerByID(i), IID_Player);
|
||||
var pDefs = playerDefaults ? playerDefaults[i] : {};
|
||||
|
||||
// Skip gaia
|
||||
@ -57,7 +75,6 @@ function LoadPlayerSettings(settings)
|
||||
{
|
||||
var pData = settings.PlayerData ? settings.PlayerData[i-1] : {};
|
||||
|
||||
// Copy player data
|
||||
cmpPlayer.SetName(getSetting(pData, pDefs, "Name"));
|
||||
cmpPlayer.SetCiv(getSetting(pData, pDefs, "Civ"));
|
||||
cmpPlayer.SetAI(pData.AI && pData.AI != "");
|
||||
@ -120,9 +137,6 @@ function LoadPlayerSettings(settings)
|
||||
cmpPlayer.SetEnemy(j);
|
||||
}
|
||||
}
|
||||
|
||||
// Add player to player manager
|
||||
cmpPlayerMan.AddPlayer(entID);
|
||||
}
|
||||
}
|
||||
|
||||
@ -146,13 +160,13 @@ function getSetting(settings, defaults, property)
|
||||
*/
|
||||
function QueryOwnerInterface(ent, iid)
|
||||
{
|
||||
var cmpPlayerMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
|
||||
var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
|
||||
|
||||
var cmpOwnership = Engine.QueryInterface(ent, IID_Ownership);
|
||||
if (!cmpOwnership)
|
||||
return null;
|
||||
|
||||
var playerEnt = cmpPlayerMan.GetPlayerByID(cmpOwnership.GetOwner());
|
||||
var playerEnt = cmpPlayerManager.GetPlayerByID(cmpOwnership.GetOwner());
|
||||
if (!playerEnt)
|
||||
return null;
|
||||
|
||||
@ -166,9 +180,9 @@ function QueryOwnerInterface(ent, iid)
|
||||
*/
|
||||
function QueryPlayerIDInterface(id, iid)
|
||||
{
|
||||
var cmpPlayerMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
|
||||
var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
|
||||
|
||||
var playerEnt = cmpPlayerMan.GetPlayerByID(id);
|
||||
var playerEnt = cmpPlayerManager.GetPlayerByID(id);
|
||||
if (!playerEnt)
|
||||
return null;
|
||||
|
||||
@ -193,8 +207,8 @@ function IsOwnedByAllyOfEntity(entity, target)
|
||||
if (cmpOwnershipTarget)
|
||||
targetOwner = cmpOwnershipTarget.GetOwner();
|
||||
|
||||
var cmpPlayerMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
|
||||
var cmpPlayer = Engine.QueryInterface(cmpPlayerMan.GetPlayerByID(owner), IID_Player);
|
||||
var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
|
||||
var cmpPlayer = Engine.QueryInterface(cmpPlayerManager.GetPlayerByID(owner), IID_Player);
|
||||
|
||||
// Check for allied diplomacy status
|
||||
if (cmpPlayer.IsAlly(targetOwner))
|
||||
@ -223,8 +237,8 @@ function IsOwnedByAllyOfPlayer(player, target)
|
||||
if (cmpOwnershipTarget)
|
||||
targetOwner = cmpOwnershipTarget.GetOwner();
|
||||
|
||||
var cmpPlayerMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
|
||||
var cmpPlayer = Engine.QueryInterface(cmpPlayerMan.GetPlayerByID(player), IID_Player);
|
||||
var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
|
||||
var cmpPlayer = Engine.QueryInterface(cmpPlayerManager.GetPlayerByID(player), IID_Player);
|
||||
|
||||
// Check for allied diplomacy status
|
||||
if (cmpPlayer.IsAlly(targetOwner))
|
||||
@ -244,8 +258,8 @@ function IsOwnedByEnemyOfPlayer(player, target)
|
||||
if (cmpOwnershipTarget)
|
||||
targetOwner = cmpOwnershipTarget.GetOwner();
|
||||
|
||||
var cmpPlayerMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
|
||||
var cmpPlayer = Engine.QueryInterface(cmpPlayerMan.GetPlayerByID(player), IID_Player);
|
||||
var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
|
||||
var cmpPlayer = Engine.QueryInterface(cmpPlayerManager.GetPlayerByID(player), IID_Player);
|
||||
|
||||
// Check for allied diplomacy status
|
||||
if (cmpPlayer.IsEnemy(targetOwner))
|
||||
|
@ -1029,7 +1029,7 @@ int CMapReader::LoadScriptSettings()
|
||||
// load player settings script
|
||||
int CMapReader::LoadPlayerSettings()
|
||||
{
|
||||
pSimulation2->LoadPlayerSettings();
|
||||
pSimulation2->LoadPlayerSettings(true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -478,9 +478,9 @@ CScriptVal CSimulation2::GetMapSettings()
|
||||
return m->m_MapSettings.get();
|
||||
}
|
||||
|
||||
void CSimulation2::LoadPlayerSettings()
|
||||
void CSimulation2::LoadPlayerSettings(bool newPlayers)
|
||||
{
|
||||
GetScriptInterface().CallFunctionVoid(GetScriptInterface().GetGlobalObject(), "LoadPlayerSettings", m->m_MapSettings);
|
||||
GetScriptInterface().CallFunctionVoid(GetScriptInterface().GetGlobalObject(), "LoadPlayerSettings", m->m_MapSettings, newPlayers);
|
||||
}
|
||||
|
||||
void CSimulation2::LoadMapSettings()
|
||||
|
@ -69,8 +69,10 @@ public:
|
||||
|
||||
/**
|
||||
* Loads the player settings script (called before map is loaded)
|
||||
* @param newPlayers will delete all the existing player entities (if any) and create new ones
|
||||
* (needed for loading maps, but Atlas might want to update existing player data)
|
||||
*/
|
||||
void LoadPlayerSettings();
|
||||
void LoadPlayerSettings(bool newPlayers);
|
||||
|
||||
/**
|
||||
* Loads the map settings script (called after map is loaded)
|
||||
|
@ -729,6 +729,9 @@ void ScenarioEditor::SetOpenFilename(const wxString& filename)
|
||||
void ScenarioEditor::NotifyOnMapReload()
|
||||
{
|
||||
m_SectionLayout.OnMapReload();
|
||||
|
||||
// Notify observers, here so it's independent of individual panels
|
||||
m_MapSettings.NotifyObservers();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
@ -145,13 +145,14 @@ void MapSettingsControl::CreateWidgets()
|
||||
gameTypes.Add(_T("endless"));
|
||||
|
||||
wxFlexGridSizer* gridSizer = new wxFlexGridSizer(2, 5, 5);
|
||||
gridSizer->AddGrowableCol(1);
|
||||
gridSizer->Add(new wxStaticText(this, wxID_ANY, _("Reveal map")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT));
|
||||
gridSizer->Add(new wxCheckBox(this, ID_MapReveal, wxEmptyString));
|
||||
gridSizer->Add(new wxStaticText(this, wxID_ANY, _("Game type")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT));
|
||||
gridSizer->Add(new wxChoice(this, ID_MapType, wxDefaultPosition, wxDefaultSize, gameTypes));
|
||||
gridSizer->Add(new wxChoice(this, ID_MapType, wxDefaultPosition, wxDefaultSize, gameTypes), wxSizerFlags().Expand());
|
||||
gridSizer->Add(new wxStaticText(this, wxID_ANY, _("Lock teams")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT));
|
||||
gridSizer->Add(new wxCheckBox(this, ID_MapTeams, wxEmptyString));
|
||||
sizer->Add(gridSizer);
|
||||
sizer->Add(gridSizer, wxSizerFlags().Expand());
|
||||
|
||||
sizer->AddSpacer(5);
|
||||
|
||||
@ -404,6 +405,9 @@ void MapSidebar::OnSimPlay(wxCommandEvent& event)
|
||||
|
||||
if (m_SimState == SimInactive)
|
||||
{
|
||||
// Force update of player settings
|
||||
POST_MESSAGE(LoadPlayerSettings, (false));
|
||||
|
||||
POST_MESSAGE(SimStateSave, (L"default"));
|
||||
POST_MESSAGE(GuiSwitchPage, (L"page_session.xml"));
|
||||
POST_MESSAGE(SimPlay, (speed));
|
||||
|
@ -101,23 +101,23 @@ public:
|
||||
gridSizer->AddGrowableCol(1);
|
||||
gridSizer->Add(new wxStaticText(this, wxID_ANY, _("Food")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT));
|
||||
wxSpinCtrl* foodCtrl = new wxSpinCtrl(this, ID_PlayerFood, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, 0, INT_MAX);
|
||||
gridSizer->Add(Tooltipped(foodCtrl, _("Initial value of food resource")));
|
||||
gridSizer->Add(Tooltipped(foodCtrl, _("Initial value of food resource")), wxSizerFlags().Expand());
|
||||
m_Controls.food = foodCtrl;
|
||||
gridSizer->Add(new wxStaticText(this, wxID_ANY, _("Wood")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT));
|
||||
wxSpinCtrl* woodCtrl = new wxSpinCtrl(this, ID_PlayerWood, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, 0, INT_MAX);
|
||||
gridSizer->Add(Tooltipped(woodCtrl, _("Initial value of wood resource")));
|
||||
gridSizer->Add(Tooltipped(woodCtrl, _("Initial value of wood resource")), wxSizerFlags().Expand());
|
||||
m_Controls.wood = woodCtrl;
|
||||
gridSizer->Add(new wxStaticText(this, wxID_ANY, _("Metal")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT));
|
||||
wxSpinCtrl* metalCtrl = new wxSpinCtrl(this, ID_PlayerMetal, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, 0, INT_MAX);
|
||||
gridSizer->Add(Tooltipped(metalCtrl, _("Initial value of metal resource")));
|
||||
gridSizer->Add(Tooltipped(metalCtrl, _("Initial value of metal resource")), wxSizerFlags().Expand());
|
||||
m_Controls.metal = metalCtrl;
|
||||
gridSizer->Add(new wxStaticText(this, wxID_ANY, _("Stone")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT));
|
||||
wxSpinCtrl* stoneCtrl = new wxSpinCtrl(this, ID_PlayerStone, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, 0, INT_MAX);
|
||||
gridSizer->Add(Tooltipped(stoneCtrl, _("Initial value of stone resource")));
|
||||
gridSizer->Add(Tooltipped(stoneCtrl, _("Initial value of stone resource")), wxSizerFlags().Expand());
|
||||
m_Controls.stone = stoneCtrl;
|
||||
gridSizer->Add(new wxStaticText(this, wxID_ANY, _("Pop limit")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT));
|
||||
wxSpinCtrl* popCtrl = new wxSpinCtrl(this, ID_PlayerPop, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, 0, INT_MAX);
|
||||
gridSizer->Add(Tooltipped(popCtrl, _("Population limit for this player")));
|
||||
gridSizer->Add(Tooltipped(popCtrl, _("Population limit for this player")), wxSizerFlags().Expand());
|
||||
m_Controls.pop = popCtrl;
|
||||
|
||||
resourceSizer->Add(gridSizer, wxSizerFlags(1).Expand());
|
||||
@ -285,31 +285,36 @@ public:
|
||||
|
||||
void ResizePlayers(size_t numPlayers)
|
||||
{
|
||||
wxASSERT(numPlayers <= m_Pages.size());
|
||||
|
||||
// We don't really want to destroy the windows corresponding
|
||||
// to the tabs, so we've kept them in a vector and will
|
||||
// only remove and add them to the notebook as needed
|
||||
if (numPlayers <= m_Pages.size())
|
||||
// to the tabs, so we've kept them in a vector and will
|
||||
// only remove and add them to the notebook as needed
|
||||
int selection = GetSelection();
|
||||
size_t pageCount = GetPageCount();
|
||||
|
||||
if (numPlayers > pageCount)
|
||||
{
|
||||
size_t pageCount = GetPageCount();
|
||||
if (numPlayers > pageCount)
|
||||
// Add previously removed pages
|
||||
for (size_t i = pageCount; i < numPlayers; ++i)
|
||||
{
|
||||
// Add previously removed pages
|
||||
for (size_t i = pageCount; i < numPlayers; ++i)
|
||||
{
|
||||
AddPage(m_Pages[i], m_Pages[i]->GetPlayerName());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remove previously added pages
|
||||
// we have to manually hide them or they remain visible
|
||||
for (size_t i = pageCount - 1; i >= numPlayers; --i)
|
||||
{
|
||||
m_Pages[i]->Hide();
|
||||
RemovePage(i);
|
||||
}
|
||||
AddPage(m_Pages[i], m_Pages[i]->GetPlayerName());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remove previously added pages
|
||||
// we have to manually hide them or they remain visible
|
||||
for (size_t i = pageCount - 1; i >= numPlayers; --i)
|
||||
{
|
||||
m_Pages[i]->Hide();
|
||||
RemovePage(i);
|
||||
}
|
||||
}
|
||||
|
||||
// Workaround for bug on wxGTK 2.8: wxChoice selection doesn't update
|
||||
// (in fact it loses its selection when adding/removing pages)
|
||||
GetChoiceCtrl()->SetSelection(selection);
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -363,18 +368,85 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void OnNumPlayersChanged(wxSpinEvent& WXUNUSED(evt))
|
||||
void OnPlayerColour(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
if (!m_InGUIUpdate)
|
||||
{
|
||||
m_Players->ResizePlayers(wxDynamicCast(FindWindow(ID_NumPlayers), wxSpinCtrl)->GetValue());
|
||||
SendToEngine();
|
||||
|
||||
// Update player settings, to show new colour
|
||||
POST_MESSAGE(LoadPlayerSettings, (false));
|
||||
}
|
||||
}
|
||||
|
||||
void OnNumPlayersText(wxCommandEvent& WXUNUSED(evt))
|
||||
{ // Ignore because it will also trigger EVT_SPINCTRL
|
||||
// and we don't want to handle the same event twice
|
||||
}
|
||||
|
||||
void OnNumPlayersSpin(wxSpinEvent& evt)
|
||||
{
|
||||
if (!m_InGUIUpdate)
|
||||
{
|
||||
wxASSERT(evt.GetInt() > 0);
|
||||
|
||||
// Notify observers
|
||||
// When wxMessageBox pops up, wxSpinCtrl loses focus, which
|
||||
// forces another EVT_SPINCTRL event, which we don't want
|
||||
// to handle, so we check here for a change
|
||||
if (evt.GetInt() == (int)m_NumPlayers)
|
||||
{
|
||||
return; // No change
|
||||
}
|
||||
|
||||
size_t oldNumPlayers = m_NumPlayers;
|
||||
m_NumPlayers = evt.GetInt();
|
||||
|
||||
if (m_NumPlayers < oldNumPlayers)
|
||||
{
|
||||
// Remove players, but check if they own any entities
|
||||
bool notified = false;
|
||||
for (size_t i = oldNumPlayers; i > m_NumPlayers; --i)
|
||||
{
|
||||
qGetPlayerObjects objectsQry(i);
|
||||
objectsQry.Post();
|
||||
|
||||
std::vector<AtlasMessage::ObjectID> ids = *objectsQry.ids;
|
||||
|
||||
if (ids.size() > 0)
|
||||
{
|
||||
if (!notified)
|
||||
{
|
||||
// TODO: Add option to reassign objects?
|
||||
if (wxMessageBox(_("WARNING: All objects belonging to the removed players will be deleted. Continue anyway?"), _("Remove player confirmation"), wxICON_EXCLAMATION | wxYES_NO) != wxYES)
|
||||
{
|
||||
// Restore previous player count
|
||||
m_NumPlayers = oldNumPlayers;
|
||||
wxDynamicCast(FindWindow(ID_NumPlayers), wxSpinCtrl)->SetValue(m_NumPlayers);
|
||||
return;
|
||||
}
|
||||
|
||||
notified = true;
|
||||
}
|
||||
|
||||
// Delete objects
|
||||
// TODO: Merge multiple commands?
|
||||
POST_COMMAND(DeleteObjects, (ids));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_Players->ResizePlayers(m_NumPlayers);
|
||||
SendToEngine();
|
||||
|
||||
// Reload players, notify observers
|
||||
POST_MESSAGE(LoadPlayerSettings, (true));
|
||||
m_MapSettings.NotifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: we shouldn't hardcode this, but instead dynamically create
|
||||
// new player notebook pages on demand; of course the default data
|
||||
// will be limited by the entries in player_defaults.json
|
||||
static const size_t MAX_NUM_PLAYERS = 8;
|
||||
|
||||
bool m_InGUIUpdate;
|
||||
@ -383,17 +455,19 @@ private:
|
||||
ScenarioEditor& m_ScenarioEditor;
|
||||
std::vector<PlayerPageControls> m_PlayerControls;
|
||||
Observable<AtObj>& m_MapSettings;
|
||||
size_t m_NumPlayers;
|
||||
|
||||
DECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
||||
BEGIN_EVENT_TABLE(PlayerSettingsControl, wxPanel)
|
||||
EVT_BUTTON(ID_PlayerColour, PlayerSettingsControl::OnEdit)
|
||||
EVT_BUTTON(ID_PlayerColour, PlayerSettingsControl::OnPlayerColour)
|
||||
EVT_BUTTON(ID_CameraSet, PlayerSettingsControl::OnEdit)
|
||||
EVT_BUTTON(ID_CameraClear, PlayerSettingsControl::OnEdit)
|
||||
EVT_CHOICE(wxID_ANY, PlayerSettingsControl::OnEdit)
|
||||
EVT_TEXT(ID_NumPlayers, PlayerSettingsControl::OnNumPlayersText)
|
||||
EVT_TEXT(wxID_ANY, PlayerSettingsControl::OnEdit)
|
||||
EVT_SPINCTRL(ID_NumPlayers, PlayerSettingsControl::OnNumPlayersChanged)
|
||||
EVT_SPINCTRL(ID_NumPlayers, PlayerSettingsControl::OnNumPlayersSpin)
|
||||
EVT_SPINCTRL(ID_PlayerFood, PlayerSettingsControl::OnEditSpin)
|
||||
EVT_SPINCTRL(ID_PlayerWood, PlayerSettingsControl::OnEditSpin)
|
||||
EVT_SPINCTRL(ID_PlayerMetal, PlayerSettingsControl::OnEditSpin)
|
||||
@ -402,7 +476,7 @@ BEGIN_EVENT_TABLE(PlayerSettingsControl, wxPanel)
|
||||
END_EVENT_TABLE();
|
||||
|
||||
PlayerSettingsControl::PlayerSettingsControl(wxWindow* parent, ScenarioEditor& scenarioEditor)
|
||||
: wxPanel(parent, wxID_ANY), m_ScenarioEditor(scenarioEditor), m_InGUIUpdate(false), m_MapSettings(scenarioEditor.GetMapSettings())
|
||||
: wxPanel(parent, wxID_ANY), m_ScenarioEditor(scenarioEditor), m_InGUIUpdate(false), m_MapSettings(scenarioEditor.GetMapSettings()), m_NumPlayers(0)
|
||||
{
|
||||
// To prevent recursion, don't handle GUI events right now
|
||||
m_InGUIUpdate = true;
|
||||
@ -502,13 +576,17 @@ void PlayerSettingsControl::ReadFromEngine()
|
||||
}
|
||||
|
||||
AtIter player = m_MapSettings["PlayerData"]["item"];
|
||||
size_t numPlayers = player.count();
|
||||
|
||||
if (!m_MapSettings.defined() || !player.defined() || numPlayers == 0)
|
||||
if (!m_MapSettings.defined() || !player.defined() || player.count() == 0)
|
||||
{
|
||||
// Player data missing - set number of players manually
|
||||
numPlayers = MAX_NUM_PLAYERS;
|
||||
// Player data missing - set number of players to max
|
||||
m_NumPlayers = MAX_NUM_PLAYERS;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_NumPlayers = player.count();
|
||||
}
|
||||
|
||||
wxASSERT(m_NumPlayers <= MAX_NUM_PLAYERS && m_NumPlayers != 0);
|
||||
|
||||
// To prevent recursion, don't handle GUI events right now
|
||||
m_InGUIUpdate = true;
|
||||
@ -517,12 +595,12 @@ void PlayerSettingsControl::ReadFromEngine()
|
||||
AtIter playerDefs = m_PlayerDefaults["item"];
|
||||
++playerDefs; // skip gaia
|
||||
|
||||
wxDynamicCast(FindWindow(ID_NumPlayers), wxSpinCtrl)->SetValue(numPlayers);
|
||||
wxDynamicCast(FindWindow(ID_NumPlayers), wxSpinCtrl)->SetValue(m_NumPlayers);
|
||||
|
||||
// Remove / add extra player pages as needed
|
||||
m_Players->ResizePlayers(numPlayers);
|
||||
m_Players->ResizePlayers(m_NumPlayers);
|
||||
|
||||
for (size_t i = 0; i < numPlayers && i < MAX_NUM_PLAYERS; ++i, ++player, ++playerDefs)
|
||||
for (size_t i = 0; i < MAX_NUM_PLAYERS; ++i, ++player, ++playerDefs)
|
||||
{
|
||||
PlayerPageControls controls = m_PlayerControls[i];
|
||||
|
||||
@ -537,7 +615,12 @@ void PlayerSettingsControl::ReadFromEngine()
|
||||
|
||||
// civ
|
||||
wxChoice* choice = controls.civ;
|
||||
wxString civCode(player["Civ"]);
|
||||
wxString civCode;
|
||||
if (player["Civ"].defined())
|
||||
civCode = wxString(player["Civ"]);
|
||||
else
|
||||
civCode = wxString(playerDefs["Civ"]);
|
||||
|
||||
for (size_t j = 0; j < choice->GetCount(); ++j)
|
||||
{
|
||||
wxStringClientData* str = dynamic_cast<wxStringClientData*>(choice->GetClientObject(j));
|
||||
@ -651,11 +734,12 @@ AtObj PlayerSettingsControl::UpdateSettingsObject()
|
||||
{
|
||||
// Update player data in the map settings
|
||||
AtIter oldPlayer = m_MapSettings["PlayerData"]["item"];
|
||||
size_t numPlayers = wxDynamicCast(FindWindow(ID_NumPlayers), wxSpinCtrl)->GetValue();
|
||||
AtObj players;
|
||||
players.set("@array", L"");
|
||||
|
||||
for (size_t i = 0; i < numPlayers && i < MAX_NUM_PLAYERS; ++i)
|
||||
wxASSERT(m_NumPlayers <= MAX_NUM_PLAYERS);
|
||||
|
||||
for (size_t i = 0; i < m_NumPlayers; ++i)
|
||||
{
|
||||
PlayerPageControls controls = m_PlayerControls[i];
|
||||
|
||||
|
@ -94,8 +94,9 @@ TerrainSidebar::TerrainSidebar(ScenarioEditor& scenarioEditor, wxWindow* sidebar
|
||||
wxSizer* sizer = new wxStaticBoxSizer(wxVERTICAL, this, _("Visualise"));
|
||||
m_MainSizer->Add(sizer, wxSizerFlags().Expand().Border(wxTOP, 10));
|
||||
|
||||
wxSizer* visSizer = new wxFlexGridSizer(2, 5, 5);
|
||||
sizer->Add(visSizer);
|
||||
wxFlexGridSizer* visSizer = new wxFlexGridSizer(2, 5, 5);
|
||||
visSizer->AddGrowableCol(1);
|
||||
sizer->Add(visSizer, wxSizerFlags().Expand());
|
||||
|
||||
wxArrayString defaultChoices;
|
||||
defaultChoices.Add(_("(none)"));
|
||||
@ -103,7 +104,7 @@ TerrainSidebar::TerrainSidebar(ScenarioEditor& scenarioEditor, wxWindow* sidebar
|
||||
m_PassabilityChoice->SetSelection(0);
|
||||
|
||||
visSizer->Add(new wxStaticText(this, wxID_ANY, _("Passability")), wxSizerFlags().Align(wxALIGN_CENTER|wxALIGN_RIGHT));
|
||||
visSizer->Add(m_PassabilityChoice);
|
||||
visSizer->Add(m_PassabilityChoice, wxSizerFlags().Expand());
|
||||
|
||||
visSizer->Add(new wxStaticText(this, wxID_ANY, _("Priorities")), wxSizerFlags().Align(wxALIGN_CENTER|wxALIGN_RIGHT));
|
||||
visSizer->Add(new wxCheckBox(this, ID_ShowPriorities, _("")));
|
||||
|
@ -216,11 +216,12 @@ void Brush::CreateUI(wxWindow* parent, wxSizer* sizer)
|
||||
sizer->AddSpacer(5);
|
||||
|
||||
// TODO: These are yucky
|
||||
wxSizer* spinnerSizer = new wxFlexGridSizer(2, 2, 5, 5);
|
||||
wxFlexGridSizer* spinnerSizer = new wxFlexGridSizer(2, 5, 5);
|
||||
spinnerSizer->AddGrowableCol(1);
|
||||
spinnerSizer->Add(new wxStaticText(parent, wxID_ANY, _("Size")), wxSizerFlags().Align(wxALIGN_CENTER|wxALIGN_RIGHT));
|
||||
spinnerSizer->Add(new BrushSizeCtrl(parent, *this));
|
||||
spinnerSizer->Add(new BrushSizeCtrl(parent, *this), wxSizerFlags().Expand());
|
||||
spinnerSizer->Add(new wxStaticText(parent, wxID_ANY, _("Strength")), wxSizerFlags().Align(wxALIGN_CENTER|wxALIGN_RIGHT));
|
||||
spinnerSizer->Add(new BrushStrengthCtrl(parent, *this));
|
||||
spinnerSizer->Add(new BrushStrengthCtrl(parent, *this), wxSizerFlags().Expand());
|
||||
sizer->Add(spinnerSizer, wxSizerFlags().Expand());
|
||||
}
|
||||
|
||||
|
@ -99,8 +99,7 @@ public:
|
||||
{
|
||||
if (type == KEY_CHAR && evt.GetKeyCode() == WXK_DELETE)
|
||||
{
|
||||
for (size_t i = 0; i < g_SelectedObjects.size(); ++i)
|
||||
POST_COMMAND(DeleteObject, (g_SelectedObjects[i]));
|
||||
POST_COMMAND(DeleteObjects, (g_SelectedObjects));
|
||||
|
||||
g_SelectedObjects.clear();
|
||||
g_SelectedObjects.NotifyObservers();
|
||||
|
@ -139,31 +139,52 @@ QUERYHANDLER(GetMapSettings)
|
||||
msg->settings = g_Game->GetSimulation2()->GetMapSettingsString();
|
||||
}
|
||||
|
||||
QUERYHANDLER(GetMapSizes)
|
||||
{
|
||||
msg->sizes = g_Game->GetSimulation2()->GetMapSizes();
|
||||
}
|
||||
|
||||
BEGIN_COMMAND(SetMapSettings)
|
||||
{
|
||||
void Do()
|
||||
std::string m_OldSettings, m_NewSettings;
|
||||
|
||||
void SetSettings(const std::string& settings)
|
||||
{
|
||||
Redo();
|
||||
g_Game->GetSimulation2()->SetMapSettings(settings);
|
||||
}
|
||||
|
||||
void Do()
|
||||
{
|
||||
m_OldSettings = g_Game->GetSimulation2()->GetMapSettingsString();
|
||||
m_NewSettings = *msg->settings;
|
||||
|
||||
SetSettings(m_NewSettings);
|
||||
}
|
||||
|
||||
// TODO: we need some way to notify the Atlas UI when the settings are changed
|
||||
// externally, otherwise this will have no visible effect
|
||||
void Undo()
|
||||
{
|
||||
// TODO
|
||||
debug_warn(L"Can't undo SetMapSettings");
|
||||
// SetSettings(m_OldSettings);
|
||||
}
|
||||
|
||||
void Redo()
|
||||
{
|
||||
g_Game->GetSimulation2()->SetMapSettings(*msg->settings);
|
||||
// SetSettings(m_NewSettings);
|
||||
}
|
||||
|
||||
void MergeIntoPrevious(cSetMapSettings* prev)
|
||||
{
|
||||
prev->m_NewSettings = m_NewSettings;
|
||||
}
|
||||
};
|
||||
END_COMMAND(SetMapSettings)
|
||||
|
||||
MESSAGEHANDLER(LoadPlayerSettings)
|
||||
{
|
||||
g_Game->GetSimulation2()->LoadPlayerSettings(msg->newplayers);
|
||||
}
|
||||
|
||||
QUERYHANDLER(GetMapSizes)
|
||||
{
|
||||
msg->sizes = g_Game->GetSimulation2()->GetMapSizes();
|
||||
}
|
||||
|
||||
QUERYHANDLER(GetRMSData)
|
||||
{
|
||||
msg->data = g_Game->GetSimulation2()->GetRMSData();
|
||||
@ -171,6 +192,8 @@ QUERYHANDLER(GetRMSData)
|
||||
|
||||
BEGIN_COMMAND(ResizeMap)
|
||||
{
|
||||
int m_OldTiles, m_NewTiles;
|
||||
|
||||
cResizeMap()
|
||||
{
|
||||
}
|
||||
@ -186,24 +209,39 @@ BEGIN_COMMAND(ResizeMap)
|
||||
g_Game->GetView()->GetLOSTexture().MakeDirty();
|
||||
}
|
||||
|
||||
void ResizeTerrain(int tiles)
|
||||
{
|
||||
CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
|
||||
|
||||
terrain->Resize(tiles / PATCH_SIZE);
|
||||
|
||||
MakeDirty();
|
||||
}
|
||||
|
||||
void Do()
|
||||
{
|
||||
Redo();
|
||||
CmpPtr<ICmpTerrain> cmpTerrain(*g_Game->GetSimulation2(), SYSTEM_ENTITY);
|
||||
if (cmpTerrain.null())
|
||||
{
|
||||
m_OldTiles = m_NewTiles = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_OldTiles = (int)cmpTerrain->GetTilesPerSide();
|
||||
m_NewTiles = msg->tiles;
|
||||
}
|
||||
|
||||
ResizeTerrain(m_NewTiles);
|
||||
}
|
||||
|
||||
void Undo()
|
||||
{
|
||||
// TODO
|
||||
debug_warn(L"Can't undo ResizeMap");
|
||||
ResizeTerrain(m_OldTiles);
|
||||
}
|
||||
|
||||
void Redo()
|
||||
{
|
||||
CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
|
||||
|
||||
terrain->Resize(msg->tiles / PATCH_SIZE);
|
||||
|
||||
MakeDirty();
|
||||
ResizeTerrain(m_NewTiles);
|
||||
}
|
||||
};
|
||||
END_COMMAND(ResizeMap)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2010 Wildfire Games.
|
||||
/* Copyright (C) 2011 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -543,18 +543,21 @@ BEGIN_COMMAND(RotateObject)
|
||||
END_COMMAND(RotateObject)
|
||||
|
||||
|
||||
BEGIN_COMMAND(DeleteObject)
|
||||
BEGIN_COMMAND(DeleteObjects)
|
||||
{
|
||||
// Saved copy of the important aspects of a unit, to allow undo
|
||||
entity_id_t m_EntityID;
|
||||
CStr m_TemplateName;
|
||||
int32_t m_Owner;
|
||||
CFixedVector3D m_Pos;
|
||||
CFixedVector3D m_Rot;
|
||||
// TODO: random selections
|
||||
struct OldObject
|
||||
{
|
||||
entity_id_t entityID;
|
||||
CStr templateName;
|
||||
int32_t owner;
|
||||
CFixedVector3D pos;
|
||||
CFixedVector3D rot;
|
||||
};
|
||||
|
||||
cDeleteObject()
|
||||
: m_EntityID(INVALID_ENTITY), m_Owner(-1)
|
||||
std::vector<OldObject> oldObjects;
|
||||
|
||||
cDeleteObjects()
|
||||
{
|
||||
}
|
||||
|
||||
@ -569,46 +572,77 @@ BEGIN_COMMAND(DeleteObject)
|
||||
CmpPtr<ICmpTemplateManager> cmpTemplateManager(sim, SYSTEM_ENTITY);
|
||||
ENSURE(!cmpTemplateManager.null());
|
||||
|
||||
m_EntityID = (entity_id_t)msg->id;
|
||||
m_TemplateName = cmpTemplateManager->GetCurrentTemplateName(m_EntityID);
|
||||
|
||||
CmpPtr<ICmpOwnership> cmpOwner(sim, m_EntityID);
|
||||
if (!cmpOwner.null())
|
||||
m_Owner = cmpOwner->GetOwner();
|
||||
|
||||
CmpPtr<ICmpPosition> cmpPosition(sim, m_EntityID);
|
||||
if (!cmpPosition.null())
|
||||
std::vector<ObjectID> ids = *msg->ids;
|
||||
for (size_t i = 0; i < ids.size(); ++i)
|
||||
{
|
||||
m_Pos = cmpPosition->GetPosition();
|
||||
m_Rot = cmpPosition->GetRotation();
|
||||
}
|
||||
OldObject obj;
|
||||
|
||||
g_Game->GetSimulation2()->DestroyEntity(m_EntityID);
|
||||
obj.entityID = (entity_id_t)ids[i];
|
||||
obj.templateName = cmpTemplateManager->GetCurrentTemplateName(obj.entityID);
|
||||
|
||||
CmpPtr<ICmpOwnership> cmpOwner(sim, obj.entityID);
|
||||
if (!cmpOwner.null())
|
||||
obj.owner = cmpOwner->GetOwner();
|
||||
|
||||
CmpPtr<ICmpPosition> cmpPosition(sim, obj.entityID);
|
||||
if (!cmpPosition.null())
|
||||
{
|
||||
obj.pos = cmpPosition->GetPosition();
|
||||
obj.rot = cmpPosition->GetRotation();
|
||||
}
|
||||
|
||||
oldObjects.push_back(obj);
|
||||
g_Game->GetSimulation2()->DestroyEntity(obj.entityID);
|
||||
}
|
||||
}
|
||||
|
||||
void Undo()
|
||||
{
|
||||
CSimulation2& sim = *g_Game->GetSimulation2();
|
||||
entity_id_t ent = sim.AddEntity(m_TemplateName.FromUTF8(), m_EntityID);
|
||||
if (ent == INVALID_ENTITY)
|
||||
LOGERROR(L"Failed to load entity template '%hs'", m_TemplateName.c_str());
|
||||
else
|
||||
{
|
||||
CmpPtr<ICmpPosition> cmpPosition(sim, m_EntityID);
|
||||
if (!cmpPosition.null())
|
||||
{
|
||||
cmpPosition->JumpTo(m_Pos.X, m_Pos.Z);
|
||||
cmpPosition->SetXZRotation(m_Rot.X, m_Rot.Z);
|
||||
cmpPosition->SetYRotation(m_Rot.Y);
|
||||
}
|
||||
|
||||
CmpPtr<ICmpOwnership> cmpOwner(sim, m_EntityID);
|
||||
if (!cmpOwner.null())
|
||||
cmpOwner->SetOwner(m_Owner);
|
||||
for (size_t i = 0; i < oldObjects.size(); ++i)
|
||||
{
|
||||
entity_id_t ent = sim.AddEntity(oldObjects[i].templateName.FromUTF8(), oldObjects[i].entityID);
|
||||
if (ent == INVALID_ENTITY)
|
||||
{
|
||||
LOGERROR(L"Failed to load entity template '%hs'", oldObjects[i].templateName.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
CmpPtr<ICmpPosition> cmpPosition(sim, oldObjects[i].entityID);
|
||||
if (!cmpPosition.null())
|
||||
{
|
||||
cmpPosition->JumpTo(oldObjects[i].pos.X, oldObjects[i].pos.Z);
|
||||
cmpPosition->SetXZRotation(oldObjects[i].rot.X, oldObjects[i].rot.Z);
|
||||
cmpPosition->SetYRotation(oldObjects[i].rot.Y);
|
||||
}
|
||||
|
||||
CmpPtr<ICmpOwnership> cmpOwner(sim, oldObjects[i].entityID);
|
||||
if (!cmpOwner.null())
|
||||
cmpOwner->SetOwner(oldObjects[i].owner);
|
||||
}
|
||||
}
|
||||
|
||||
oldObjects.clear();
|
||||
}
|
||||
};
|
||||
END_COMMAND(DeleteObject)
|
||||
END_COMMAND(DeleteObjects)
|
||||
|
||||
QUERYHANDLER(GetPlayerObjects)
|
||||
{
|
||||
std::vector<ObjectID> ids;
|
||||
player_id_t playerID = msg->player;
|
||||
|
||||
const CSimulation2::InterfaceListUnordered& cmps = g_Game->GetSimulation2()->GetEntitiesWithInterfaceUnordered(IID_Ownership);
|
||||
for (CSimulation2::InterfaceListUnordered::const_iterator eit = cmps.begin(); eit != cmps.end(); ++eit)
|
||||
{
|
||||
if (static_cast<ICmpOwnership*>(eit->second)->GetOwner() == playerID)
|
||||
{
|
||||
ids.push_back(eit->first);
|
||||
}
|
||||
}
|
||||
|
||||
msg->ids = ids;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -152,15 +152,19 @@ QUERY(GetMapSettings,
|
||||
((std::string, settings))
|
||||
);
|
||||
|
||||
COMMAND(SetMapSettings, MERGE,
|
||||
((std::string, settings))
|
||||
);
|
||||
|
||||
MESSAGE(LoadPlayerSettings,
|
||||
((bool, newplayers))
|
||||
);
|
||||
|
||||
QUERY(GetMapSizes,
|
||||
,
|
||||
((std::string, sizes))
|
||||
);
|
||||
|
||||
COMMAND(SetMapSettings, NOMERGE,
|
||||
((std::string, settings))
|
||||
);
|
||||
|
||||
QUERY(GetRMSData,
|
||||
,
|
||||
((std::vector<std::string>, data))
|
||||
@ -418,7 +422,7 @@ QUERY(GetEnvironmentSettings,
|
||||
((sEnvironmentSettings, settings))
|
||||
);
|
||||
|
||||
COMMAND(SetEnvironmentSettings, MERGE,
|
||||
COMMAND(SetEnvironmentSettings, MERGE, // merge lots of small changes into one undoable command
|
||||
((sEnvironmentSettings, settings))
|
||||
);
|
||||
|
||||
@ -486,8 +490,8 @@ COMMAND(RotateObject, MERGE,
|
||||
((float, angle))
|
||||
);
|
||||
|
||||
COMMAND(DeleteObject, NOMERGE,
|
||||
((ObjectID, id))
|
||||
COMMAND(DeleteObjects, NOMERGE,
|
||||
((std::vector<ObjectID>, ids))
|
||||
);
|
||||
|
||||
MESSAGE(SetSelectionPreview,
|
||||
@ -507,6 +511,12 @@ COMMAND(SetObjectSettings, NOMERGE,
|
||||
((sObjectSettings, settings))
|
||||
);
|
||||
|
||||
QUERY(GetPlayerObjects,
|
||||
((int, player))
|
||||
,
|
||||
((std::vector<ObjectID>, ids))
|
||||
);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
QUERY(GetCinemaPaths,
|
||||
|
Loading…
Reference in New Issue
Block a user