0ad/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Object/Object.cpp
Ykkrosh 76e957ed78 Fixed compilation errors.
Slightly tidied Atlas code.
Removed old unused ScEd code.

This was SVN commit r4389.
2006-09-24 15:59:33 +00:00

336 lines
9.1 KiB
C++

#include "stdafx.h"
#include "Object.h"
#include "Buttons/ToolButton.h"
#include "ScenarioEditor/Tools/Common/Tools.h"
#include "ScenarioEditor/Tools/Common/ObjectSettings.h"
#include "ScenarioEditor/Tools/Common/MiscState.h"
#include "GameInterface/Messages.h"
#include "wx/busyinfo.h"
class ObjectSelectListBox : public wxListBox
{
public:
ObjectSelectListBox(wxWindow* parent)
: wxListBox(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_SINGLE|wxLB_HSCROLL)
{
}
void OnSelect(wxCommandEvent& evt)
{
// On selecting an object, enable the PlaceObject tool with this object
wxString id = static_cast<wxStringClientData*>(evt.GetClientObject())->GetData();
SetCurrentTool(_T("PlaceObject"), &id);
}
private:
DECLARE_EVENT_TABLE();
};
BEGIN_EVENT_TABLE(ObjectSelectListBox, wxListBox)
EVT_LISTBOX(wxID_ANY, ObjectSelectListBox::OnSelect)
END_EVENT_TABLE();
class ObjectChoiceCtrl : public wxChoice
{
public:
ObjectChoiceCtrl(wxWindow* parent, const wxArrayString& strings, ObjectSidebar& sidebar)
: wxChoice(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, strings),
m_Sidebar(sidebar)
{
SetSelection(0);
}
void OnSelect(wxCommandEvent& evt)
{
// Switch between displayed lists of objects (e.g. entities vs actors)
m_Sidebar.SetObjectFilter(evt.GetSelection());
}
private:
ObjectSidebar& m_Sidebar;
DECLARE_EVENT_TABLE();
};
BEGIN_EVENT_TABLE(ObjectChoiceCtrl, wxChoice)
EVT_CHOICE(wxID_ANY, ObjectChoiceCtrl::OnSelect)
END_EVENT_TABLE();
//////////////////////////////////////////////////////////////////////////
class ObjectBottomBar : public wxPanel
{
public:
ObjectBottomBar(wxWindow* parent);
};
struct ObjectSidebarImpl
{
ObjectSidebarImpl() : m_BottomBar(NULL), m_ObjectListBox(NULL) { }
wxWindow* m_BottomBar;
wxListBox* m_ObjectListBox;
std::vector<AtlasMessage::sObjectsListItem> m_Objects;
};
ObjectSidebar::ObjectSidebar(wxWindow* sidebarContainer, wxWindow* bottomBarContainer)
: Sidebar(sidebarContainer, bottomBarContainer), p(new ObjectSidebarImpl())
{
wxArrayString strings;
strings.Add(_("Entities"));
strings.Add(_("Actors (all)"));
m_MainSizer->Add(new ObjectChoiceCtrl(this, strings, *this), wxSizerFlags().Expand());
p->m_ObjectListBox = new ObjectSelectListBox(this);
m_MainSizer->Add(p->m_ObjectListBox, wxSizerFlags().Proportion(1).Expand());
m_BottomBar = new ObjectBottomBar(bottomBarContainer);
}
ObjectSidebar::~ObjectSidebar()
{
delete p;
}
void ObjectSidebar::OnFirstDisplay()
{
wxBusyInfo busy (_("Loading list of objects"));
// Get the list of objects from the game
AtlasMessage::qGetObjectsList qry;
qry.Post();
p->m_Objects = *qry.objects;
// Display first group of objects
SetObjectFilter(0);
}
void ObjectSidebar::SetObjectFilter(int type)
{
p->m_ObjectListBox->Freeze();
p->m_ObjectListBox->Clear();
for (std::vector<AtlasMessage::sObjectsListItem>::iterator it = p->m_Objects.begin(); it != p->m_Objects.end(); ++it)
{
if (it->type == type)
{
wxString id = it->id.c_str();
wxString name = it->name.c_str();
p->m_ObjectListBox->Append(name, new wxStringClientData(id));
}
}
p->m_ObjectListBox->Thaw();
}
//////////////////////////////////////////////////////////////////////////
class PlayerComboBox : public wxComboBox
{
public:
PlayerComboBox(wxWindow* parent, wxArrayString& choices)
: wxComboBox(parent, -1, choices[g_ObjectSettings.GetPlayerID()], wxDefaultPosition, wxDefaultSize, choices, wxCB_READONLY)
{
m_Conn = g_ObjectSettings.RegisterObserver(1, &PlayerComboBox::OnObjectSettingsChange, this);
}
~PlayerComboBox()
{
g_ObjectSettings.RemoveObserver(m_Conn);
}
private:
ObservableConnection m_Conn;
void OnObjectSettingsChange(const ObjectSettings& settings)
{
SetSelection(settings.GetPlayerID());
}
void OnSelect(wxCommandEvent& evt)
{
g_ObjectSettings.SetPlayerID(evt.GetInt());
g_ObjectSettings.NotifyObserversExcept(m_Conn);
}
DECLARE_EVENT_TABLE();
};
BEGIN_EVENT_TABLE(PlayerComboBox, wxComboBox)
EVT_COMBOBOX(wxID_ANY, OnSelect)
END_EVENT_TABLE();
class VariationDisplay : public wxScrolledWindow
{
public:
VariationDisplay(wxWindow* parent)
: wxScrolledWindow(parent, -1)
{
m_Conn = g_ObjectSettings.RegisterObserver(1, &VariationDisplay::OnObjectSettingsChange, this);
SetMinSize(wxSize(160, wxDefaultCoord));
SetScrollRate(0, 5);
m_Sizer = new wxBoxSizer(wxVERTICAL);
SetSizer(m_Sizer);
}
~VariationDisplay()
{
g_ObjectSettings.RemoveObserver(m_Conn);
}
private:
ObservableConnection m_Conn;
std::vector<wxWindow*> m_ComboBoxes;
wxSizer* m_Sizer;
// Event handler shared by all the combo boxes created by this window
void OnSelect(wxCommandEvent& evt)
{
std::set<wxString> selections;
// It's possible for a variant name to appear in multiple groups.
// If so, assume that all the names in each group are the same, so
// we don't have to worry about some impossible combinations (e.g.
// one group "a,b", a second "b,c", and a third "c,a", where's there's
// no set of selections that matches one (and only one) of each group).
//
// So... When a combo box is changed from 'a' to 'b', add 'b' to the new
// selections and make sure any other combo boxes containing both 'a' and
// 'b' no longer contain 'a'.
wxComboBox* thisComboBox = wxDynamicCast(evt.GetEventObject(), wxComboBox);
wxString newValue = thisComboBox->GetValue();
selections.insert(newValue);
for (size_t i = 0; i < m_ComboBoxes.size(); ++i)
{
wxComboBox* comboBox = wxDynamicCast(m_ComboBoxes[i], wxComboBox);
wxCHECK(comboBox != NULL, );
// If our newly selected value is used in another combobox, we want
// that combobox to use the new value, so don't add its old value
// to the list of selections
if (comboBox->FindString(newValue) == wxNOT_FOUND)
selections.insert(comboBox->GetValue());
}
g_ObjectSettings.SetActorSelections(selections);
g_ObjectSettings.NotifyObserversExcept(m_Conn);
RefreshObjectSettings();
}
void OnObjectSettingsChange(const ObjectSettings& settings)
{
Freeze();
const std::vector<ObjectSettings::Group>& variation = settings.GetActorVariation();
// Creating combo boxes seems to be pretty expensive - so we create as
// few as possible, by never deleting any.
size_t oldCount = m_ComboBoxes.size();
size_t newCount = variation.size();
// If we have too many combo boxes, hide the excess ones
for (size_t i = newCount; i < oldCount; ++i)
{
m_ComboBoxes[i]->Show(false);
}
for (size_t i = 0; i < variation.size(); ++i)
{
const ObjectSettings::Group& group = variation[i];
if (i < oldCount)
{
// Already got enough boxes available, so use an old one
wxComboBox* comboBox = wxDynamicCast(m_ComboBoxes[i], wxComboBox);
wxCHECK(comboBox != NULL, );
// Replace the contents of the old combobox with the new data
comboBox->Freeze();
comboBox->Clear();
comboBox->Append(group.variants);
comboBox->SetValue(group.chosen);
comboBox->Show(true);
comboBox->Thaw();
}
else
{
// Create an initially empty combobox, because we can fill it
// quicker than the default constructor can
wxComboBox* combo = new wxComboBox(this, -1, wxEmptyString, wxDefaultPosition,
wxSize(130, wxDefaultCoord), wxArrayString(), wxCB_READONLY);
// Freeze it before adding all the values
combo->Freeze();
combo->Append(group.variants);
combo->SetValue(group.chosen);
combo->Thaw();
// Add the on-select event handler
combo->Connect(wxID_ANY, wxEVT_COMMAND_COMBOBOX_SELECTED,
wxCommandEventHandler(VariationDisplay::OnSelect), NULL, this);
// Add box to sizer and list
m_Sizer->Add(combo);
m_ComboBoxes.push_back(combo);
}
}
Layout();
// Make the scrollbars appear when appropriate
FitInside();
Thaw();
}
void RefreshObjectSettings()
{
const std::vector<ObjectSettings::Group>& variation = g_ObjectSettings.GetActorVariation();
// For each group, set the corresponding combobox's value to the chosen one
size_t i = 0;
for (std::vector<ObjectSettings::Group>::const_iterator group = variation.begin();
group != variation.end() && i < m_ComboBoxes.size();
++group, ++i)
{
wxComboBox* comboBox = wxDynamicCast(m_ComboBoxes[i], wxComboBox);
wxCHECK(comboBox != NULL, );
comboBox->SetValue(group->chosen);
}
}
};
//////////////////////////////////////////////////////////////////////////
ObjectBottomBar::ObjectBottomBar(wxWindow* parent)
: wxPanel(parent, wxID_ANY)
{
wxSizer* sizer = new wxBoxSizer(wxVERTICAL);
wxArrayString players;
// TODO: get proper player names
players.Add(_("Gaia"));
players.Add(_("Player 1"));
players.Add(_("Player 2"));
players.Add(_("Player 3"));
players.Add(_("Player 4"));
players.Add(_("Player 5"));
players.Add(_("Player 6"));
players.Add(_("Player 7"));
players.Add(_("Player 8"));
wxComboBox* playerSelect = new PlayerComboBox(this, players);
sizer->Add(playerSelect);
wxWindow* variationSelect = new VariationDisplay(this);
wxSizer* variationSizer = new wxStaticBoxSizer(wxVERTICAL, this, _("Variation"));
variationSizer->Add(variationSelect, wxSizerFlags().Proportion(1).Expand());
sizer->Add(variationSizer, wxSizerFlags().Proportion(1));
SetSizer(sizer);
}