2022-03-28 15:47:52 -07:00
/* Copyright (C) 2021 Wildfire Games.
2023-12-02 16:30:12 -08:00
* This file is part of 0 A . D .
2011-05-27 14:48:23 -07:00
*
2023-12-02 16:30:12 -08:00
* 0 A . D . is free software : you can redistribute it and / or modify
2011-05-27 14:48:23 -07:00
* 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 .
*
2023-12-02 16:30:12 -08:00
* 0 A . D . is distributed in the hope that it will be useful ,
2011-05-27 14:48:23 -07:00
* 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
2023-12-02 16:30:12 -08:00
* along with 0 A . D . If not , see < http : //www.gnu.org/licenses/>.
2011-05-27 14:48:23 -07:00
*/
# include "precompiled.h"
# include "Object.h"
# include "Buttons/ToolButton.h"
2011-06-09 16:45:12 -07:00
# include "General/Datafile.h"
2011-05-27 14:48:23 -07:00
# 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"
2020-01-20 12:42:54 -08:00
# include "wx/wxcrt.h"
2011-05-27 14:48:23 -07:00
2011-05-27 14:56:43 -07:00
enum
2011-05-27 14:48:23 -07:00
{
2011-05-27 14:56:43 -07:00
ID_ObjectType = 1 ,
2011-06-13 16:32:41 -07:00
ID_ObjectFilter ,
2020-01-20 12:42:54 -08:00
ID_ObjectExactFilter ,
2011-06-09 16:45:12 -07:00
ID_PlayerSelect ,
2011-05-27 14:56:43 -07:00
ID_SelectObject ,
ID_ToggleViewer ,
ID_ViewerWireframe ,
ID_ViewerMove ,
ID_ViewerGround ,
2012-09-28 11:20:36 -07:00
ID_ViewerWater ,
2011-05-27 14:56:43 -07:00
ID_ViewerShadows ,
ID_ViewerPolyCount ,
ID_ViewerAnimation ,
2011-11-24 22:36:13 -08:00
ID_ViewerBoundingBox ,
ID_ViewerAxesMarker ,
2011-12-09 02:49:08 -08:00
ID_ViewerPropPoints ,
2011-05-27 14:56:43 -07:00
ID_ViewerPlay ,
ID_ViewerPause ,
ID_ViewerSlow
2011-05-27 14:48:23 -07:00
} ;
2011-05-27 14:56:43 -07:00
// Helper function for adding tooltips
2011-05-29 08:02:02 -07:00
static wxWindow * Tooltipped ( wxWindow * window , const wxString & tip )
2011-05-27 14:56:43 -07:00
{
window - > SetToolTip ( tip ) ;
return window ;
}
2011-05-27 14:48:23 -07:00
2011-05-27 14:56:43 -07:00
class ObjectBottomBar : public wxPanel
2011-05-27 14:48:23 -07:00
{
public :
2011-11-24 22:36:13 -08:00
ObjectBottomBar (
wxWindow * parent ,
Observable < ObjectSettings > & objectSettings ,
Observable < AtObj > & mapSettings ,
ObjectSidebarImpl * p
) ;
2011-05-27 14:48:23 -07:00
2011-05-27 14:56:43 -07:00
void OnFirstDisplay ( ) ;
void ShowActorViewer ( bool show ) ;
2015-02-01 13:23:06 -08:00
void OnSelectedObjectsChange ( const std : : vector < AtlasMessage : : ObjectID > & selectedObjects ) ;
2011-05-27 14:48:23 -07:00
private :
2011-05-27 14:56:43 -07:00
void OnViewerSetting ( wxCommandEvent & evt ) ;
void OnSelectAnim ( wxCommandEvent & evt ) ;
void OnSpeed ( wxCommandEvent & evt ) ;
2011-05-27 14:48:23 -07:00
2011-05-27 14:56:43 -07:00
bool m_ViewerWireframe ;
bool m_ViewerMove ;
bool m_ViewerGround ;
2012-09-28 11:20:36 -07:00
bool m_ViewerWater ;
2011-05-27 14:56:43 -07:00
bool m_ViewerPolyCount ;
2011-11-24 22:36:13 -08:00
bool m_ViewerBoundingBox ;
bool m_ViewerAxesMarker ;
2011-12-10 03:53:39 -08:00
int m_ViewerPropPointsMode ; // 0 disabled, 1 for point markers, 2 for point markers + axes
2011-05-27 14:48:23 -07:00
2011-05-27 14:56:43 -07:00
wxPanel * m_ViewerPanel ;
2015-02-01 13:23:06 -08:00
wxScrolledWindow * m_TemplateNames ;
2011-05-27 14:48:23 -07:00
2011-05-27 14:56:43 -07:00
ObjectSidebarImpl * p ;
DECLARE_EVENT_TABLE ( ) ;
2011-05-27 14:48:23 -07:00
} ;
struct ObjectSidebarImpl
{
2012-04-16 18:26:24 -07:00
ObjectSidebarImpl ( ScenarioEditor & scenarioEditor ) :
2011-05-27 14:56:43 -07:00
m_ObjectListBox ( NULL ) , m_ActorViewerActive ( false ) ,
2019-06-03 13:19:53 -07:00
m_ActorViewerEntity ( L " actor|structures/fndn_1x1.xml " ) ,
m_ActorViewerAnimation ( " idle " ) , m_ActorViewerSpeed ( 0.f ) ,
2012-04-16 18:26:24 -07:00
m_ObjectSettings ( scenarioEditor . GetObjectSettings ( ) )
2011-05-27 14:56:43 -07:00
{
}
2011-05-27 14:48:23 -07:00
wxListBox * m_ObjectListBox ;
std : : vector < AtlasMessage : : sObjectsListItem > m_Objects ;
2011-05-27 14:56:43 -07:00
ObservableScopedConnection m_ToolConn ;
bool m_ActorViewerActive ;
2019-06-03 13:19:53 -07:00
std : : wstring m_ActorViewerEntity ;
std : : string m_ActorViewerAnimation ;
2011-05-27 14:56:43 -07:00
float m_ActorViewerSpeed ;
2012-04-16 18:26:24 -07:00
Observable < ObjectSettings > & m_ObjectSettings ;
2011-05-27 14:56:43 -07:00
2020-01-20 12:42:54 -08:00
struct SearchItem
{
// Weight of the pattern (higher - better).
size_t weight ;
// Index in the original sequence to save the order.
size_t index ;
bool operator < ( const SearchItem & other ) const
{
if ( weight ! = other . weight )
return weight > other . weight ;
return index < other . index ;
}
} ;
// Cache the std::vector to prevent frequent reallocations.
std : : vector < SearchItem > m_SearchItems ;
struct SearchItemFilter
{
SearchItemFilter ( const wxString & filterName )
{
bool firstCharacterInWord = true ;
for ( const wxUniChar & ch : filterName )
{
if ( wxIsalpha ( ch ) )
{
if ( firstCharacterInWord )
m_FilterWords . push_back ( wxString ( ) ) ;
firstCharacterInWord = false ;
m_FilterWords . back ( ) . Append ( ch ) ;
}
else
firstCharacterInWord = true ;
}
}
// Returns positive integer if filter words can present in the name.
// Otherwise returns zero.
size_t CalculateWeight ( const wxString & name )
{
if ( m_FilterWords . empty ( ) | | name . IsEmpty ( ) )
return 0 ;
std : : vector < size_t > filterWordWeights ( m_FilterWords . size ( ) , 0 ) ;
for ( size_t wordBegin = 0 ; wordBegin < name . Length ( ) ; )
{
if ( ! wxIsalpha ( name [ wordBegin ] ) )
{
+ + wordBegin ;
continue ;
}
size_t wordEnd = wordBegin ;
while ( wordEnd < name . Length ( ) & & wxIsalpha ( name [ wordEnd ] ) )
+ + wordEnd ;
for ( size_t i = 0 ; i < m_FilterWords . size ( ) ; + + i )
{
// TODO: we might have a copy here, maybe we can use
// something similar to std::string_view but for wxString.
size_t weight = CalculateLCS (
m_FilterWords [ i ] , name . Mid ( wordBegin , wordEnd - wordBegin ) ) ;
// We use a simple heuristic, if LCS shorter than a half
// of the filter word, then it's not good for us.
if ( weight < m_FilterWords [ i ] . size ( ) / 2 )
continue ;
filterWordWeights [ i ] = std : : max ( filterWordWeights [ i ] , weight ) ;
}
wordBegin = wordEnd ;
}
size_t totalWeight = 0 ;
for ( size_t weight : filterWordWeights )
{
// If a filter word was't found at all, then we can't accept
// the search item name.
if ( ! weight )
return 0 ;
totalWeight + = weight ;
}
return totalWeight ;
}
// We use longest common subsequence to calculate the weight
// between two words: filter and item names.
size_t CalculateLCS ( const wxString & filterWord , const wxString & word )
{
if ( filterWord . IsEmpty ( ) | | word . IsEmpty ( ) )
return 0 ;
m_LCSGrid . resize ( filterWord . Length ( ) * word . Length ( ) ) ;
for ( size_t i = 0 ; i < filterWord . Length ( ) ; + + i )
for ( size_t j = 0 ; j < word . Length ( ) ; + + j )
{
# define GRID(x, y) m_LCSGrid[(x) * word.Length() + (y)]
GRID ( i , j ) = wxTolower ( filterWord . GetChar ( i ) ) = = wxTolower ( word . GetChar ( j ) ) ;
if ( i & & j )
GRID ( i , j ) + = GRID ( i - 1 , j - 1 ) ;
if ( i )
GRID ( i , j ) = std : : max ( GRID ( i , j ) , GRID ( i - 1 , j ) ) ;
if ( j )
GRID ( i , j ) = std : : max ( GRID ( i , j ) , GRID ( i , j - 1 ) ) ;
# undef GRID
}
return m_LCSGrid . back ( ) ;
}
std : : vector < wxString > m_FilterWords ;
// Cache the std::vector to prevent frequent reallocations.
std : : vector < size_t > m_LCSGrid ;
} ;
2011-05-27 14:56:43 -07:00
void ActorViewerPostToGame ( )
{
2019-06-03 13:19:53 -07:00
POST_MESSAGE ( SetActorViewer , ( m_ActorViewerEntity . c_str ( ) , m_ActorViewerAnimation . c_str ( ) , m_ObjectSettings . GetPlayerID ( ) , m_ActorViewerSpeed , false ) ) ;
2011-05-27 14:56:43 -07:00
}
2011-05-27 14:48:23 -07:00
} ;
2011-11-24 22:36:13 -08:00
ObjectSidebar : : ObjectSidebar (
ScenarioEditor & scenarioEditor ,
wxWindow * sidebarContainer ,
wxWindow * bottomBarContainer
)
: Sidebar ( scenarioEditor , sidebarContainer , bottomBarContainer ) ,
2019-04-05 05:37:37 -07:00
m_Impl ( new ObjectSidebarImpl ( scenarioEditor ) )
2011-05-27 14:48:23 -07:00
{
2017-08-27 11:47:39 -07:00
wxSizer * scrollSizer = new wxBoxSizer ( wxVERTICAL ) ;
wxScrolledWindow * scrolledWindow = new wxScrolledWindow ( this ) ;
scrolledWindow - > SetScrollRate ( 10 , 10 ) ;
scrolledWindow - > SetSizer ( scrollSizer ) ;
m_MainSizer - > Add ( scrolledWindow , wxSizerFlags ( ) . Proportion ( 1 ) . Expand ( ) ) ;
2011-06-13 16:32:41 -07:00
wxBoxSizer * sizer = new wxBoxSizer ( wxHORIZONTAL ) ;
2017-08-27 11:47:39 -07:00
sizer - > Add ( new wxStaticText ( scrolledWindow , wxID_ANY , _ ( " Filter " ) ) , wxSizerFlags ( ) . Align ( wxALIGN_CENTER ) ) ;
2020-01-20 12:42:54 -08:00
sizer - > AddSpacer ( 2 ) ;
2011-11-24 22:36:13 -08:00
sizer - > Add (
Tooltipped (
2017-08-27 11:47:39 -07:00
new wxTextCtrl ( scrolledWindow , ID_ObjectFilter ) ,
2011-11-24 22:36:13 -08:00
_ ( " Enter text to filter object list " )
) ,
wxSizerFlags ( ) . Expand ( ) . Proportion ( 1 )
) ;
2017-08-27 11:47:39 -07:00
scrollSizer - > Add ( sizer , wxSizerFlags ( ) . Expand ( ) ) ;
scrollSizer - > AddSpacer ( 3 ) ;
2020-01-20 12:42:54 -08:00
wxCheckBox * exactSearchCheckBox = new wxCheckBox (
scrolledWindow , ID_ObjectExactFilter , _ ( " Exact Search " ) ) ;
exactSearchCheckBox - > SetValue ( true ) ;
scrollSizer - > Add ( Tooltipped ( exactSearchCheckBox ,
_ ( " Provides a search with a strict string equality " ) ) ) ;
scrollSizer - > AddSpacer ( 3 ) ;
2011-11-24 22:36:13 -08:00
// ------------------------------------------------------------------------------------------
2011-06-13 16:32:41 -07:00
2011-05-27 14:48:23 -07:00
wxArrayString strings ;
strings . Add ( _ ( " Entities " ) ) ;
strings . Add ( _ ( " Actors (all) " ) ) ;
2017-08-27 11:47:39 -07:00
wxChoice * objectType = new wxChoice ( scrolledWindow , ID_ObjectType , wxDefaultPosition , wxDefaultSize , strings ) ;
2011-05-29 11:14:52 -07:00
objectType - > SetSelection ( 0 ) ;
2017-08-27 11:47:39 -07:00
scrollSizer - > Add ( objectType , wxSizerFlags ( ) . Expand ( ) ) ;
scrollSizer - > AddSpacer ( 3 ) ;
2016-11-23 06:09:58 -08:00
2011-11-24 22:36:13 -08:00
// ------------------------------------------------------------------------------------------
2011-05-27 14:48:23 -07:00
2019-04-05 05:37:37 -07:00
m_Impl - > m_ObjectListBox = new wxListBox ( scrolledWindow , ID_SelectObject , wxDefaultPosition , wxDefaultSize , 0 , nullptr , wxLB_SINGLE | wxLB_HSCROLL ) ;
scrollSizer - > Add ( m_Impl - > m_ObjectListBox , wxSizerFlags ( ) . Proportion ( 1 ) . Expand ( ) ) ;
2017-08-27 11:47:39 -07:00
scrollSizer - > AddSpacer ( 3 ) ;
2011-11-24 22:36:13 -08:00
// ------------------------------------------------------------------------------------------
2011-05-27 14:48:23 -07:00
2017-08-27 11:47:39 -07:00
scrollSizer - > Add ( new wxButton ( scrolledWindow , ID_ToggleViewer , _ ( " Switch to Actor Viewer " ) ) , wxSizerFlags ( ) . Expand ( ) ) ;
2011-05-27 14:56:43 -07:00
2011-11-24 22:36:13 -08:00
// ------------------------------------------------------------------------------------------
m_BottomBar = new ObjectBottomBar (
bottomBarContainer ,
scenarioEditor . GetObjectSettings ( ) ,
scenarioEditor . GetMapSettings ( ) ,
2019-04-05 05:37:37 -07:00
m_Impl
2011-11-24 22:36:13 -08:00
) ;
2011-05-27 14:56:43 -07:00
2019-04-05 05:37:37 -07:00
m_Impl - > m_ToolConn = scenarioEditor . GetToolManager ( ) . GetCurrentTool ( ) . RegisterObserver ( 0 , & ObjectSidebar : : OnToolChange , this ) ;
2011-05-27 14:48:23 -07:00
}
ObjectSidebar : : ~ ObjectSidebar ( )
{
2019-04-05 05:37:37 -07:00
delete m_Impl ;
2011-05-27 14:48:23 -07:00
}
2011-05-27 14:56:43 -07:00
void ObjectSidebar : : OnToolChange ( ITool * tool )
{
if ( wxString ( tool - > GetClassInfo ( ) - > GetClassName ( ) ) = = _T ( " ActorViewerTool " ) )
{
2019-04-05 05:37:37 -07:00
m_Impl - > m_ActorViewerActive = true ;
m_Impl - > ActorViewerPostToGame ( ) ;
2011-09-07 20:00:56 -07:00
wxDynamicCast ( FindWindow ( ID_ToggleViewer ) , wxButton ) - > SetLabel ( _ ( " Return to game view " ) ) ;
2011-05-27 14:56:43 -07:00
}
else
{
2019-04-05 05:37:37 -07:00
m_Impl - > m_ActorViewerActive = false ;
2011-09-07 20:00:56 -07:00
wxDynamicCast ( FindWindow ( ID_ToggleViewer ) , wxButton ) - > SetLabel ( _ ( " Switch to Actor Viewer " ) ) ;
2011-05-27 14:56:43 -07:00
}
2019-04-05 05:37:37 -07:00
static_cast < ObjectBottomBar * > ( m_BottomBar ) - > ShowActorViewer ( m_Impl - > m_ActorViewerActive ) ;
2011-05-27 14:56:43 -07:00
}
2011-05-27 14:48:23 -07:00
void ObjectSidebar : : OnFirstDisplay ( )
{
2011-05-27 14:56:43 -07:00
static_cast < ObjectBottomBar * > ( m_BottomBar ) - > OnFirstDisplay ( ) ;
2011-05-27 14:48:23 -07:00
wxBusyInfo busy ( _ ( " Loading list of objects " ) ) ;
// Get the list of objects from the game
AtlasMessage : : qGetObjectsList qry ;
qry . Post ( ) ;
2019-04-05 05:37:37 -07:00
m_Impl - > m_Objects = * qry . objects ;
2011-05-27 14:48:23 -07:00
// Display first group of objects
2011-06-13 16:32:41 -07:00
FilterObjects ( ) ;
2011-05-27 14:48:23 -07:00
}
2011-06-13 16:32:41 -07:00
void ObjectSidebar : : FilterObjects ( )
2011-05-27 14:48:23 -07:00
{
2011-06-13 16:32:41 -07:00
int filterType = wxDynamicCast ( FindWindow ( ID_ObjectType ) , wxChoice ) - > GetSelection ( ) ;
wxString filterName = wxDynamicCast ( FindWindow ( ID_ObjectFilter ) , wxTextCtrl ) - > GetValue ( ) ;
2019-04-05 05:37:37 -07:00
m_Impl - > m_ObjectListBox - > Freeze ( ) ;
m_Impl - > m_ObjectListBox - > Clear ( ) ;
2020-01-20 12:42:54 -08:00
if ( wxDynamicCast ( FindWindow ( ID_ObjectExactFilter ) , wxCheckBox ) - > IsChecked ( ) | | filterName . IsEmpty ( ) )
2011-05-27 14:48:23 -07:00
{
2020-01-20 12:42:54 -08:00
for ( std : : vector < AtlasMessage : : sObjectsListItem > : : iterator it = m_Impl - > m_Objects . begin ( ) ; it ! = m_Impl - > m_Objects . end ( ) ; + + it )
2011-05-27 14:48:23 -07:00
{
2020-01-20 12:42:54 -08:00
if ( it - > type ! = filterType )
continue ;
2011-05-27 14:48:23 -07:00
wxString id = it - > id . c_str ( ) ;
wxString name = it - > name . c_str ( ) ;
2011-06-13 16:32:41 -07:00
if ( name . Lower ( ) . Find ( filterName . Lower ( ) ) ! = wxNOT_FOUND )
2019-04-05 05:37:37 -07:00
m_Impl - > m_ObjectListBox - > Append ( name , new wxStringClientData ( id ) ) ;
2011-05-27 14:48:23 -07:00
}
}
2020-01-20 12:42:54 -08:00
else
{
ObjectSidebarImpl : : SearchItemFilter filter ( filterName ) ;
for ( size_t idx = 0 ; idx < m_Impl - > m_Objects . size ( ) ; + + idx )
{
const AtlasMessage : : sObjectsListItem & it = m_Impl - > m_Objects [ idx ] ;
if ( it . type ! = filterType )
continue ;
wxString name = it . name . c_str ( ) ;
size_t weight = filter . CalculateWeight ( name ) ;
// We don't want to show items with zero weight.
if ( ! weight )
continue ;
m_Impl - > m_SearchItems . push_back ( { weight , idx } ) ;
}
std : : sort ( m_Impl - > m_SearchItems . begin ( ) , m_Impl - > m_SearchItems . end ( ) ) ;
for ( const ObjectSidebarImpl : : SearchItem & item : m_Impl - > m_SearchItems )
{
const AtlasMessage : : sObjectsListItem & it = m_Impl - > m_Objects [ item . index ] ;
wxString id = it . id . c_str ( ) ;
wxString name = it . name . c_str ( ) ;
m_Impl - > m_ObjectListBox - > Append ( name , new wxStringClientData ( id ) ) ;
}
m_Impl - > m_SearchItems . clear ( ) ;
}
2019-04-05 05:37:37 -07:00
m_Impl - > m_ObjectListBox - > Thaw ( ) ;
2011-05-27 14:48:23 -07:00
}
2011-09-07 20:00:56 -07:00
void ObjectSidebar : : OnToggleViewer ( wxCommandEvent & WXUNUSED ( evt ) )
2011-05-27 14:56:43 -07:00
{
2019-04-05 05:37:37 -07:00
if ( m_Impl - > m_ActorViewerActive )
2011-08-28 20:50:29 -07:00
{
2011-05-27 14:56:43 -07:00
m_ScenarioEditor . GetToolManager ( ) . SetCurrentTool ( _T ( " " ) , NULL ) ;
2011-08-28 20:50:29 -07:00
}
2011-05-27 14:56:43 -07:00
else
2011-08-28 20:50:29 -07:00
{
2011-05-27 14:56:43 -07:00
m_ScenarioEditor . GetToolManager ( ) . SetCurrentTool ( _T ( " ActorViewerTool " ) , NULL ) ;
2011-08-28 20:50:29 -07:00
}
2011-05-27 14:56:43 -07:00
}
2011-06-13 16:32:41 -07:00
void ObjectSidebar : : OnSelectType ( wxCommandEvent & WXUNUSED ( evt ) )
2011-05-27 14:56:43 -07:00
{
2011-06-13 16:32:41 -07:00
FilterObjects ( ) ;
2011-05-27 14:56:43 -07:00
}
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
2019-04-05 05:37:37 -07:00
m_Impl - > m_ActorViewerEntity = id ;
2011-05-27 14:56:43 -07:00
2019-04-05 05:37:37 -07:00
if ( m_Impl - > m_ActorViewerActive )
2011-05-27 14:56:43 -07:00
{
2019-04-05 05:37:37 -07:00
m_Impl - > ActorViewerPostToGame ( ) ;
2011-05-27 14:56:43 -07:00
}
else
{
// On selecting an object, enable the PlaceObject tool with this object
m_ScenarioEditor . GetToolManager ( ) . SetCurrentTool ( _T ( " PlaceObject " ) , & id ) ;
}
}
2011-06-13 16:32:41 -07:00
void ObjectSidebar : : OnSelectFilter ( wxCommandEvent & WXUNUSED ( evt ) )
{
FilterObjects ( ) ;
}
2020-01-20 12:42:54 -08:00
void ObjectSidebar : : OnToggleExactFilter ( wxCommandEvent & WXUNUSED ( evt ) )
{
FilterObjects ( ) ;
}
2011-05-27 14:56:43 -07:00
BEGIN_EVENT_TABLE ( ObjectSidebar , Sidebar )
EVT_CHOICE ( ID_ObjectType , ObjectSidebar : : OnSelectType )
2011-06-13 16:32:41 -07:00
EVT_TEXT ( ID_ObjectFilter , ObjectSidebar : : OnSelectFilter )
2011-05-27 14:56:43 -07:00
EVT_LISTBOX ( ID_SelectObject , ObjectSidebar : : OnSelectObject )
2011-09-07 20:00:56 -07:00
EVT_BUTTON ( ID_ToggleViewer , ObjectSidebar : : OnToggleViewer )
2020-01-20 12:42:54 -08:00
EVT_CHECKBOX ( ID_ObjectExactFilter , ObjectSidebar : : OnToggleExactFilter )
2011-05-27 14:56:43 -07:00
END_EVENT_TABLE ( ) ;
2011-05-27 14:48:23 -07:00
//////////////////////////////////////////////////////////////////////////
class PlayerComboBox : public wxComboBox
{
public :
2011-06-09 16:45:12 -07:00
PlayerComboBox ( wxWindow * parent , Observable < ObjectSettings > & objectSettings , Observable < AtObj > & mapSettings )
: wxComboBox ( parent , ID_PlayerSelect , wxEmptyString , wxDefaultPosition , wxDefaultSize , 0 , 0 , wxCB_READONLY )
, m_ObjectSettings ( objectSettings ) , m_MapSettings ( mapSettings )
{
m_ObjectConn = m_ObjectSettings . RegisterObserver ( 1 , & PlayerComboBox : : OnObjectSettingsChange , this ) ;
m_MapConn = m_MapSettings . RegisterObserver ( 1 , & PlayerComboBox : : OnMapSettingsChange , this ) ;
}
void SetPlayers ( wxArrayString & names )
2011-05-27 14:48:23 -07:00
{
2011-06-09 16:45:12 -07:00
m_Players = names ;
OnMapSettingsChange ( m_MapSettings ) ;
2011-05-27 14:48:23 -07:00
}
private :
2011-06-09 16:45:12 -07:00
ObservableScopedConnection m_ObjectConn ;
2011-05-27 14:48:23 -07:00
Observable < ObjectSettings > & m_ObjectSettings ;
2011-06-09 16:45:12 -07:00
ObservableScopedConnection m_MapConn ;
Observable < AtObj > & m_MapSettings ;
wxArrayString m_Players ;
2011-05-27 14:48:23 -07:00
2012-08-21 13:13:42 -07:00
void SetSelection ( int playerID )
2012-02-23 20:40:29 -08:00
{
// This control may not be loaded yet (before first display)
// or may have less items than we expect, which could cause
// an assertion failure, so handle that here
2012-08-21 13:13:42 -07:00
if ( ( unsigned int ) playerID < GetCount ( ) )
2012-02-23 20:40:29 -08:00
{
2012-08-21 13:13:42 -07:00
wxComboBox : : SetSelection ( playerID ) ;
2012-02-23 20:40:29 -08:00
}
else
{
// Invalid selection
wxComboBox : : SetSelection ( wxNOT_FOUND ) ;
}
}
2011-05-27 14:48:23 -07:00
void OnObjectSettingsChange ( const ObjectSettings & settings )
{
2012-02-23 20:40:29 -08:00
SetSelection ( settings . GetPlayerID ( ) ) ;
2011-05-27 14:48:23 -07:00
}
2011-06-09 16:45:12 -07:00
void OnMapSettingsChange ( const AtObj & settings )
{
2012-02-23 20:40:29 -08:00
// Reload displayed player names
2011-06-09 16:45:12 -07:00
Clear ( ) ;
size_t numPlayers = settings [ " PlayerData " ] [ " item " ] . count ( ) ;
2011-06-13 16:32:41 -07:00
for ( size_t i = 0 ; i < = numPlayers & & i < m_Players . Count ( ) ; + + i )
2011-06-09 16:45:12 -07:00
{
Append ( m_Players [ i ] ) ;
}
2012-02-23 20:40:29 -08:00
SetSelection ( m_ObjectSettings . GetPlayerID ( ) ) ;
2011-06-09 16:45:12 -07:00
}
2011-05-27 14:48:23 -07:00
void OnSelect ( wxCommandEvent & evt )
{
m_ObjectSettings . SetPlayerID ( evt . GetInt ( ) ) ;
2011-06-09 16:45:12 -07:00
m_ObjectSettings . NotifyObserversExcept ( m_ObjectConn ) ;
2011-05-27 14:48:23 -07:00
}
DECLARE_EVENT_TABLE ( ) ;
} ;
BEGIN_EVENT_TABLE ( PlayerComboBox , wxComboBox )
EVT_COMBOBOX ( wxID_ANY , PlayerComboBox : : OnSelect )
END_EVENT_TABLE ( ) ;
//////////////////////////////////////////////////////////////////////////
2011-11-24 22:36:13 -08:00
ObjectBottomBar : : ObjectBottomBar (
wxWindow * parent ,
Observable < ObjectSettings > & objectSettings ,
Observable < AtObj > & mapSettings ,
ObjectSidebarImpl * p
)
2014-09-13 12:34:04 -07:00
: wxPanel ( parent , wxID_ANY ) , p ( p )
2011-05-27 14:48:23 -07:00
{
2011-05-27 14:56:43 -07:00
m_ViewerWireframe = false ;
m_ViewerMove = false ;
m_ViewerGround = true ;
2012-09-28 11:20:36 -07:00
m_ViewerWater = false ;
2011-05-27 14:56:43 -07:00
m_ViewerPolyCount = false ;
2011-11-24 22:36:13 -08:00
m_ViewerBoundingBox = false ;
m_ViewerAxesMarker = false ;
2011-12-09 21:11:25 -08:00
m_ViewerPropPointsMode = 0 ;
2011-05-27 14:56:43 -07:00
2011-11-24 22:36:13 -08:00
wxSizer * mainSizer = new wxBoxSizer ( wxHORIZONTAL ) ;
2011-05-27 14:56:43 -07:00
2011-11-24 22:36:13 -08:00
// --- viewer options panel -------------------------------------------------------------------------------
2011-05-27 14:56:43 -07:00
m_ViewerPanel = new wxPanel ( this , wxID_ANY ) ;
wxSizer * viewerSizer = new wxBoxSizer ( wxHORIZONTAL ) ;
2011-11-24 22:36:13 -08:00
wxSizer * viewerButtonsSizer = new wxStaticBoxSizer ( wxHORIZONTAL , m_ViewerPanel , _ ( " Display settings " ) ) ;
{
wxSizer * viewerButtonsLeft = new wxBoxSizer ( wxVERTICAL ) ;
viewerButtonsLeft - > SetMinSize ( 110 , - 1 ) ;
viewerButtonsLeft - > Add ( Tooltipped ( new wxButton ( m_ViewerPanel , ID_ViewerWireframe , _ ( " Wireframe " ) ) , _ ( " Toggle wireframe / solid rendering " ) ) , wxSizerFlags ( ) . Expand ( ) ) ;
viewerButtonsLeft - > Add ( Tooltipped ( new wxButton ( m_ViewerPanel , ID_ViewerMove , _ ( " Move " ) ) , _ ( " Toggle movement along ground when playing walk/run animations " ) ) , wxSizerFlags ( ) . Expand ( ) ) ;
viewerButtonsLeft - > Add ( Tooltipped ( new wxButton ( m_ViewerPanel , ID_ViewerGround , _ ( " Ground " ) ) , _ ( " Toggle the ground plane " ) ) , wxSizerFlags ( ) . Expand ( ) ) ;
2024-12-10 02:29:34 -08:00
// TODO: disabled until https://gitea.wildfiregames.com/0ad/0ad/issues/2692 is fixed
2015-02-22 11:49:06 -08:00
wxButton * waterButton = new wxButton ( m_ViewerPanel , ID_ViewerWater , _ ( " Water " ) ) ;
waterButton - > Enable ( false ) ;
viewerButtonsLeft - > Add ( Tooltipped ( waterButton , _ ( " Toggle the water plane " ) ) , wxSizerFlags ( ) . Expand ( ) ) ;
2011-11-24 22:36:13 -08:00
viewerButtonsLeft - > Add ( Tooltipped ( new wxButton ( m_ViewerPanel , ID_ViewerShadows , _ ( " Shadows " ) ) , _ ( " Toggle shadow rendering " ) ) , wxSizerFlags ( ) . Expand ( ) ) ;
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 ( ) ) ;
wxSizer * viewerButtonsRight = new wxBoxSizer ( wxVERTICAL ) ;
viewerButtonsRight - > SetMinSize ( 110 , - 1 ) ;
2012-09-28 11:20:36 -07:00
viewerButtonsRight - > Add ( Tooltipped ( new wxButton ( m_ViewerPanel , ID_ViewerBoundingBox , _ ( " Bounding Boxes " ) ) , _ ( " Toggle bounding boxes " ) ) , wxSizerFlags ( ) . Expand ( ) ) ;
2011-12-09 02:49:08 -08:00
viewerButtonsRight - > Add ( Tooltipped ( new wxButton ( m_ViewerPanel , ID_ViewerAxesMarker , _ ( " Axes Marker " ) ) , _ ( " Toggle the axes marker (R=X, G=Y, B=Z) " ) ) , wxSizerFlags ( ) . Expand ( ) ) ;
viewerButtonsRight - > Add ( Tooltipped ( new wxButton ( m_ViewerPanel , ID_ViewerPropPoints , _ ( " Prop Points " ) ) , _ ( " Toggle prop points (works best in wireframe mode) " ) ) , wxSizerFlags ( ) . Expand ( ) ) ;
2011-11-24 22:36:13 -08:00
viewerButtonsSizer - > Add ( viewerButtonsLeft , wxSizerFlags ( ) . Expand ( ) ) ;
viewerButtonsSizer - > Add ( viewerButtonsRight , wxSizerFlags ( ) . Expand ( ) ) ;
}
2011-05-27 14:56:43 -07:00
viewerSizer - > Add ( viewerButtonsSizer , wxSizerFlags ( ) . Expand ( ) ) ;
2011-11-24 22:36:13 -08:00
viewerSizer - > AddSpacer ( 3 ) ;
// --- animations panel -------------------------------------------------------------------------------
2011-05-27 14:56:43 -07:00
wxSizer * viewerAnimSizer = new wxStaticBoxSizer ( wxVERTICAL , m_ViewerPanel , _ ( " Animation " ) ) ;
2011-06-09 16:45:12 -07:00
// TODO: this list should come from the actor
wxArrayString animChoices ;
AtObj anims ( Datafile : : ReadList ( " animations " ) ) ;
for ( AtIter a = anims [ " item " ] ; a . defined ( ) ; + + a )
{
animChoices . Add ( wxString ( * a ) ) ;
}
wxChoice * viewerAnimSelector = new wxChoice ( m_ViewerPanel , ID_ViewerAnimation , wxDefaultPosition , wxDefaultSize , animChoices ) ;
2011-05-29 11:14:52 -07:00
viewerAnimSelector - > SetSelection ( 0 ) ;
2011-05-27 14:56:43 -07:00
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 ( ) ) ;
2011-11-24 22:36:13 -08:00
// --- add viewer-specific options -------------------------------------------------------------------------------
2011-05-27 14:56:43 -07:00
m_ViewerPanel - > SetSizer ( viewerSizer ) ;
2011-11-24 22:36:13 -08:00
mainSizer - > Add ( m_ViewerPanel , wxSizerFlags ( ) . Expand ( ) ) ;
2011-05-27 14:56:43 -07:00
2011-11-24 22:36:13 -08:00
m_ViewerPanel - > Layout ( ) ; // prevents strange visibility glitch of the animation buttons on my machine (Vista 32-bit SP1) -- vtsj
2011-05-27 14:56:43 -07:00
m_ViewerPanel - > Show ( false ) ;
2011-11-24 22:36:13 -08:00
// --- add player/variation selection -------------------------------------------------------------------------------
2011-05-27 14:56:43 -07:00
2011-11-24 22:36:13 -08:00
wxSizer * playerSelectionSizer = new wxBoxSizer ( wxHORIZONTAL ) ;
2011-05-27 14:56:43 -07:00
wxSizer * playerVariationSizer = new wxBoxSizer ( wxVERTICAL ) ;
// TODO: make this a wxChoice instead
2011-06-09 16:45:12 -07:00
wxComboBox * playerSelect = new PlayerComboBox ( this , objectSettings , mapSettings ) ;
2011-11-24 22:36:13 -08:00
playerSelectionSizer - > Add ( new wxStaticText ( this , wxID_ANY , _ ( " Player: " ) ) , wxSizerFlags ( ) . Align ( wxALIGN_CENTER ) ) ;
playerSelectionSizer - > AddSpacer ( 3 ) ;
playerSelectionSizer - > Add ( playerSelect ) ;
playerVariationSizer - > Add ( playerSelectionSizer ) ;
playerVariationSizer - > AddSpacer ( 3 ) ;
2011-05-27 14:48:23 -07:00
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 ( ) ) ;
2011-05-27 14:56:43 -07:00
playerVariationSizer - > Add ( variationSizer , wxSizerFlags ( ) . Proportion ( 1 ) ) ;
2011-11-24 22:36:13 -08:00
mainSizer - > AddSpacer ( 3 ) ;
mainSizer - > Add ( playerVariationSizer , wxSizerFlags ( ) . Expand ( ) ) ;
2011-05-27 14:48:23 -07:00
2011-11-24 22:36:13 -08:00
// ----------------------------------------------------------------------------------
2015-02-01 13:23:06 -08:00
// --- 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 ) ;
displaySizer - > Add ( m_TemplateNames , wxSizerFlags ( ) . Proportion ( 1 ) . Expand ( ) ) ;
m_TemplateNames - > Layout ( ) ;
mainSizer - > AddSpacer ( 3 ) ;
mainSizer - > Add ( displaySizer , wxSizerFlags ( ) . Proportion ( 1 ) . Expand ( ) ) ;
g_SelectedObjects . RegisterObserver ( 0 , & ObjectBottomBar : : OnSelectedObjectsChange , this ) ;
2011-11-24 22:36:13 -08:00
SetSizer ( mainSizer ) ;
2011-05-27 14:48:23 -07:00
}
2011-05-27 14:56:43 -07:00
2017-02-24 09:02:10 -08:00
static wxControl * CreateTemplateNameObject ( wxWindow * parent , const std : : string & templateName , int counterTemplate )
2015-02-01 13:23:06 -08:00
{
2015-02-02 12:20:37 -08:00
wxString idTemplate ( wxString : : FromUTF8 ( templateName . c_str ( ) ) ) ;
2015-02-01 13:23:06 -08:00
if ( counterTemplate > 1 )
idTemplate . Append ( wxString : : Format ( wxT ( " (%i) " ) , counterTemplate ) ) ;
wxStaticText * templateNameObject = new wxStaticText ( parent , wxID_ANY , idTemplate ) ;
return templateNameObject ;
}
void ObjectBottomBar : : OnSelectedObjectsChange ( const std : : vector < AtlasMessage : : ObjectID > & selectedObjects )
{
Freeze ( ) ;
wxSizer * sizer = m_TemplateNames - > GetSizer ( ) ;
sizer - > Clear ( true ) ;
AtlasMessage : : qGetSelectedObjectsTemplateNames objectTemplatesName ( selectedObjects ) ;
objectTemplatesName . Post ( ) ;
std : : vector < std : : string > names = * objectTemplatesName . names ;
int counterTemplate = 0 ;
std : : string lastTemplateName = " " ;
for ( std : : vector < std : : string > : : const_iterator it = names . begin ( ) ; it ! = names . end ( ) ; + + it )
{
if ( lastTemplateName = = " " )
lastTemplateName = ( * it ) ;
if ( lastTemplateName = = ( * it ) )
{
+ + counterTemplate ;
continue ;
}
sizer - > Add ( CreateTemplateNameObject ( m_TemplateNames , lastTemplateName , counterTemplate ) , wxSizerFlags ( ) . Align ( wxALIGN_LEFT ) ) ;
lastTemplateName = ( * it ) ;
counterTemplate = 1 ;
}
// Add the remaining template
sizer - > Add ( CreateTemplateNameObject ( m_TemplateNames , lastTemplateName , counterTemplate ) , wxSizerFlags ( ) . Align ( wxALIGN_LEFT ) ) ;
Thaw ( ) ;
sizer - > FitInside ( m_TemplateNames ) ;
}
2011-05-27 14:56:43 -07:00
void ObjectBottomBar : : OnFirstDisplay ( )
{
2011-06-09 16:45:12 -07:00
// We use messages here because the simulation is not init'd otherwise (causing a crash)
// Get player names
wxArrayString players ;
AtlasMessage : : qGetPlayerDefaults qryPlayers ;
qryPlayers . Post ( ) ;
2014-02-24 12:22:02 -08:00
AtObj playerData = AtlasObject : : LoadFromJSON ( * qryPlayers . defaults ) ;
2011-06-09 16:45:12 -07:00
AtObj playerDefs = * playerData [ " PlayerData " ] ;
2019-04-05 05:37:37 -07:00
for ( AtIter iterator = playerDefs [ " item " ] ; iterator . defined ( ) ; + + iterator )
2019-06-03 13:19:53 -07:00
players . Add ( wxString : : FromUTF8 ( iterator [ " Name " ] ) ) ;
2019-04-05 05:37:37 -07:00
2011-06-09 16:45:12 -07:00
wxDynamicCast ( FindWindow ( ID_PlayerSelect ) , PlayerComboBox ) - > SetPlayers ( players ) ;
2011-05-27 14:56:43 -07:00
// 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 ) ) ;
2012-09-28 11:20:36 -07:00
POST_MESSAGE ( SetViewParamB , ( AtlasMessage : : eRenderView : : ACTOR , L " water " , m_ViewerWater ) ) ;
2011-05-27 14:56:43 -07:00
POST_MESSAGE ( SetViewParamB , ( AtlasMessage : : eRenderView : : ACTOR , L " stats " , m_ViewerPolyCount ) ) ;
2011-11-24 22:36:13 -08:00
POST_MESSAGE ( SetViewParamB , ( AtlasMessage : : eRenderView : : ACTOR , L " bounding_box " , m_ViewerBoundingBox ) ) ;
2011-12-10 03:53:39 -08:00
POST_MESSAGE ( SetViewParamI , ( AtlasMessage : : eRenderView : : ACTOR , L " prop_points " , m_ViewerPropPointsMode ) ) ;
2011-05-27 14:56:43 -07:00
}
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 ;
2012-09-28 11:20:36 -07:00
case ID_ViewerWater :
m_ViewerWater = ! m_ViewerWater ;
POST_MESSAGE ( SetViewParamB , ( AtlasMessage : : eRenderView : : ACTOR , L " water " , m_ViewerWater ) ) ;
break ;
2011-05-27 14:56:43 -07:00
case ID_ViewerShadows :
2022-03-28 15:47:52 -07:00
POST_MESSAGE ( SetViewParamB , ( AtlasMessage : : eRenderView : : ACTOR , L " shadows " , true ) ) ;
2011-05-27 14:56:43 -07:00
break ;
case ID_ViewerPolyCount :
m_ViewerPolyCount = ! m_ViewerPolyCount ;
POST_MESSAGE ( SetViewParamB , ( AtlasMessage : : eRenderView : : ACTOR , L " stats " , m_ViewerPolyCount ) ) ;
break ;
2011-11-24 22:36:13 -08:00
case ID_ViewerBoundingBox :
m_ViewerBoundingBox = ! m_ViewerBoundingBox ;
POST_MESSAGE ( SetViewParamB , ( AtlasMessage : : eRenderView : : ACTOR , L " bounding_box " , m_ViewerBoundingBox ) ) ;
break ;
case ID_ViewerAxesMarker :
m_ViewerAxesMarker = ! m_ViewerAxesMarker ;
POST_MESSAGE ( SetViewParamB , ( AtlasMessage : : eRenderView : : ACTOR , L " axes_marker " , m_ViewerAxesMarker ) ) ;
break ;
2011-12-09 02:49:08 -08:00
case ID_ViewerPropPoints :
2011-12-10 18:11:05 -08:00
m_ViewerPropPointsMode = ( m_ViewerPropPointsMode + 1 ) % 3 ;
2011-12-10 03:53:39 -08:00
POST_MESSAGE ( SetViewParamI , ( AtlasMessage : : eRenderView : : ACTOR , L " prop_points " , m_ViewerPropPointsMode ) ) ;
2011-12-09 02:49:08 -08:00
break ;
2011-05-27 14:56:43 -07:00
}
}
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 )
2012-09-28 11:20:36 -07:00
EVT_BUTTON ( ID_ViewerWater , ObjectBottomBar : : OnViewerSetting )
2011-05-27 14:56:43 -07:00
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 )
2011-11-24 22:36:13 -08:00
EVT_BUTTON ( ID_ViewerBoundingBox , ObjectBottomBar : : OnViewerSetting )
EVT_BUTTON ( ID_ViewerAxesMarker , ObjectBottomBar : : OnViewerSetting )
2011-12-09 02:49:08 -08:00
EVT_BUTTON ( ID_ViewerPropPoints , ObjectBottomBar : : OnViewerSetting )
2011-05-27 14:56:43 -07:00
END_EVENT_TABLE ( ) ;