mirror of
https://gitea.wildfiregames.com/0ad/0ad
synced 2026-06-16 05:13:58 -07:00
Replace New dialog box with separate tools for resizing maps and replacing terrain textures, to provide more power and to simplify the problem of initialising map settings. Fix engine to cope with dynamic map resizing. Add JSON support to AtObj, to let C++ interact with JSON more easily. This was SVN commit r9566.
398 lines
13 KiB
C++
398 lines
13 KiB
C++
/* 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
|
|
* 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.
|
|
*
|
|
* 0 A.D. is distributed in the hope that it will be useful,
|
|
* 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
|
|
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "precompiled.h"
|
|
|
|
#include "Object.h"
|
|
|
|
#include "Buttons/ToolButton.h"
|
|
#include "ScenarioEditor/ScenarioEditor.h"
|
|
#include "ScenarioEditor/Tools/Common/ObjectSettings.h"
|
|
#include "ScenarioEditor/Tools/Common/MiscState.h"
|
|
#include "VariationControl.h"
|
|
|
|
#include "GameInterface/Messages.h"
|
|
|
|
#include "wx/busyinfo.h"
|
|
|
|
enum
|
|
{
|
|
ID_ObjectType = 1,
|
|
ID_SelectObject,
|
|
ID_ToggleViewer,
|
|
ID_ViewerWireframe,
|
|
ID_ViewerMove,
|
|
ID_ViewerGround,
|
|
ID_ViewerShadows,
|
|
ID_ViewerPolyCount,
|
|
ID_ViewerAnimation,
|
|
ID_ViewerPlay,
|
|
ID_ViewerPause,
|
|
ID_ViewerSlow
|
|
};
|
|
|
|
// Helper function for adding tooltips
|
|
static wxWindow* Tooltipped(wxWindow* window, const wxString& tip)
|
|
{
|
|
window->SetToolTip(tip);
|
|
return window;
|
|
}
|
|
|
|
class ObjectBottomBar : public wxPanel
|
|
{
|
|
public:
|
|
ObjectBottomBar(wxWindow* parent, Observable<ObjectSettings>& objectSettings, ObjectSidebarImpl* p);
|
|
|
|
void OnFirstDisplay();
|
|
|
|
void ShowActorViewer(bool show);
|
|
|
|
private:
|
|
void OnViewerSetting(wxCommandEvent& evt);
|
|
void OnSelectAnim(wxCommandEvent& evt);
|
|
void OnSpeed(wxCommandEvent& evt);
|
|
|
|
bool m_ViewerWireframe;
|
|
bool m_ViewerMove;
|
|
bool m_ViewerGround;
|
|
bool m_ViewerShadows;
|
|
bool m_ViewerPolyCount;
|
|
|
|
wxPanel* m_ViewerPanel;
|
|
|
|
ObjectSidebarImpl* p;
|
|
|
|
DECLARE_EVENT_TABLE();
|
|
};
|
|
|
|
struct ObjectSidebarImpl
|
|
{
|
|
ObjectSidebarImpl() :
|
|
m_ObjectListBox(NULL), m_ActorViewerActive(false),
|
|
m_ActorViewerEntity(_T("actor|structures/fndn_1x1.xml")), m_ActorViewerAnimation(_T("idle")), m_ActorViewerSpeed(0.f)
|
|
{
|
|
}
|
|
|
|
wxListBox* m_ObjectListBox;
|
|
std::vector<AtlasMessage::sObjectsListItem> m_Objects;
|
|
ObservableScopedConnection m_ToolConn;
|
|
|
|
bool m_ActorViewerActive;
|
|
wxString m_ActorViewerEntity;
|
|
wxString m_ActorViewerAnimation;
|
|
float m_ActorViewerSpeed;
|
|
|
|
void ActorViewerPostToGame()
|
|
{
|
|
POST_MESSAGE(SetActorViewer, (m_ActorViewerEntity.c_str(), m_ActorViewerAnimation.c_str(), m_ActorViewerSpeed, false));
|
|
}
|
|
};
|
|
|
|
ObjectSidebar::ObjectSidebar(ScenarioEditor& scenarioEditor, wxWindow* sidebarContainer, wxWindow* bottomBarContainer)
|
|
: Sidebar(scenarioEditor, sidebarContainer, bottomBarContainer), p(new ObjectSidebarImpl())
|
|
{
|
|
wxArrayString strings;
|
|
strings.Add(_("Entities"));
|
|
strings.Add(_("Actors (all)"));
|
|
wxChoice* objectType = new wxChoice(this, ID_ObjectType, wxDefaultPosition, wxDefaultSize, strings);
|
|
m_MainSizer->Add(objectType, wxSizerFlags().Expand());
|
|
|
|
p->m_ObjectListBox = new wxListBox(this, ID_SelectObject, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_SINGLE|wxLB_HSCROLL);
|
|
m_MainSizer->Add(p->m_ObjectListBox, wxSizerFlags().Proportion(1).Expand());
|
|
|
|
m_MainSizer->Add(new wxButton(this, ID_ToggleViewer, _("Switch to Actor Viewer")), wxSizerFlags().Expand());
|
|
|
|
m_BottomBar = new ObjectBottomBar(bottomBarContainer, scenarioEditor.GetObjectSettings(), p);
|
|
|
|
p->m_ToolConn = scenarioEditor.GetToolManager().GetCurrentTool().RegisterObserver(0, &ObjectSidebar::OnToolChange, this);
|
|
}
|
|
|
|
ObjectSidebar::~ObjectSidebar()
|
|
{
|
|
delete p;
|
|
}
|
|
|
|
void ObjectSidebar::OnToolChange(ITool* tool)
|
|
{
|
|
if (wxString(tool->GetClassInfo()->GetClassName()) == _T("ActorViewerTool"))
|
|
{
|
|
p->m_ActorViewerActive = true;
|
|
p->ActorViewerPostToGame();
|
|
}
|
|
else
|
|
{
|
|
p->m_ActorViewerActive = false;
|
|
}
|
|
|
|
static_cast<ObjectBottomBar*>(m_BottomBar)->ShowActorViewer(p->m_ActorViewerActive);
|
|
}
|
|
|
|
void ObjectSidebar::OnFirstDisplay()
|
|
{
|
|
static_cast<ObjectBottomBar*>(m_BottomBar)->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();
|
|
}
|
|
|
|
void ObjectSidebar::ToggleViewer(wxCommandEvent& WXUNUSED(evt))
|
|
{
|
|
if (p->m_ActorViewerActive)
|
|
m_ScenarioEditor.GetToolManager().SetCurrentTool(_T(""), NULL);
|
|
else
|
|
m_ScenarioEditor.GetToolManager().SetCurrentTool(_T("ActorViewerTool"), NULL);
|
|
}
|
|
|
|
void ObjectSidebar::OnSelectType(wxCommandEvent& evt)
|
|
{
|
|
// Switch between displayed lists of objects (e.g. entities vs actors)
|
|
SetObjectFilter(evt.GetSelection());
|
|
}
|
|
|
|
void ObjectSidebar::OnSelectObject(wxCommandEvent& evt)
|
|
{
|
|
if (evt.GetInt() < 0)
|
|
return;
|
|
|
|
wxString id = static_cast<wxStringClientData*>(evt.GetClientObject())->GetData();
|
|
|
|
// Always update the actor viewer's state even if it's inactive,
|
|
// so it will be correct when first enabled
|
|
p->m_ActorViewerEntity = id;
|
|
|
|
if (p->m_ActorViewerActive)
|
|
{
|
|
p->ActorViewerPostToGame();
|
|
}
|
|
else
|
|
{
|
|
// On selecting an object, enable the PlaceObject tool with this object
|
|
m_ScenarioEditor.GetToolManager().SetCurrentTool(_T("PlaceObject"), &id);
|
|
}
|
|
}
|
|
|
|
BEGIN_EVENT_TABLE(ObjectSidebar, Sidebar)
|
|
EVT_CHOICE(ID_ObjectType, ObjectSidebar::OnSelectType)
|
|
EVT_LISTBOX(ID_SelectObject, ObjectSidebar::OnSelectObject)
|
|
EVT_BUTTON(ID_ToggleViewer, ObjectSidebar::ToggleViewer)
|
|
END_EVENT_TABLE();
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
class PlayerComboBox : public wxComboBox
|
|
{
|
|
public:
|
|
PlayerComboBox(wxWindow* parent, wxArrayString& choices, Observable<ObjectSettings>& objectSettings)
|
|
: wxComboBox(parent, -1, choices[objectSettings.GetPlayerID()], wxDefaultPosition, wxDefaultSize, choices, wxCB_READONLY)
|
|
, m_ObjectSettings(objectSettings)
|
|
{
|
|
m_Conn = m_ObjectSettings.RegisterObserver(1, &PlayerComboBox::OnObjectSettingsChange, this);
|
|
}
|
|
|
|
private:
|
|
|
|
ObservableScopedConnection m_Conn;
|
|
Observable<ObjectSettings>& m_ObjectSettings;
|
|
|
|
void OnObjectSettingsChange(const ObjectSettings& settings)
|
|
{
|
|
SetSelection((long)settings.GetPlayerID());
|
|
}
|
|
|
|
void OnSelect(wxCommandEvent& evt)
|
|
{
|
|
m_ObjectSettings.SetPlayerID(evt.GetInt());
|
|
m_ObjectSettings.NotifyObserversExcept(m_Conn);
|
|
}
|
|
|
|
DECLARE_EVENT_TABLE();
|
|
};
|
|
BEGIN_EVENT_TABLE(PlayerComboBox, wxComboBox)
|
|
EVT_COMBOBOX(wxID_ANY, PlayerComboBox::OnSelect)
|
|
END_EVENT_TABLE();
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
ObjectBottomBar::ObjectBottomBar(wxWindow* parent, Observable<ObjectSettings>& objectSettings, ObjectSidebarImpl* p)
|
|
: wxPanel(parent, wxID_ANY), p(p)
|
|
{
|
|
m_ViewerWireframe = false;
|
|
m_ViewerMove = false;
|
|
m_ViewerGround = true;
|
|
m_ViewerShadows = true;
|
|
m_ViewerPolyCount = false;
|
|
|
|
wxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
|
|
|
|
|
|
m_ViewerPanel = new wxPanel(this, wxID_ANY);
|
|
wxSizer* viewerSizer = new wxBoxSizer(wxHORIZONTAL);
|
|
|
|
wxSizer* viewerButtonsSizer = new wxStaticBoxSizer(wxVERTICAL, m_ViewerPanel, _("Display settings"));
|
|
viewerButtonsSizer->SetMinSize(140, -1);
|
|
viewerButtonsSizer->Add(Tooltipped(new wxButton(m_ViewerPanel, ID_ViewerWireframe, _("Wireframe")), _("Toggle wireframe / solid rendering")), wxSizerFlags().Expand());
|
|
viewerButtonsSizer->Add(Tooltipped(new wxButton(m_ViewerPanel, ID_ViewerMove, _("Move")), _("Toggle movement along ground when playing walk/run animations")), wxSizerFlags().Expand());
|
|
viewerButtonsSizer->Add(Tooltipped(new wxButton(m_ViewerPanel, ID_ViewerGround, _("Ground")), _("Toggle the ground plane")), wxSizerFlags().Expand());
|
|
viewerButtonsSizer->Add(Tooltipped(new wxButton(m_ViewerPanel, ID_ViewerShadows, _("Shadows")), _("Toggle shadow rendering")), wxSizerFlags().Expand());
|
|
viewerButtonsSizer->Add(Tooltipped(new wxButton(m_ViewerPanel, ID_ViewerPolyCount, _("Poly count")), _("Toggle polygon-count statistics - turn off ground and shadows for more useful data")), wxSizerFlags().Expand());
|
|
viewerSizer->Add(viewerButtonsSizer, wxSizerFlags().Expand());
|
|
|
|
wxSizer* viewerAnimSizer = new wxStaticBoxSizer(wxVERTICAL, m_ViewerPanel, _("Animation"));
|
|
|
|
wxString animChoices[] = {
|
|
_T("idle"), _T("walk"), _T("run"), _T("melee"), _T("death"), _T("build"),
|
|
_T("gather_fruit"), _T("gather_grain"), _T("gather_meat"), _T("gather_tree"),
|
|
_T("gather_rock"), _T("gather_ore"), _T("gather_ruins"), _T("gather_treasure")
|
|
}; // TODO: this list should come from the actor
|
|
wxChoice* viewerAnimSelector = new wxChoice(m_ViewerPanel, ID_ViewerAnimation, wxDefaultPosition, wxDefaultSize, sizeof(animChoices)/sizeof(animChoices[0]), animChoices);
|
|
viewerAnimSizer->Add(viewerAnimSelector, wxSizerFlags().Expand());
|
|
|
|
wxSizer* viewerAnimSpeedSizer = new wxBoxSizer(wxHORIZONTAL);
|
|
viewerAnimSpeedSizer->Add(new wxButton(m_ViewerPanel, ID_ViewerPlay, _("Play"), wxDefaultPosition, wxSize(50, -1)), wxSizerFlags().Expand());
|
|
viewerAnimSpeedSizer->Add(new wxButton(m_ViewerPanel, ID_ViewerPause, _("Pause"), wxDefaultPosition, wxSize(50, -1)), wxSizerFlags().Expand());
|
|
viewerAnimSpeedSizer->Add(new wxButton(m_ViewerPanel, ID_ViewerSlow, _("Slow"), wxDefaultPosition, wxSize(50, -1)), wxSizerFlags().Expand());
|
|
viewerAnimSizer->Add(viewerAnimSpeedSizer);
|
|
|
|
viewerSizer->Add(viewerAnimSizer, wxSizerFlags().Expand());
|
|
|
|
m_ViewerPanel->SetSizer(viewerSizer);
|
|
sizer->Add(m_ViewerPanel, wxSizerFlags().Expand());
|
|
|
|
m_ViewerPanel->Show(false);
|
|
|
|
|
|
wxSizer* playerVariationSizer = 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, objectSettings);
|
|
// TODO: make this a wxChoice instead
|
|
playerVariationSizer->Add(playerSelect);
|
|
|
|
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));
|
|
|
|
sizer->Add(playerVariationSizer, wxSizerFlags().Expand());
|
|
|
|
SetSizer(sizer);
|
|
}
|
|
|
|
void ObjectBottomBar::OnFirstDisplay()
|
|
{
|
|
// Initialise the game with the default settings
|
|
POST_MESSAGE(SetViewParamB, (AtlasMessage::eRenderView::ACTOR, L"wireframe", m_ViewerWireframe));
|
|
POST_MESSAGE(SetViewParamB, (AtlasMessage::eRenderView::ACTOR, L"walk", m_ViewerMove));
|
|
POST_MESSAGE(SetViewParamB, (AtlasMessage::eRenderView::ACTOR, L"ground", m_ViewerGround));
|
|
POST_MESSAGE(SetViewParamB, (AtlasMessage::eRenderView::ACTOR, L"shadows", m_ViewerShadows));
|
|
POST_MESSAGE(SetViewParamB, (AtlasMessage::eRenderView::ACTOR, L"stats", m_ViewerPolyCount));
|
|
}
|
|
|
|
void ObjectBottomBar::ShowActorViewer(bool show)
|
|
{
|
|
m_ViewerPanel->Show(show);
|
|
Layout();
|
|
}
|
|
|
|
void ObjectBottomBar::OnViewerSetting(wxCommandEvent& evt)
|
|
{
|
|
switch (evt.GetId())
|
|
{
|
|
case ID_ViewerWireframe:
|
|
m_ViewerWireframe = !m_ViewerWireframe;
|
|
POST_MESSAGE(SetViewParamB, (AtlasMessage::eRenderView::ACTOR, L"wireframe", m_ViewerWireframe));
|
|
break;
|
|
case ID_ViewerMove:
|
|
m_ViewerMove = !m_ViewerMove;
|
|
POST_MESSAGE(SetViewParamB, (AtlasMessage::eRenderView::ACTOR, L"walk", m_ViewerMove));
|
|
break;
|
|
case ID_ViewerGround:
|
|
m_ViewerGround = !m_ViewerGround;
|
|
POST_MESSAGE(SetViewParamB, (AtlasMessage::eRenderView::ACTOR, L"ground", m_ViewerGround));
|
|
break;
|
|
case ID_ViewerShadows:
|
|
m_ViewerShadows = !m_ViewerShadows;
|
|
POST_MESSAGE(SetViewParamB, (AtlasMessage::eRenderView::ACTOR, L"shadows", m_ViewerShadows));
|
|
break;
|
|
case ID_ViewerPolyCount:
|
|
m_ViewerPolyCount = !m_ViewerPolyCount;
|
|
POST_MESSAGE(SetViewParamB, (AtlasMessage::eRenderView::ACTOR, L"stats", m_ViewerPolyCount));
|
|
break;
|
|
}
|
|
}
|
|
|
|
void ObjectBottomBar::OnSelectAnim(wxCommandEvent& evt)
|
|
{
|
|
p->m_ActorViewerAnimation = evt.GetString();
|
|
p->ActorViewerPostToGame();
|
|
}
|
|
|
|
void ObjectBottomBar::OnSpeed(wxCommandEvent& evt)
|
|
{
|
|
switch (evt.GetId())
|
|
{
|
|
case ID_ViewerPlay: p->m_ActorViewerSpeed = 1.0f; break;
|
|
case ID_ViewerPause: p->m_ActorViewerSpeed = 0.0f; break;
|
|
case ID_ViewerSlow: p->m_ActorViewerSpeed = 0.1f; break;
|
|
}
|
|
p->ActorViewerPostToGame();
|
|
}
|
|
|
|
BEGIN_EVENT_TABLE(ObjectBottomBar, wxPanel)
|
|
EVT_BUTTON(ID_ViewerWireframe, ObjectBottomBar::OnViewerSetting)
|
|
EVT_BUTTON(ID_ViewerMove, ObjectBottomBar::OnViewerSetting)
|
|
EVT_BUTTON(ID_ViewerGround, ObjectBottomBar::OnViewerSetting)
|
|
EVT_BUTTON(ID_ViewerShadows, ObjectBottomBar::OnViewerSetting)
|
|
EVT_BUTTON(ID_ViewerPolyCount, ObjectBottomBar::OnViewerSetting)
|
|
EVT_CHOICE(ID_ViewerAnimation, ObjectBottomBar::OnSelectAnim)
|
|
EVT_BUTTON(ID_ViewerPlay, ObjectBottomBar::OnSpeed)
|
|
EVT_BUTTON(ID_ViewerPause, ObjectBottomBar::OnSpeed)
|
|
EVT_BUTTON(ID_ViewerSlow, ObjectBottomBar::OnSpeed)
|
|
END_EVENT_TABLE();
|