Index: source/graphics/MapReader.cpp =================================================================== --- source/graphics/MapReader.cpp +++ source/graphics/MapReader.cpp @@ -28,6 +28,7 @@ #include "graphics/Terrain.h" #include "graphics/TerrainTextureEntry.h" #include "graphics/TerrainTextureManager.h" +#include "graphics/Unit.h" #include "lib/timer.h" #include "lib/external_libraries/libsdl.h" #include "maths/MathUtil.h" @@ -424,6 +425,8 @@ int at_angle; int at_uid; int at_seed; + int el_variations; + int el_variation; XMBElementList nodes; // children of root @@ -476,6 +479,8 @@ AT(angle); AT(uid); AT(seed); + EL(variations); + EL(variation); #undef AT #undef EL @@ -953,6 +958,7 @@ CFixedVector3D Position; CFixedVector3D Orientation; long Seed = -1; + std::set actorSelections; // Obstruction control groups. entity_id_t ControlGroup = INVALID_ENTITY; @@ -1019,6 +1025,20 @@ Seed = seedStr.ToLong(); ENSURE(Seed >= 0); } + + XMBElementList childActors = setting.GetChildNodes(); + if (childActors.size() > 1) + LOGERROR("Failed to load variations from actor(more than one child) template '%s'", utf8_from_wstring(TemplateName)); + else if (childActors.size() == 1) + { + XMBElement variations = childActors[0]; + ENSURE(variations.GetNodeName() == el_variations); + XERO_ITER_EL(variations, variation) + { + ENSURE(variation.GetNodeName() == el_variation); + actorSelections.insert(variation.GetText()); + } + } } else debug_warn(L"Invalid map XML data"); @@ -1070,7 +1090,13 @@ { if (Seed != -1) cmpVisual->SetActorSeed((u32)Seed); - // TODO: variation/selection strings + + if (!actorSelections.empty()) + { + CUnit* unit = cmpVisual->GetUnit(); + if (unit) + unit->SetActorSelections(actorSelections); + } } if (PlayerID == m_MapReader.m_PlayerID && (boost::algorithm::ends_with(TemplateName, L"civil_centre") || m_MapReader.m_StartingCameraTarget == INVALID_ENTITY)) Index: source/graphics/MapWriter.cpp =================================================================== --- source/graphics/MapWriter.cpp +++ source/graphics/MapWriter.cpp @@ -27,6 +27,7 @@ #include "Terrain.h" #include "TerrainTextureEntry.h" #include "TerrainTextureManager.h" +#include "Unit.h" #include "maths/MathUtil.h" #include "maths/NUSpline.h" @@ -404,12 +405,22 @@ if (cmpVisual) { entity_id_t seed = static_cast(cmpVisual->GetActorSeed()); + XMLWriter_Element actorTag(xmlMapFile, "Actor"); + if (seed != ent) - { - XMLWriter_Element actorTag(xmlMapFile, "Actor"); actorTag.Attribute("seed",seed); + + CUnit* unit = cmpVisual->GetUnit(); + if (unit) + { + const std::set& selections = unit->GetActorSelections(); + if (!selections.empty()) + { + XMLWriter_Element variationsTag(xmlMapFile, "Variations"); + for (const CStr& selection: selections) + variationsTag.Setting("Variation", selection); + } } - // TODO: variation/selection strings } } } Index: source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Object/Object.cpp =================================================================== --- source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Object/Object.cpp +++ source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Object/Object.cpp @@ -603,26 +603,25 @@ wxComboBox* playerSelect = new PlayerComboBox(this, objectSettings, mapSettings); playerSelectionSizer->Add(new wxStaticText(this, wxID_ANY, _("Player:")), wxSizerFlags().Align(wxALIGN_CENTER)); playerSelectionSizer->AddSpacer(3); - playerSelectionSizer->Add(playerSelect); + playerSelectionSizer->Add(playerSelect, wxSizerFlags().Proportion(1).Expand()); - playerVariationSizer->Add(playerSelectionSizer); + playerVariationSizer->AddSpacer(3); + playerVariationSizer->Add(playerSelectionSizer, wxSizerFlags().Expand()); playerVariationSizer->AddSpacer(3); wxWindow* variationSelect = new VariationControl(this, objectSettings); - variationSelect->SetMinSize(wxSize(160, -1)); wxSizer* variationSizer = new wxStaticBoxSizer(wxVERTICAL, this, _("Variation")); variationSizer->Add(variationSelect, wxSizerFlags().Proportion(1).Expand()); - playerVariationSizer->Add(variationSizer, wxSizerFlags().Proportion(1)); + playerVariationSizer->Add(variationSizer, wxSizerFlags().Proportion(1).Expand()); mainSizer->AddSpacer(3); - mainSizer->Add(playerVariationSizer, wxSizerFlags().Expand()); + mainSizer->Add(playerVariationSizer, wxSizerFlags().Proportion(1).Expand()); // ---------------------------------------------------------------------------------- // --- display template name wxSizer* displaySizer = new wxStaticBoxSizer(wxVERTICAL, this, _("Selected entities")); m_TemplateNames = new wxScrolledWindow(this); - m_TemplateNames->SetMinSize(wxSize(250, -1)); m_TemplateNames->SetScrollRate(0, 5); wxSizer* scrollwindowSizer = new wxBoxSizer(wxVERTICAL); m_TemplateNames->SetSizer(scrollwindowSizer); Index: source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Object/VariationControl.h =================================================================== --- source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Object/VariationControl.h +++ source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Object/VariationControl.h @@ -30,7 +30,6 @@ private: void OnSelect(wxCommandEvent& evt); void OnObjectSettingsChange(const ObjectSettings& settings); - void RefreshObjectSettings(); ObservableScopedConnection m_Conn; Index: source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Object/VariationControl.cpp =================================================================== --- source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Object/VariationControl.cpp +++ source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Object/VariationControl.cpp @@ -65,8 +65,7 @@ } m_ObjectSettings.SetActorSelections(selections); - m_ObjectSettings.NotifyObserversExcept(m_Conn); - RefreshObjectSettings(); + m_ObjectSettings.NotifyObservers(); } void VariationControl::OnObjectSettingsChange(const ObjectSettings& settings) @@ -130,17 +129,3 @@ // Make the scrollbars appear when appropriate FitInside(); } - -void VariationControl::RefreshObjectSettings() -{ - const std::vector& variation = m_ObjectSettings.GetActorVariation(); - - // For each group, set the corresponding combobox's value to the chosen one - size_t i = 0; - for (std::vector::const_iterator group = variation.begin(); - group != variation.end() && i < m_ComboBoxes.size(); - ++group, ++i) - { - m_ComboBoxes[i]->SetValue(group->chosen); - } -} Index: source/tools/atlas/AtlasUI/ScenarioEditor/Tools/Common/ObjectSettings.cpp =================================================================== --- source/tools/atlas/AtlasUI/ScenarioEditor/Tools/Common/ObjectSettings.cpp +++ source/tools/atlas/AtlasUI/ScenarioEditor/Tools/Common/ObjectSettings.cpp @@ -110,40 +110,41 @@ // TODO: what would be the sensible action if nothing's selected? // and if multiple objects are selected? - if (selection.empty()) - return; - - AtlasMessage::qGetObjectSettings qry (m_View, selection[0]); - qry.Post(); - - m_PlayerID = qry.settings->player; - m_ActorSelections.clear(); m_VariantGroups.clear(); - - std::vector > variation = *qry.settings->variantGroups; - for (std::vector >::iterator grp = variation.begin(); - grp != variation.end(); - ++grp) + m_PlayerID = 0; + // we need to inform about settings changes and now is empty + if (!selection.empty()) { - wxArrayString variants; + AtlasMessage::qGetObjectSettings qry (m_View, selection[0]); + qry.Post(); + + m_PlayerID = qry.settings->player; - for (std::vector::iterator it = grp->begin(); - it != grp->end(); - ++it) + std::vector > variation = *qry.settings->variantGroups; + for (std::vector >::iterator grp = variation.begin(); + grp != variation.end(); + ++grp) { - variants.Add(it->c_str()); - } + wxArrayString variants; - m_VariantGroups.push_back(variants); - } + for (std::vector::iterator it = grp->begin(); + it != grp->end(); + ++it) + { + variants.Add(it->c_str()); + } - std::vector selections = *qry.settings->selections; - for (std::vector::iterator sel = selections.begin(); - sel != selections.end(); - ++sel) - { - m_ActorSelections.insert(sel->c_str()); + m_VariantGroups.push_back(variants); + } + + std::vector selections = *qry.settings->selections; + for (std::vector::iterator sel = selections.begin(); + sel != selections.end(); + ++sel) + { + m_ActorSelections.insert(sel->c_str()); + } } static_cast*>(this)->NotifyObservers(); Index: source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp =================================================================== --- source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp +++ source/tools/atlas/GameInterface/Handlers/ObjectHandlers.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 @@ -203,47 +203,51 @@ settings.player = player; } - // TODO: selections - -/* // Get the unit's possible variants and selected variants - std::vector > groups = unit->GetObject().m_Base->GetVariantGroups(); - const std::set& selections = unit->GetActorSelections(); - - // Iterate over variant groups std::vector > variantgroups; std::set selections_set; - variantgroups.reserve(groups.size()); - for (size_t i = 0; i < groups.size(); ++i) + + CmpPtr cmpVisualActor(*simulation, view->GetEntityId(msg->id)); + if (cmpVisualActor) { - // Copy variants into output structure + CUnit* unit = cmpVisualActor->GetUnit(); + if (unit) + { + std::vector> groups = unit->GetObject().m_Base->GetVariantGroups(); + const std::set& selections = unit->GetActorSelections(); + variantgroups.reserve(groups.size()); - std::vector group; - group.reserve(groups[i].size()); - int choice = -1; + for (size_t i = 0; i < groups.size(); ++i) + { + // Copy variants into output structure - for (size_t j = 0; j < groups[i].size(); ++j) - { - group.push_back(CStrW(groups[i][j])); + std::vector subgroup; + subgroup.reserve(groups[i].size()); + int choice = -1; - // Find the first string in 'selections' that matches one of this - // group's variants - if (choice == -1) - if (selections.find(groups[i][j]) != selections.end()) - choice = (int)j; - } + for (size_t j = 0; j < groups[i].size(); ++j) + { + subgroup.push_back(wstring_from_utf8(groups[i][j])); - // Assuming one of the variants was selected (which it really ought - // to be), remember that one's name - if (choice != -1) - selections_set.insert(CStrW(groups[i][choice])); + // Find the first string in 'selections' that matches one of this + // group's variants + if (choice == -1) + if (selections.find(groups[i][j]) != selections.end()) + choice = (int)j; + } + + // Assuming one of the variants was selected (which it really ought + // to be), remember that one's name + if (choice != -1) + selections_set.insert(wstring_from_utf8(groups[i][choice])); - variantgroups.push_back(group); + variantgroups.push_back(subgroup); + } + } } - settings.variantgroups = variantgroups; + settings.variantGroups = variantgroups; settings.selections = std::vector (selections_set.begin(), selections_set.end()); // convert set->vector -*/ msg->settings = settings; } @@ -325,8 +329,13 @@ m_PlayerOld = player; } - // TODO: selections -// m_SelectionsOld = unit->GetActorSelections(); + CmpPtr cmpVisualActor(*simulation, view->GetEntityId(msg->id)); + if (cmpVisualActor) + { + CUnit* unit = cmpVisualActor->GetUnit(); + if (unit) + m_SelectionsOld = unit->GetActorSelections(); + } m_PlayerNew = (player_id_t)settings.player; @@ -350,7 +359,7 @@ } private: - void Set(player_id_t player, const std::set& UNUSED(selections)) + void Set(player_id_t player, const std::set& selections) { AtlasView* view = AtlasView::GetView(msg->view); CSimulation2* simulation = view->GetSimulation2(); @@ -359,8 +368,13 @@ if (cmpOwnership) cmpOwnership->SetOwner(player); - // TODO: selections -// unit->SetActorSelections(selections); + CmpPtr cmpVisualActor(*simulation, view->GetEntityId(msg->id)); + if (cmpVisualActor) + { + CUnit* unit = cmpVisualActor->GetUnit(); + if (unit) + unit->SetActorSelections(selections); + } } }; END_COMMAND(SetObjectSettings);