1 /* Copyright (C) 2017 Wildfire Games.
2 * This file is part of 0 A.D.
3 *
4 * 0 A.D. is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * 0 A.D. is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include "precompiled.h"
19
20 #include "Object.h"
21
22 #include "Buttons/ToolButton.h"
23 #include "General/Datafile.h"
24 #include "ScenarioEditor/ScenarioEditor.h"
25 #include "ScenarioEditor/Tools/Common/ObjectSettings.h"
26 #include "ScenarioEditor/Tools/Common/MiscState.h"
27 #include "VariationControl.h"
28
29 #include "GameInterface/Messages.h"
30
31 #include "wx/busyinfo.h"
32
33 enum
34 {
35 ID_ObjectType = 1,
36 ID_ObjectFilter,
37 ID_PlayerSelect,
38 ID_SelectObject,
39 ID_ToggleViewer,
40 ID_ViewerWireframe,
41 ID_ViewerMove,
42 ID_ViewerGround,
43 ID_ViewerWater,
44 ID_ViewerShadows,
45 ID_ViewerPolyCount,
46 ID_ViewerAnimation,
47 ID_ViewerBoundingBox,
48 ID_ViewerAxesMarker,
49 ID_ViewerPropPoints,
50 ID_ViewerPlay,
51 ID_ViewerPause,
52 ID_ViewerSlow
53 };
54
55 // Helper function for adding tooltips
Tooltipped(wxWindow * window,const wxString & tip)56 static wxWindow* Tooltipped(wxWindow* window, const wxString& tip)
57 {
58 window->SetToolTip(tip);
59 return window;
60 }
61
62 class ObjectBottomBar : public wxPanel
63 {
64 public:
65 ObjectBottomBar(
66 wxWindow* parent,
67 Observable<ObjectSettings>& objectSettings,
68 Observable<AtObj>& mapSettings,
69 ObjectSidebarImpl* p
70 );
71
72 void OnFirstDisplay();
73 void ShowActorViewer(bool show);
74 void OnSelectedObjectsChange(const std::vector<AtlasMessage::ObjectID>& selectedObjects);
75
76 private:
77 void OnViewerSetting(wxCommandEvent& evt);
78 void OnSelectAnim(wxCommandEvent& evt);
79 void OnSpeed(wxCommandEvent& evt);
80
81 bool m_ViewerWireframe;
82 bool m_ViewerMove;
83 bool m_ViewerGround;
84 bool m_ViewerWater;
85 bool m_ViewerShadows;
86 bool m_ViewerPolyCount;
87 bool m_ViewerBoundingBox;
88 bool m_ViewerAxesMarker;
89 int m_ViewerPropPointsMode; // 0 disabled, 1 for point markers, 2 for point markers + axes
90
91 wxPanel* m_ViewerPanel;
92 wxScrolledWindow* m_TemplateNames;
93
94 ObjectSidebarImpl* p;
95 DECLARE_EVENT_TABLE();
96 };
97
98 struct ObjectSidebarImpl
99 {
ObjectSidebarImplObjectSidebarImpl100 ObjectSidebarImpl(ScenarioEditor& scenarioEditor) :
101 m_ObjectListBox(NULL), m_ActorViewerActive(false),
102 m_ActorViewerEntity(_T("actor|structures/fndn_1x1.xml")),
103 m_ActorViewerAnimation(_T("idle")), m_ActorViewerSpeed(0.f),
104 m_ObjectSettings(scenarioEditor.GetObjectSettings())
105 {
106 }
107
108 wxListBox* m_ObjectListBox;
109 std::vector<AtlasMessage::sObjectsListItem> m_Objects;
110 ObservableScopedConnection m_ToolConn;
111
112 bool m_ActorViewerActive;
113 wxString m_ActorViewerEntity;
114 wxString m_ActorViewerAnimation;
115 float m_ActorViewerSpeed;
116 Observable<ObjectSettings>& m_ObjectSettings;
117
ActorViewerPostToGameObjectSidebarImpl118 void ActorViewerPostToGame()
119 {
120 POST_MESSAGE(SetActorViewer, ((std::wstring)m_ActorViewerEntity.wc_str(), (std::wstring)m_ActorViewerAnimation.wc_str(), m_ObjectSettings.GetPlayerID(), m_ActorViewerSpeed, false));
121 }
122 };
123
ObjectSidebar(ScenarioEditor & scenarioEditor,wxWindow * sidebarContainer,wxWindow * bottomBarContainer)124 ObjectSidebar::ObjectSidebar(
125 ScenarioEditor& scenarioEditor,
126 wxWindow* sidebarContainer,
127 wxWindow* bottomBarContainer
128 )
129 : Sidebar(scenarioEditor, sidebarContainer, bottomBarContainer),
130 p(new ObjectSidebarImpl(scenarioEditor))
131 {
132 wxSizer* scrollSizer = new wxBoxSizer(wxVERTICAL);
133 wxScrolledWindow* scrolledWindow = new wxScrolledWindow(this);
134 scrolledWindow->SetScrollRate(10, 10);
135 scrolledWindow->SetSizer(scrollSizer);
136 m_MainSizer->Add(scrolledWindow, wxSizerFlags().Proportion(1).Expand());
137
138 wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
139 sizer->Add(new wxStaticText(scrolledWindow, wxID_ANY, _("Filter")), wxSizerFlags().Align(wxALIGN_CENTER));
140 sizer->Add(
141 Tooltipped(
142 new wxTextCtrl(scrolledWindow, ID_ObjectFilter),
143 _("Enter text to filter object list")
144 ),
145 wxSizerFlags().Expand().Proportion(1)
146 );
147 scrollSizer->Add(sizer, wxSizerFlags().Expand());
148 scrollSizer->AddSpacer(3);
149
150 // ------------------------------------------------------------------------------------------
151
152 wxArrayString strings;
153 strings.Add(_("Entities"));
154 strings.Add(_("Actors (all)"));
155 wxChoice* objectType = new wxChoice(scrolledWindow, ID_ObjectType, wxDefaultPosition, wxDefaultSize, strings);
156 objectType->SetSelection(0);
157 scrollSizer->Add(objectType, wxSizerFlags().Expand());
158 scrollSizer->AddSpacer(3);
159
160 // ------------------------------------------------------------------------------------------
161
162 p->m_ObjectListBox = new wxListBox(scrolledWindow, ID_SelectObject, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_SINGLE|wxLB_HSCROLL);
163 scrollSizer->Add(p->m_ObjectListBox, wxSizerFlags().Proportion(1).Expand());
164 scrollSizer->AddSpacer(3);
165
166 // ------------------------------------------------------------------------------------------
167
168 scrollSizer->Add(new wxButton(scrolledWindow, ID_ToggleViewer, _("Switch to Actor Viewer")), wxSizerFlags().Expand());
169
170 // ------------------------------------------------------------------------------------------
171
172 m_BottomBar = new ObjectBottomBar(
173 bottomBarContainer,
174 scenarioEditor.GetObjectSettings(),
175 scenarioEditor.GetMapSettings(),
176 p
177 );
178
179 p->m_ToolConn = scenarioEditor.GetToolManager().GetCurrentTool().RegisterObserver(0, &ObjectSidebar::OnToolChange, this);
180 }
181
~ObjectSidebar()182 ObjectSidebar::~ObjectSidebar()
183 {
184 delete p;
185 }
186
OnToolChange(ITool * tool)187 void ObjectSidebar::OnToolChange(ITool* tool)
188 {
189 if (wxString(tool->GetClassInfo()->GetClassName()) == _T("ActorViewerTool"))
190 {
191 p->m_ActorViewerActive = true;
192 p->ActorViewerPostToGame();
193 wxDynamicCast(FindWindow(ID_ToggleViewer), wxButton)->SetLabel(_("Return to game view"));
194 }
195 else
196 {
197 p->m_ActorViewerActive = false;
198 wxDynamicCast(FindWindow(ID_ToggleViewer), wxButton)->SetLabel(_("Switch to Actor Viewer"));
199 }
200
201 static_cast<ObjectBottomBar*>(m_BottomBar)->ShowActorViewer(p->m_ActorViewerActive);
202 }
203
OnFirstDisplay()204 void ObjectSidebar::OnFirstDisplay()
205 {
206 static_cast<ObjectBottomBar*>(m_BottomBar)->OnFirstDisplay();
207
208 wxBusyInfo busy (_("Loading list of objects"));
209
210 // Get the list of objects from the game
211 AtlasMessage::qGetObjectsList qry;
212 qry.Post();
213 p->m_Objects = *qry.objects;
214 // Display first group of objects
215 FilterObjects();
216 }
217
FilterObjects()218 void ObjectSidebar::FilterObjects()
219 {
220 int filterType = wxDynamicCast(FindWindow(ID_ObjectType), wxChoice)->GetSelection();
221 wxString filterName = wxDynamicCast(FindWindow(ID_ObjectFilter), wxTextCtrl)->GetValue();
222
223 p->m_ObjectListBox->Freeze();
224 p->m_ObjectListBox->Clear();
225 for (std::vector<AtlasMessage::sObjectsListItem>::iterator it = p->m_Objects.begin(); it != p->m_Objects.end(); ++it)
226 {
227 if (it->type == filterType)
228 {
229 wxString id = it->id.c_str();
230 wxString name = it->name.c_str();
231
232 if (name.Lower().Find(filterName.Lower()) != wxNOT_FOUND)
233 {
234 p->m_ObjectListBox->Append(name, new wxStringClientData(id));
235 }
236 }
237 }
238 p->m_ObjectListBox->Thaw();
239 }
240
OnToggleViewer(wxCommandEvent & WXUNUSED (evt))241 void ObjectSidebar::OnToggleViewer(wxCommandEvent& WXUNUSED(evt))
242 {
243 if (p->m_ActorViewerActive)
244 {
245 m_ScenarioEditor.GetToolManager().SetCurrentTool(_T(""), NULL);
246 }
247 else
248 {
249 m_ScenarioEditor.GetToolManager().SetCurrentTool(_T("ActorViewerTool"), NULL);
250 }
251 }
252
OnSelectType(wxCommandEvent & WXUNUSED (evt))253 void ObjectSidebar::OnSelectType(wxCommandEvent& WXUNUSED(evt))
254 {
255 FilterObjects();
256 }
257
OnSelectObject(wxCommandEvent & evt)258 void ObjectSidebar::OnSelectObject(wxCommandEvent& evt)
259 {
260 if (evt.GetInt() < 0)
261 return;
262
263 wxString id = static_cast<wxStringClientData*>(evt.GetClientObject())->GetData();
264
265 // Always update the actor viewer's state even if it's inactive,
266 // so it will be correct when first enabled
267 p->m_ActorViewerEntity = id;
268
269 if (p->m_ActorViewerActive)
270 {
271 p->ActorViewerPostToGame();
272 }
273 else
274 {
275 // On selecting an object, enable the PlaceObject tool with this object
276 m_ScenarioEditor.GetToolManager().SetCurrentTool(_T("PlaceObject"), &id);
277 }
278 }
279
OnSelectFilter(wxCommandEvent & WXUNUSED (evt))280 void ObjectSidebar::OnSelectFilter(wxCommandEvent& WXUNUSED(evt))
281 {
282 FilterObjects();
283 }
284
285 BEGIN_EVENT_TABLE(ObjectSidebar, Sidebar)
286 EVT_CHOICE(ID_ObjectType, ObjectSidebar::OnSelectType)
287 EVT_TEXT(ID_ObjectFilter, ObjectSidebar::OnSelectFilter)
288 EVT_LISTBOX(ID_SelectObject, ObjectSidebar::OnSelectObject)
289 EVT_BUTTON(ID_ToggleViewer, ObjectSidebar::OnToggleViewer)
290 END_EVENT_TABLE();
291
292 //////////////////////////////////////////////////////////////////////////
293
294 class PlayerComboBox : public wxComboBox
295 {
296 public:
PlayerComboBox(wxWindow * parent,Observable<ObjectSettings> & objectSettings,Observable<AtObj> & mapSettings)297 PlayerComboBox(wxWindow* parent, Observable<ObjectSettings>& objectSettings, Observable<AtObj>& mapSettings)
298 : wxComboBox(parent, ID_PlayerSelect, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, 0, wxCB_READONLY)
299 , m_ObjectSettings(objectSettings), m_MapSettings(mapSettings)
300 {
301 m_ObjectConn = m_ObjectSettings.RegisterObserver(1, &PlayerComboBox::OnObjectSettingsChange, this);
302 m_MapConn = m_MapSettings.RegisterObserver(1, &PlayerComboBox::OnMapSettingsChange, this);
303 }
304
SetPlayers(wxArrayString & names)305 void SetPlayers(wxArrayString& names)
306 {
307 m_Players = names;
308 OnMapSettingsChange(m_MapSettings);
309 }
310
311 private:
312
313 ObservableScopedConnection m_ObjectConn;
314 Observable<ObjectSettings>& m_ObjectSettings;
315 ObservableScopedConnection m_MapConn;
316 Observable<AtObj>& m_MapSettings;
317 wxArrayString m_Players;
318
SetSelection(int playerID)319 void SetSelection(int playerID)
320 {
321 // This control may not be loaded yet (before first display)
322 // or may have less items than we expect, which could cause
323 // an assertion failure, so handle that here
324 if ((unsigned int)playerID < GetCount())
325 {
326 wxComboBox::SetSelection(playerID);
327 }
328 else
329 {
330 // Invalid selection
331 wxComboBox::SetSelection(wxNOT_FOUND);
332 }
333 }
334
OnObjectSettingsChange(const ObjectSettings & settings)335 void OnObjectSettingsChange(const ObjectSettings& settings)
336 {
337 SetSelection(settings.GetPlayerID());
338 }
339
OnMapSettingsChange(const AtObj & settings)340 void OnMapSettingsChange(const AtObj& settings)
341 {
342 // Reload displayed player names
343 Clear();
344 size_t numPlayers = settings["PlayerData"]["item"].count();
345 for (size_t i = 0; i <= numPlayers && i < m_Players.Count(); ++i)
346 {
347 Append(m_Players[i]);
348 }
349
350 SetSelection(m_ObjectSettings.GetPlayerID());
351 }
352
OnSelect(wxCommandEvent & evt)353 void OnSelect(wxCommandEvent& evt)
354 {
355 m_ObjectSettings.SetPlayerID(evt.GetInt());
356 m_ObjectSettings.NotifyObserversExcept(m_ObjectConn);
357 }
358
359 DECLARE_EVENT_TABLE();
360 };
361 BEGIN_EVENT_TABLE(PlayerComboBox, wxComboBox)
362 EVT_COMBOBOX(wxID_ANY, PlayerComboBox::OnSelect)
363 END_EVENT_TABLE();
364
365 //////////////////////////////////////////////////////////////////////////
366
ObjectBottomBar(wxWindow * parent,Observable<ObjectSettings> & objectSettings,Observable<AtObj> & mapSettings,ObjectSidebarImpl * p)367 ObjectBottomBar::ObjectBottomBar(
368 wxWindow* parent,
369 Observable<ObjectSettings>& objectSettings,
370 Observable<AtObj>& mapSettings,
371 ObjectSidebarImpl* p
372 )
373 : wxPanel(parent, wxID_ANY), p(p)
374 {
375 m_ViewerWireframe = false;
376 m_ViewerMove = false;
377 m_ViewerGround = true;
378 m_ViewerWater = false;
379 m_ViewerShadows = true;
380 m_ViewerPolyCount = false;
381 m_ViewerBoundingBox = false;
382 m_ViewerAxesMarker = false;
383 m_ViewerPropPointsMode = 0;
384
385 wxSizer* mainSizer = new wxBoxSizer(wxHORIZONTAL);
386
387 // --- viewer options panel -------------------------------------------------------------------------------
388
389 m_ViewerPanel = new wxPanel(this, wxID_ANY);
390 wxSizer* viewerSizer = new wxBoxSizer(wxHORIZONTAL);
391
392 wxSizer* viewerButtonsSizer = new wxStaticBoxSizer(wxHORIZONTAL, m_ViewerPanel, _("Display settings"));
393 {
394 wxSizer* viewerButtonsLeft = new wxBoxSizer(wxVERTICAL);
395 viewerButtonsLeft->SetMinSize(110, -1);
396 viewerButtonsLeft->Add(Tooltipped(new wxButton(m_ViewerPanel, ID_ViewerWireframe, _("Wireframe")), _("Toggle wireframe / solid rendering")), wxSizerFlags().Expand());
397 viewerButtonsLeft->Add(Tooltipped(new wxButton(m_ViewerPanel, ID_ViewerMove, _("Move")), _("Toggle movement along ground when playing walk/run animations")), wxSizerFlags().Expand());
398 viewerButtonsLeft->Add(Tooltipped(new wxButton(m_ViewerPanel, ID_ViewerGround, _("Ground")), _("Toggle the ground plane")), wxSizerFlags().Expand());
399 // TODO: disabled until http://trac.wildfiregames.com/ticket/2692 is fixed
400 wxButton* waterButton = new wxButton(m_ViewerPanel, ID_ViewerWater, _("Water"));
401 waterButton->Enable(false);
402 viewerButtonsLeft->Add(Tooltipped(waterButton, _("Toggle the water plane")), wxSizerFlags().Expand());
403 viewerButtonsLeft->Add(Tooltipped(new wxButton(m_ViewerPanel, ID_ViewerShadows, _("Shadows")), _("Toggle shadow rendering")), wxSizerFlags().Expand());
404 viewerButtonsLeft->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());
405
406 wxSizer* viewerButtonsRight = new wxBoxSizer(wxVERTICAL);
407 viewerButtonsRight->SetMinSize(110,-1);
408 viewerButtonsRight->Add(Tooltipped(new wxButton(m_ViewerPanel, ID_ViewerBoundingBox, _("Bounding Boxes")), _("Toggle bounding boxes")), wxSizerFlags().Expand());
409 viewerButtonsRight->Add(Tooltipped(new wxButton(m_ViewerPanel, ID_ViewerAxesMarker, _("Axes Marker")), _("Toggle the axes marker (R=X, G=Y, B=Z)")), wxSizerFlags().Expand());
410 viewerButtonsRight->Add(Tooltipped(new wxButton(m_ViewerPanel, ID_ViewerPropPoints, _("Prop Points")), _("Toggle prop points (works best in wireframe mode)")), wxSizerFlags().Expand());
411
412 viewerButtonsSizer->Add(viewerButtonsLeft, wxSizerFlags().Expand());
413 viewerButtonsSizer->Add(viewerButtonsRight, wxSizerFlags().Expand());
414 }
415
416 viewerSizer->Add(viewerButtonsSizer, wxSizerFlags().Expand());
417 viewerSizer->AddSpacer(3);
418
419 // --- animations panel -------------------------------------------------------------------------------
420
421 wxSizer* viewerAnimSizer = new wxStaticBoxSizer(wxVERTICAL, m_ViewerPanel, _("Animation"));
422
423 // TODO: this list should come from the actor
424 wxArrayString animChoices;
425 AtObj anims (Datafile::ReadList("animations"));
426 for (AtIter a = anims["item"]; a.defined(); ++a)
427 {
428 animChoices.Add(wxString(*a));
429 }
430 wxChoice* viewerAnimSelector = new wxChoice(m_ViewerPanel, ID_ViewerAnimation, wxDefaultPosition, wxDefaultSize, animChoices);
431 viewerAnimSelector->SetSelection(0);
432 viewerAnimSizer->Add(viewerAnimSelector, wxSizerFlags().Expand());
433
434 wxSizer* viewerAnimSpeedSizer = new wxBoxSizer(wxHORIZONTAL);
435 viewerAnimSpeedSizer->Add(new wxButton(m_ViewerPanel, ID_ViewerPlay, _("Play"), wxDefaultPosition, wxSize(50, -1)), wxSizerFlags().Expand());
436 viewerAnimSpeedSizer->Add(new wxButton(m_ViewerPanel, ID_ViewerPause, _("Pause"), wxDefaultPosition, wxSize(50, -1)), wxSizerFlags().Expand());
437 viewerAnimSpeedSizer->Add(new wxButton(m_ViewerPanel, ID_ViewerSlow, _("Slow"), wxDefaultPosition, wxSize(50, -1)), wxSizerFlags().Expand());
438 viewerAnimSizer->Add(viewerAnimSpeedSizer);
439
440 viewerSizer->Add(viewerAnimSizer, wxSizerFlags().Expand());
441
442 // --- add viewer-specific options -------------------------------------------------------------------------------
443
444 m_ViewerPanel->SetSizer(viewerSizer);
445 mainSizer->Add(m_ViewerPanel, wxSizerFlags().Expand());
446
447 m_ViewerPanel->Layout(); // prevents strange visibility glitch of the animation buttons on my machine (Vista 32-bit SP1) -- vtsj
448 m_ViewerPanel->Show(false);
449
450 // --- add player/variation selection -------------------------------------------------------------------------------
451
452 wxSizer* playerSelectionSizer = new wxBoxSizer(wxHORIZONTAL);
453 wxSizer* playerVariationSizer = new wxBoxSizer(wxVERTICAL);
454
455 // TODO: make this a wxChoice instead
456 wxComboBox* playerSelect = new PlayerComboBox(this, objectSettings, mapSettings);
457 playerSelectionSizer->Add(new wxStaticText(this, wxID_ANY, _("Player:")), wxSizerFlags().Align(wxALIGN_CENTER));
458 playerSelectionSizer->AddSpacer(3);
459 playerSelectionSizer->Add(playerSelect);
460
461 playerVariationSizer->Add(playerSelectionSizer);
462 playerVariationSizer->AddSpacer(3);
463
464
465 wxWindow* variationSelect = new VariationControl(this, objectSettings);
466 variationSelect->SetMinSize(wxSize(160, -1));
467 wxSizer* variationSizer = new wxStaticBoxSizer(wxVERTICAL, this, _("Variation"));
468 variationSizer->Add(variationSelect, wxSizerFlags().Proportion(1).Expand());
469 playerVariationSizer->Add(variationSizer, wxSizerFlags().Proportion(1));
470
471 mainSizer->AddSpacer(3);
472 mainSizer->Add(playerVariationSizer, wxSizerFlags().Expand());
473
474 // ----------------------------------------------------------------------------------
475 // --- display template name
476 wxSizer* displaySizer = new wxStaticBoxSizer(wxVERTICAL, this, _("Selected entities"));
477 m_TemplateNames = new wxScrolledWindow(this);
478 m_TemplateNames->SetMinSize(wxSize(250, -1));
479 m_TemplateNames->SetScrollRate(0, 5);
480 wxSizer* scrollwindowSizer = new wxBoxSizer(wxVERTICAL);
481 m_TemplateNames->SetSizer(scrollwindowSizer);
482 displaySizer->Add(m_TemplateNames, wxSizerFlags().Proportion(1).Expand());
483 m_TemplateNames->Layout();
484 mainSizer->AddSpacer(3);
485 mainSizer->Add(displaySizer, wxSizerFlags().Proportion(1).Expand());
486
487 g_SelectedObjects.RegisterObserver(0, &ObjectBottomBar::OnSelectedObjectsChange, this);
488
489 SetSizer(mainSizer);
490 }
491
CreateTemplateNameObject(wxWindow * parent,const std::string & templateName,int counterTemplate)492 static wxControl* CreateTemplateNameObject(wxWindow* parent, const std::string& templateName, int counterTemplate)
493 {
494 wxString idTemplate(wxString::FromUTF8(templateName.c_str()));
495 if (counterTemplate > 1)
496 idTemplate.Append(wxString::Format(wxT(" (%i)"), counterTemplate));
497
498 wxStaticText* templateNameObject = new wxStaticText(parent, wxID_ANY, idTemplate);
499 return templateNameObject;
500 }
501
OnSelectedObjectsChange(const std::vector<AtlasMessage::ObjectID> & selectedObjects)502 void ObjectBottomBar::OnSelectedObjectsChange(const std::vector<AtlasMessage::ObjectID>& selectedObjects)
503 {
504 Freeze();
505 wxSizer* sizer = m_TemplateNames->GetSizer();
506 sizer->Clear(true);
507
508 AtlasMessage::qGetSelectedObjectsTemplateNames objectTemplatesName(selectedObjects);
509 objectTemplatesName.Post();
510 std::vector<std::string> names = *objectTemplatesName.names;
511
512 int counterTemplate = 0;
513 std::string lastTemplateName = "";
514 for (std::vector<std::string>::const_iterator it = names.begin(); it != names.end(); ++it)
515 {
516 if (lastTemplateName == "")
517 lastTemplateName = (*it);
518
519 if (lastTemplateName == (*it))
520 {
521 ++counterTemplate;
522 continue;
523 }
524
525 sizer->Add(CreateTemplateNameObject(m_TemplateNames, lastTemplateName, counterTemplate), wxSizerFlags().Align(wxALIGN_LEFT));
526
527 lastTemplateName = (*it);
528 counterTemplate = 1;
529 }
530 // Add the remaining template
531 sizer->Add(CreateTemplateNameObject(m_TemplateNames, lastTemplateName, counterTemplate), wxSizerFlags().Align(wxALIGN_LEFT));
532
533 Thaw();
534 sizer->FitInside(m_TemplateNames);
535 }
536
OnFirstDisplay()537 void ObjectBottomBar::OnFirstDisplay()
538 {
539 // We use messages here because the simulation is not init'd otherwise (causing a crash)
540
541 // Get player names
542 wxArrayString players;
543 AtlasMessage::qGetPlayerDefaults qryPlayers;
544 qryPlayers.Post();
545 AtObj playerData = AtlasObject::LoadFromJSON(*qryPlayers.defaults);
546 AtObj playerDefs = *playerData["PlayerData"];
547 for (AtIter p = playerDefs["item"]; p.defined(); ++p)
548 {
549 players.Add(wxString(p["Name"]));
550 }
551 wxDynamicCast(FindWindow(ID_PlayerSelect), PlayerComboBox)->SetPlayers(players);
552
553 // Initialise the game with the default settings
554 POST_MESSAGE(SetViewParamB, (AtlasMessage::eRenderView::ACTOR, L"wireframe", m_ViewerWireframe));
555 POST_MESSAGE(SetViewParamB, (AtlasMessage::eRenderView::ACTOR, L"walk", m_ViewerMove));
556 POST_MESSAGE(SetViewParamB, (AtlasMessage::eRenderView::ACTOR, L"ground", m_ViewerGround));
557 POST_MESSAGE(SetViewParamB, (AtlasMessage::eRenderView::ACTOR, L"water", m_ViewerWater));
558 POST_MESSAGE(SetViewParamB, (AtlasMessage::eRenderView::ACTOR, L"shadows", m_ViewerShadows));
559 POST_MESSAGE(SetViewParamB, (AtlasMessage::eRenderView::ACTOR, L"stats", m_ViewerPolyCount));
560 POST_MESSAGE(SetViewParamB, (AtlasMessage::eRenderView::ACTOR, L"bounding_box", m_ViewerBoundingBox));
561 POST_MESSAGE(SetViewParamI, (AtlasMessage::eRenderView::ACTOR, L"prop_points", m_ViewerPropPointsMode));
562 }
563
ShowActorViewer(bool show)564 void ObjectBottomBar::ShowActorViewer(bool show)
565 {
566 m_ViewerPanel->Show(show);
567 Layout();
568 }
569
OnViewerSetting(wxCommandEvent & evt)570 void ObjectBottomBar::OnViewerSetting(wxCommandEvent& evt)
571 {
572 switch (evt.GetId())
573 {
574 case ID_ViewerWireframe:
575 m_ViewerWireframe = !m_ViewerWireframe;
576 POST_MESSAGE(SetViewParamB, (AtlasMessage::eRenderView::ACTOR, L"wireframe", m_ViewerWireframe));
577 break;
578 case ID_ViewerMove:
579 m_ViewerMove = !m_ViewerMove;
580 POST_MESSAGE(SetViewParamB, (AtlasMessage::eRenderView::ACTOR, L"walk", m_ViewerMove));
581 break;
582 case ID_ViewerGround:
583 m_ViewerGround = !m_ViewerGround;
584 POST_MESSAGE(SetViewParamB, (AtlasMessage::eRenderView::ACTOR, L"ground", m_ViewerGround));
585 break;
586 case ID_ViewerWater:
587 m_ViewerWater = !m_ViewerWater;
588 POST_MESSAGE(SetViewParamB, (AtlasMessage::eRenderView::ACTOR, L"water", m_ViewerWater));
589 break;
590 case ID_ViewerShadows:
591 m_ViewerShadows = !m_ViewerShadows;
592 POST_MESSAGE(SetViewParamB, (AtlasMessage::eRenderView::ACTOR, L"shadows", m_ViewerShadows));
593 break;
594 case ID_ViewerPolyCount:
595 m_ViewerPolyCount = !m_ViewerPolyCount;
596 POST_MESSAGE(SetViewParamB, (AtlasMessage::eRenderView::ACTOR, L"stats", m_ViewerPolyCount));
597 break;
598 case ID_ViewerBoundingBox:
599 m_ViewerBoundingBox = !m_ViewerBoundingBox;
600 POST_MESSAGE(SetViewParamB, (AtlasMessage::eRenderView::ACTOR, L"bounding_box", m_ViewerBoundingBox));
601 break;
602 case ID_ViewerAxesMarker:
603 m_ViewerAxesMarker = !m_ViewerAxesMarker;
604 POST_MESSAGE(SetViewParamB, (AtlasMessage::eRenderView::ACTOR, L"axes_marker", m_ViewerAxesMarker));
605 break;
606 case ID_ViewerPropPoints:
607 m_ViewerPropPointsMode = (m_ViewerPropPointsMode+1) % 3;
608 POST_MESSAGE(SetViewParamI, (AtlasMessage::eRenderView::ACTOR, L"prop_points", m_ViewerPropPointsMode));
609 break;
610 }
611 }
612
OnSelectAnim(wxCommandEvent & evt)613 void ObjectBottomBar::OnSelectAnim(wxCommandEvent& evt)
614 {
615 p->m_ActorViewerAnimation = evt.GetString();
616 p->ActorViewerPostToGame();
617 }
618
OnSpeed(wxCommandEvent & evt)619 void ObjectBottomBar::OnSpeed(wxCommandEvent& evt)
620 {
621 switch (evt.GetId())
622 {
623 case ID_ViewerPlay: p->m_ActorViewerSpeed = 1.0f; break;
624 case ID_ViewerPause: p->m_ActorViewerSpeed = 0.0f; break;
625 case ID_ViewerSlow: p->m_ActorViewerSpeed = 0.1f; break;
626 }
627 p->ActorViewerPostToGame();
628 }
629
630 BEGIN_EVENT_TABLE(ObjectBottomBar, wxPanel)
631 EVT_BUTTON(ID_ViewerWireframe, ObjectBottomBar::OnViewerSetting)
632 EVT_BUTTON(ID_ViewerMove, ObjectBottomBar::OnViewerSetting)
633 EVT_BUTTON(ID_ViewerGround, ObjectBottomBar::OnViewerSetting)
634 EVT_BUTTON(ID_ViewerWater, ObjectBottomBar::OnViewerSetting)
635 EVT_BUTTON(ID_ViewerShadows, ObjectBottomBar::OnViewerSetting)
636 EVT_BUTTON(ID_ViewerPolyCount, ObjectBottomBar::OnViewerSetting)
637 EVT_CHOICE(ID_ViewerAnimation, ObjectBottomBar::OnSelectAnim)
638 EVT_BUTTON(ID_ViewerPlay, ObjectBottomBar::OnSpeed)
639 EVT_BUTTON(ID_ViewerPause, ObjectBottomBar::OnSpeed)
640 EVT_BUTTON(ID_ViewerSlow, ObjectBottomBar::OnSpeed)
641 EVT_BUTTON(ID_ViewerBoundingBox, ObjectBottomBar::OnViewerSetting)
642 EVT_BUTTON(ID_ViewerAxesMarker, ObjectBottomBar::OnViewerSetting)
643 EVT_BUTTON(ID_ViewerPropPoints, ObjectBottomBar::OnViewerSetting)
644 END_EVENT_TABLE();
645