Index: ps/trunk/build/premake/premake5.lua =================================================================== --- ps/trunk/build/premake/premake5.lua +++ ps/trunk/build/premake/premake5.lua @@ -1175,7 +1175,8 @@ { -- include "..", "CustomControls", - "Misc" + "Misc", + "../../../third_party/jsonspirit" }, atlas_extern_libs, { -- extra_params Index: ps/trunk/source/simulation2/Simulation2.h =================================================================== --- ps/trunk/source/simulation2/Simulation2.h +++ ps/trunk/source/simulation2/Simulation2.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 Wildfire Games. +/* Copyright (C) 2020 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -250,6 +250,13 @@ std::vector GetCivData(); /** + * Get victory condition data + * + * @return vector of strings containing JSON format data + */ + std::vector GetVictoryConditiondData(); + + /** * Get player default data * * @return string containing JSON format data Index: ps/trunk/source/simulation2/Simulation2.cpp =================================================================== --- ps/trunk/source/simulation2/Simulation2.cpp +++ ps/trunk/source/simulation2/Simulation2.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 Wildfire Games. +/* Copyright (C) 2020 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -952,6 +952,11 @@ return GetJSONData(L"simulation/data/civs/"); } +std::vector CSimulation2::GetVictoryConditiondData() +{ + return GetJSONData(L"simulation/data/settings/victory_conditions/"); +} + static std::string ReadJSON(const VfsPath& path) { if (!VfsFileExists(path)) Index: ps/trunk/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Map/Map.cpp =================================================================== --- ps/trunk/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Map/Map.cpp +++ ps/trunk/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Map/Map.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 Wildfire Games. +/* Copyright (C) 2020 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -20,12 +20,13 @@ #include "Map.h" #include "AtlasObject/AtlasObject.h" +#include "AtlasObject/JSONSpiritInclude.h" #include "GameInterface/Messages.h" #include "ScenarioEditor/ScenarioEditor.h" #include "ScenarioEditor/Tools/Common/Tools.h" -#include "wx/busyinfo.h" -#include "wx/filename.h" +#include +#include #define CREATE_CHECKBOX(window, parentSizer, name, description, ID) \ parentSizer->Add(new wxStaticText(window, wxID_ANY, _(name)), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT)); \ @@ -43,12 +44,6 @@ ID_MapKW_Naval, ID_MapKW_New, ID_MapKW_Trigger, - ID_VC_Conquest, - ID_VC_ConquestUnits, - ID_VC_ConquestStructures, - ID_VC_CaptureTheRelic, - ID_VC_Wonder, - ID_VC_Regicide, ID_RandomScript, ID_RandomSize, ID_RandomNomad, @@ -105,15 +100,15 @@ AtObj UpdateSettingsObject(); private: void SendToEngine(); - void OnConquestChanged(); + void OnVictoryConditionChanged(long controlId); void OnEdit(wxCommandEvent& evt) { + OnVictoryConditionChanged(evt.GetId()); SendToEngine(); - if (evt.GetId() == ID_VC_Conquest) - OnConquestChanged(); } + std::map m_VictoryConditions; std::set m_MapSettingsKeywords; std::set m_MapSettingsVictoryConditions; std::vector m_PlayerCivChoices; @@ -171,16 +166,23 @@ sizer->AddSpacer(5); - // TODO: replace by names in binaries/data/mods/public/simulation/data/settings/victory_conditions/ wxStaticBoxSizer* victoryConditionSizer = new wxStaticBoxSizer(wxVERTICAL, this, _("Victory Conditions")); wxFlexGridSizer* vcGridSizer = new wxFlexGridSizer(2, 0, 5); vcGridSizer->AddGrowableCol(1); - CREATE_CHECKBOX(this, vcGridSizer, "Conquest", "Select Conquest victory condition", ID_VC_Conquest); - CREATE_CHECKBOX(this, vcGridSizer, "Conquest Units", "Select Conquest Units victory condition", ID_VC_ConquestUnits); - CREATE_CHECKBOX(this, vcGridSizer, "Conquest Structures", "Select Conquest Structures victory condition", ID_VC_ConquestStructures); - CREATE_CHECKBOX(this, vcGridSizer, "Capture the Relic", "Select Capture the Relic victory condition", ID_VC_CaptureTheRelic); - CREATE_CHECKBOX(this, vcGridSizer, "Wonder", "Select Wonder victory condition", ID_VC_Wonder); - CREATE_CHECKBOX(this, vcGridSizer, "Regicide", "Select Regicide victory condition", ID_VC_Regicide); + + AtlasMessage::qGetVictoryConditionData qryVictoryCondition; + qryVictoryCondition.Post(); + std::vector 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"]); + m_VictoryConditions.insert(std::pair(index, victoryCondition)); + CREATE_CHECKBOX(this, vcGridSizer, title.MakeLower(), "Select " + wxString::FromUTF8(victoryCondition["Data"]["Title"]) + " victory condition.", index); + } + victoryConditionSizer->Add(vcGridSizer); sizer->Add(victoryConditionSizer, wxSizerFlags().Expand()); @@ -224,19 +226,29 @@ for (AtIter victoryCondition = m_MapSettings["VictoryConditions"]["item"]; victoryCondition.defined(); ++victoryCondition) m_MapSettingsVictoryConditions.insert(std::string(victoryCondition)); - wxWindow* window; -#define INIT_CHECKBOX(ID, mapSettings, value) \ - window = FindWindow(ID); \ - if (window != nullptr) \ - wxDynamicCast(window, wxCheckBox)->SetValue(mapSettings.count(value) != 0); - - INIT_CHECKBOX(ID_VC_Conquest, m_MapSettingsVictoryConditions, "conquest"); - INIT_CHECKBOX(ID_VC_ConquestUnits, m_MapSettingsVictoryConditions, "conquest_units"); - INIT_CHECKBOX(ID_VC_ConquestStructures, m_MapSettingsVictoryConditions, "conquest_structures"); - INIT_CHECKBOX(ID_VC_CaptureTheRelic, m_MapSettingsVictoryConditions, "capture_the_relic"); - INIT_CHECKBOX(ID_VC_Wonder, m_MapSettingsVictoryConditions, "wonder"); - INIT_CHECKBOX(ID_VC_Regicide, m_MapSettingsVictoryConditions, "regicide"); - OnConquestChanged(); + // Clear Checkboxes before loading data. We don't update victory condition just yet because it might reenable some of the checkboxes. + for (const std::pair& vc : m_VictoryConditions) + { + wxCheckBox* checkBox = wxDynamicCast(FindWindow(vc.first), wxCheckBox); + if (!checkBox) + continue; + + checkBox->SetValue(false); + checkBox->Enable(true); + } + + for (const std::pair& vc : m_VictoryConditions) + { + if (m_MapSettingsVictoryConditions.count(wxString::FromUTF8(vc.second["Data"]["Title"]).Lower().ToStdString()) == 0) + continue; + + wxCheckBox* checkBox = wxDynamicCast(FindWindow(vc.first), wxCheckBox); + if (!checkBox) + continue; + + checkBox->SetValue(true); + OnVictoryConditionChanged(vc.first); + } // lock teams wxDynamicCast(FindWindow(ID_MapTeams), wxCheckBox)->SetValue(wxString::FromUTF8(m_MapSettings["LockTeams"]) == "true"); @@ -246,14 +258,17 @@ m_MapSettingsKeywords.clear(); for (AtIter keyword = m_MapSettings["Keywords"]["item"]; keyword.defined(); ++keyword) m_MapSettingsKeywords.insert(std::string(keyword)); - + wxWindow* window; + #define INIT_CHECKBOX(ID, mapSettings, value) \ + window = FindWindow(ID); \ + if (window != nullptr) \ + wxDynamicCast(window, wxCheckBox)->SetValue(mapSettings.count(value) != 0); INIT_CHECKBOX(ID_MapKW_Demo, m_MapSettingsKeywords, "demo"); INIT_CHECKBOX(ID_MapKW_Naval, m_MapSettingsKeywords, "naval"); INIT_CHECKBOX(ID_MapKW_New, m_MapSettingsKeywords, "new"); INIT_CHECKBOX(ID_MapKW_Trigger, m_MapSettingsKeywords, "trigger"); + #undef INIT_CHECKBOX } - -#undef INIT_CHECKBOX } void MapSettingsControl::SetMapSettings(const AtObj& obj) @@ -264,19 +279,59 @@ SendToEngine(); } -// TODO Use the json data for this -void MapSettingsControl::OnConquestChanged() +void MapSettingsControl::OnVictoryConditionChanged(long controlId) { - bool conqestEnabled = wxDynamicCast(FindWindow(ID_VC_Conquest), wxCheckBox)->GetValue(); + AtObj victoryCondition; - wxCheckBox* conquestUnitsCheckbox = wxDynamicCast(FindWindow(ID_VC_ConquestUnits), wxCheckBox); - conquestUnitsCheckbox->Enable(!conqestEnabled); - wxCheckBox* conquestStructuresCheckbox = wxDynamicCast(FindWindow(ID_VC_ConquestStructures), wxCheckBox); - conquestStructuresCheckbox->Enable(!conqestEnabled); - if (conqestEnabled) + for (const std::pair& vc : m_VictoryConditions) { - conquestUnitsCheckbox->SetValue(false); - conquestStructuresCheckbox->SetValue(false); + if(vc.first != controlId) + continue; + + victoryCondition = vc.second; + break; + } + + // ChangeOnChecked and DisabledWhenChecked use file names instead of victory titles so we have to convert them. + + for (AtIter victoryConditionPair = victoryCondition["Data"]["ChangeOnChecked"]; victoryConditionPair.defined(); ++victoryConditionPair) + { + for (const std::pair& vc : m_VictoryConditions) + { + std::string escapedTitle = wxString::FromUTF8(vc.second["Data"]["Title"]).Lower().ToStdString(); + for (std::string::iterator it = escapedTitle.begin(); it != escapedTitle.end(); ++it) { + if (*it == ' ') + *it = '_'; + } + + if (victoryConditionPair[escapedTitle.c_str()].defined()) + { + wxCheckBox* victoryConditionCheckBox = wxDynamicCast(FindWindow(vc.first), wxCheckBox); + victoryConditionCheckBox->SetValue(wxString::FromUTF8(victoryConditionPair[escapedTitle.c_str()]).Lower().ToStdString() == "true"); + break; + } + } + } + + bool controlEnabled = wxDynamicCast(FindWindow(controlId), wxCheckBox)->GetValue(); + for (AtIter victoryConditionTitle = victoryCondition["Data"]["DisabledWhenChecked"]; victoryConditionTitle.defined(); ++victoryConditionTitle) + { + for (const std::pair& vc : m_VictoryConditions) + { + std::string escapedTitle = wxString::FromUTF8(vc.second["Data"]["Title"]).Lower().ToStdString(); + for (std::string::iterator it = escapedTitle.begin(); it != escapedTitle.end(); ++it) { + if (*it == ' ') + *it = '_'; + } + + if (escapedTitle == wxString::FromUTF8(victoryConditionTitle["item"]).ToStdString()) + { + wxCheckBox* victoryConditionCheckBox = wxDynamicCast(FindWindow(vc.first), wxCheckBox); + victoryConditionCheckBox->Enable(!controlEnabled); + victoryConditionCheckBox->SetValue(!controlEnabled); + break; + } + } } } @@ -301,12 +356,8 @@ else \ m_MapSettingsVictoryConditions.erase(name); - INSERT_VICTORY_CONDITION_CHECKBOX("conquest", ID_VC_Conquest); - INSERT_VICTORY_CONDITION_CHECKBOX("conquest_units", ID_VC_ConquestUnits); - INSERT_VICTORY_CONDITION_CHECKBOX("conquest_structures", ID_VC_ConquestStructures); - INSERT_VICTORY_CONDITION_CHECKBOX("capture_the_relic", ID_VC_CaptureTheRelic); - INSERT_VICTORY_CONDITION_CHECKBOX("wonder", ID_VC_Wonder); - INSERT_VICTORY_CONDITION_CHECKBOX("regicide", ID_VC_Regicide); + for (const std::pair& vc : m_VictoryConditions) + INSERT_VICTORY_CONDITION_CHECKBOX(wxString::FromUTF8(vc.second["Data"]["Title"]).Lower().ToStdString(), vc.first) #undef INSERT_VICTORY_CONDITION_CHECKBOX Index: ps/trunk/source/tools/atlas/GameInterface/Handlers/MapHandlers.cpp =================================================================== --- ps/trunk/source/tools/atlas/GameInterface/Handlers/MapHandlers.cpp +++ ps/trunk/source/tools/atlas/GameInterface/Handlers/MapHandlers.cpp @@ -369,4 +369,9 @@ #undef GET_FILE_LIST } +QUERYHANDLER(GetVictoryConditionData) +{ + msg->data = g_Game->GetSimulation2()->GetVictoryConditiondData(); +} + } Index: ps/trunk/source/tools/atlas/GameInterface/Messages.h =================================================================== --- ps/trunk/source/tools/atlas/GameInterface/Messages.h +++ ps/trunk/source/tools/atlas/GameInterface/Messages.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 Wildfire Games. +/* Copyright (C) 2020 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -224,6 +224,11 @@ ((std::vector, data)) ); +QUERY(GetVictoryConditionData, + , + ((std::vector, data)) + ); + QUERY(GetPlayerDefaults, , ((std::string, defaults))