+ state_type() : m_highlight( 0 ), m_state( 0 ), m_lights( 0 ){
+ }
+ unsigned int m_highlight;
+ Shader* m_state;
+ const LightList* m_lights;
+};
+
+std::vector<state_type> m_state_stack;
+RenderStateFlags m_globalstate;
+Shader* m_state_select0;
+Shader* m_state_select1;
+const Vector3& m_viewer;
+
+public:
+CamRenderer( RenderStateFlags globalstate, Shader* select0, Shader* select1, const Vector3& viewer ) :
+ m_globalstate( globalstate ),
+ m_state_select0( select0 ),
+ m_state_select1( select1 ),
+ m_viewer( viewer ){
+ ASSERT_NOTNULL( select0 );
+ ASSERT_NOTNULL( select1 );
+ m_state_stack.push_back( state_type() );
+}
+
+void SetState( Shader* state, EStyle style ){
+ ASSERT_NOTNULL( state );
+ if ( style == eFullMaterials ) {
+ m_state_stack.back().m_state = state;
+ }
+}
+EStyle getStyle() const {
+ return eFullMaterials;
+}
+void PushState(){
+ m_state_stack.push_back( m_state_stack.back() );
+}
+void PopState(){
+ ASSERT_MESSAGE( !m_state_stack.empty(), "popping empty stack" );
+ m_state_stack.pop_back();
+}
+void Highlight( EHighlightMode mode, bool bEnable = true ){
+ ( bEnable )
+ ? m_state_stack.back().m_highlight |= mode
+ : m_state_stack.back().m_highlight &= ~mode;
+}
+void setLights( const LightList& lights ){
+ m_state_stack.back().m_lights = &lights;
+}
+void addRenderable( const OpenGLRenderable& renderable, const Matrix4& world ){
+ if ( m_state_stack.back().m_highlight & ePrimitive ) {
+ m_state_select0->addRenderable( renderable, world, m_state_stack.back().m_lights );
+ }
+ if ( m_state_stack.back().m_highlight & eFace ) {
+ m_state_select1->addRenderable( renderable, world, m_state_stack.back().m_lights );
+ }
+
+ m_state_stack.back().m_state->addRenderable( renderable, world, m_state_stack.back().m_lights );
+}
+
+void render( const Matrix4& modelview, const Matrix4& projection ){
+ GlobalShaderCache().render( m_globalstate, modelview, projection, m_viewer );
+}
+};
+
+/*
+ ==============
+ Cam_Draw
+ ==============
+ */
+
+void ShowStatsToggle(){
+ g_camwindow_globals_private.m_showStats ^= 1;
+}
+typedef FreeCaller<ShowStatsToggle> ShowStatsToggleCaller;
+
+void ShowStatsExport( const BoolImportCallback& importer ){
+ importer( g_camwindow_globals_private.m_showStats );
+}
+typedef FreeCaller1<const BoolImportCallback&, ShowStatsExport> ShowStatsExportCaller;
+
+ShowStatsExportCaller g_show_stats_caller;
+BoolExportCallback g_show_stats_callback( g_show_stats_caller );
+ToggleItem g_show_stats( g_show_stats_callback );
+
+void CamWnd::Cam_Draw(){
+ glViewport( 0, 0, m_Camera.width, m_Camera.height );
+#if 0
+ GLint viewprt[4];
+ glGetIntegerv( GL_VIEWPORT, viewprt );
+#endif
+
+ // enable depth buffer writes
+ glDepthMask( GL_TRUE );
+ glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
+
+ Vector3 clearColour( 0, 0, 0 );
+ if ( m_Camera.draw_mode != cd_lighting ) {
+ clearColour = g_camwindow_globals.color_cameraback;
+ }
+
+ glClearColor( clearColour[0], clearColour[1], clearColour[2], 0 );
+ glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+
+ extern void Renderer_ResetStats();
+ Renderer_ResetStats();
+ extern void Cull_ResetStats();
+ Cull_ResetStats();
+
+ glMatrixMode( GL_PROJECTION );
+ glLoadMatrixf( reinterpret_cast<const float*>( &m_Camera.projection ) );
+
+ glMatrixMode( GL_MODELVIEW );
+ glLoadMatrixf( reinterpret_cast<const float*>( &m_Camera.modelview ) );
+
+
+ // one directional light source directly behind the viewer
+ {
+ GLfloat inverse_cam_dir[4], ambient[4], diffuse[4]; //, material[4];
+
+ ambient[0] = ambient[1] = ambient[2] = 0.4f;
+ ambient[3] = 1.0f;
+ diffuse[0] = diffuse[1] = diffuse[2] = 0.4f;
+ diffuse[3] = 1.0f;
+ //material[0] = material[1] = material[2] = 0.8f;
+ //material[3] = 1.0f;
+
+ inverse_cam_dir[0] = m_Camera.vpn[0];
+ inverse_cam_dir[1] = m_Camera.vpn[1];
+ inverse_cam_dir[2] = m_Camera.vpn[2];
+ inverse_cam_dir[3] = 0;
+
+ glLightfv( GL_LIGHT0, GL_POSITION, inverse_cam_dir );
+
+ glLightfv( GL_LIGHT0, GL_AMBIENT, ambient );
+ glLightfv( GL_LIGHT0, GL_DIFFUSE, diffuse );
+
+ glEnable( GL_LIGHT0 );
+ }
+
+
+ unsigned int globalstate = RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_ALPHATEST | RENDER_BLEND | RENDER_CULLFACE | RENDER_COLOURARRAY | RENDER_OFFSETLINE | RENDER_POLYGONSMOOTH | RENDER_LINESMOOTH | RENDER_FOG | RENDER_COLOURCHANGE;
+ switch ( m_Camera.draw_mode )
+ {
+ case cd_wire:
+ break;
+ case cd_solid:
+ globalstate |= RENDER_FILL
+ | RENDER_LIGHTING
+ | RENDER_SMOOTH
+ | RENDER_SCALED;
+ break;
+ case cd_texture:
+ globalstate |= RENDER_FILL
+ | RENDER_LIGHTING
+ | RENDER_TEXTURE
+ | RENDER_SMOOTH
+ | RENDER_SCALED;
+ break;
+ case cd_lighting:
+ globalstate |= RENDER_FILL
+ | RENDER_LIGHTING
+ | RENDER_TEXTURE
+ | RENDER_SMOOTH
+ | RENDER_SCALED
+ | RENDER_BUMP
+ | RENDER_PROGRAM
+ | RENDER_SCREEN;
+ break;
+ default:
+ globalstate = 0;
+ break;
+ }
+
+ if ( !g_xywindow_globals.m_bNoStipple ) {
+ globalstate |= RENDER_LINESTIPPLE | RENDER_POLYGONSTIPPLE;
+ }
+
+ {
+ CamRenderer renderer( globalstate, m_state_select2, m_state_select1, m_view.getViewer() );
+
+ Scene_Render( renderer, m_view );
+
+ renderer.render( m_Camera.modelview, m_Camera.projection );
+ }
+
+ // prepare for 2d stuff
+ glColor4f( 1, 1, 1, 1 );
+ glDisable( GL_BLEND );
+ glMatrixMode( GL_PROJECTION );
+ glLoadIdentity();
+ glOrtho( 0, (float)m_Camera.width, 0, (float)m_Camera.height, -100, 100 );
+ glScalef( 1, -1, 1 );
+ glTranslatef( 0, -(float)m_Camera.height, 0 );
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+
+ if ( GlobalOpenGL().GL_1_3() ) {
+ glClientActiveTexture( GL_TEXTURE0 );
+ glActiveTexture( GL_TEXTURE0 );
+ }
+
+ glDisableClientState( GL_TEXTURE_COORD_ARRAY );
+ glDisableClientState( GL_NORMAL_ARRAY );
+ glDisableClientState( GL_COLOR_ARRAY );
+
+ glDisable( GL_TEXTURE_2D );
+ glDisable( GL_LIGHTING );
+ glDisable( GL_COLOR_MATERIAL );
+ glDisable( GL_DEPTH_TEST );
+ glColor3f( 1.f, 1.f, 1.f );
+ glLineWidth( 1 );
+
+ // draw the crosshair
+ if ( m_bFreeMove ) {
+ glBegin( GL_LINES );
+ glVertex2f( (float)m_Camera.width / 2.f, (float)m_Camera.height / 2.f + 6 );
+ glVertex2f( (float)m_Camera.width / 2.f, (float)m_Camera.height / 2.f + 2 );
+ glVertex2f( (float)m_Camera.width / 2.f, (float)m_Camera.height / 2.f - 6 );
+ glVertex2f( (float)m_Camera.width / 2.f, (float)m_Camera.height / 2.f - 2 );
+ glVertex2f( (float)m_Camera.width / 2.f + 6, (float)m_Camera.height / 2.f );
+ glVertex2f( (float)m_Camera.width / 2.f + 2, (float)m_Camera.height / 2.f );
+ glVertex2f( (float)m_Camera.width / 2.f - 6, (float)m_Camera.height / 2.f );
+ glVertex2f( (float)m_Camera.width / 2.f - 2, (float)m_Camera.height / 2.f );
+ glEnd();
+ }
+
+ if ( g_camwindow_globals_private.m_showStats ) {
+ glRasterPos3f( 1.0f, static_cast<float>( m_Camera.height ) - GlobalOpenGL().m_font->getPixelDescent(), 0.0f );
+ extern const char* Renderer_GetStats();
+ GlobalOpenGL().drawString( Renderer_GetStats() );
+
+ glRasterPos3f( 1.0f, static_cast<float>( m_Camera.height ) - GlobalOpenGL().m_font->getPixelDescent() - GlobalOpenGL().m_font->getPixelHeight(), 0.0f );
+ extern const char* Cull_GetStats();
+ GlobalOpenGL().drawString( Cull_GetStats() );
+ }
+
+ // bind back to the default texture so that we don't have problems
+ // elsewhere using/modifying texture maps between contexts
+ glBindTexture( GL_TEXTURE_2D, 0 );
+}
+
+void CamWnd::draw(){
+ m_drawing = true;
+
+ //globalOutputStream() << "draw...\n";
+ if ( glwidget_make_current( m_gl_widget ) != FALSE ) {
+ if ( Map_Valid( g_map ) && ScreenUpdates_Enabled() ) {
+ GlobalOpenGL_debugAssertNoErrors();
+ Cam_Draw();
+ GlobalOpenGL_debugAssertNoErrors();
+ //qglFinish();
+
+ m_XORRectangle.set( rectangle_t() );
+ }
+
+ glwidget_swap_buffers( m_gl_widget );
+ }
+
+ m_drawing = false;
+}
+
+void CamWnd::BenchMark(){
+ double dStart = Sys_DoubleTime();
+ for ( int i = 0 ; i < 100 ; i++ )
+ {
+ Vector3 angles;
+ angles[CAMERA_ROLL] = 0;
+ angles[CAMERA_PITCH] = 0;
+ angles[CAMERA_YAW] = static_cast<float>( i * ( 360.0 / 100.0 ) );
+ Camera_setAngles( *this, angles );
+ }
+ double dEnd = Sys_DoubleTime();
+ globalOutputStream() << FloatFormat( dEnd - dStart, 5, 2 ) << " seconds\n";
+}
+
+
+void fill_view_camera_menu( ui::Menu menu ){
+ create_check_menu_item_with_mnemonic( menu, "Camera View", "ToggleCamera" );
+}
+
+void GlobalCamera_ResetAngles(){
+ CamWnd& camwnd = *g_camwnd;
+ Vector3 angles;
+ angles[CAMERA_ROLL] = angles[CAMERA_PITCH] = 0;
+ angles[CAMERA_YAW] = static_cast<float>( 22.5 * floor( ( Camera_getAngles( camwnd )[CAMERA_YAW] + 11 ) / 22.5 ) );
+ Camera_setAngles( camwnd, angles );
+}
+
+void Camera_ChangeFloorUp(){
+ CamWnd& camwnd = *g_camwnd;
+ camwnd.Cam_ChangeFloor( true );
+}
+
+void Camera_ChangeFloorDown(){
+ CamWnd& camwnd = *g_camwnd;
+ camwnd.Cam_ChangeFloor( false );
+}
+
+void Camera_CubeIn(){
+ CamWnd& camwnd = *g_camwnd;
+ g_camwindow_globals.m_nCubicScale--;
+ if ( g_camwindow_globals.m_nCubicScale < 1 ) {
+ g_camwindow_globals.m_nCubicScale = 1;
+ }
+ Camera_updateProjection( camwnd.getCamera() );
+ CamWnd_Update( camwnd );
+ g_pParentWnd->SetGridStatus();
+}
+
+void Camera_CubeOut(){
+ CamWnd& camwnd = *g_camwnd;
+ g_camwindow_globals.m_nCubicScale++;
+ if ( g_camwindow_globals.m_nCubicScale > 23 ) {
+ g_camwindow_globals.m_nCubicScale = 23;
+ }
+ Camera_updateProjection( camwnd.getCamera() );
+ CamWnd_Update( camwnd );
+ g_pParentWnd->SetGridStatus();
+}
+
+bool Camera_GetFarClip(){
+ return g_camwindow_globals_private.m_bCubicClipping;
+}
+
+BoolExportCaller g_getfarclip_caller( g_camwindow_globals_private.m_bCubicClipping );
+ToggleItem g_getfarclip_item( g_getfarclip_caller );
+
+void Camera_SetFarClip( bool value ){
+ CamWnd& camwnd = *g_camwnd;
+ g_camwindow_globals_private.m_bCubicClipping = value;
+ g_getfarclip_item.update();
+ Camera_updateProjection( camwnd.getCamera() );
+ CamWnd_Update( camwnd );
+}
+
+void Camera_ToggleFarClip(){
+ Camera_SetFarClip( !Camera_GetFarClip() );
+}
+
+
+void CamWnd_constructToolbar( ui::Toolbar toolbar ){
+ toolbar_append_toggle_button( toolbar, "Cubic clip the camera view (\\)", "view_cubicclipping.png", "ToggleCubicClip" );
+}
+
+void CamWnd_registerShortcuts(){
+ toggle_add_accelerator( "ToggleCubicClip" );
+
+ if ( g_pGameDescription->mGameType == "doom3" ) {
+ command_connect_accelerator( "TogglePreview" );
+ }
+
+ command_connect_accelerator( "CameraSpeedInc" );
+ command_connect_accelerator( "CameraSpeedDec" );
+}
+
+
+void GlobalCamera_Benchmark(){
+ CamWnd& camwnd = *g_camwnd;
+ camwnd.BenchMark();
+}
+
+void GlobalCamera_Update(){
+ CamWnd& camwnd = *g_camwnd;
+ CamWnd_Update( camwnd );
+}
+
+camera_draw_mode CamWnd_GetMode(){
+ return camera_t::draw_mode;
+}
+void CamWnd_SetMode( camera_draw_mode mode ){
+ ShaderCache_setBumpEnabled( mode == cd_lighting );
+ camera_t::draw_mode = mode;
+ if ( g_camwnd != 0 ) {
+ CamWnd_Update( *g_camwnd );
+ }
+}
+
+void CamWnd_TogglePreview( void ){
+ // gametype must be doom3 for this function to work
+ // if the gametype is not doom3 something is wrong with the
+ // global command list or somebody else calls this function.
+ ASSERT_MESSAGE( g_pGameDescription->mGameType == "doom3", "CamWnd_TogglePreview called although mGameType is not doom3 compatible" );
+
+ // switch between textured and lighting mode
+ CamWnd_SetMode( ( CamWnd_GetMode() == cd_lighting ) ? cd_texture : cd_lighting );
+}
+
+
+CameraModel* g_camera_model = 0;
+
+void CamWnd_LookThroughCamera( CamWnd& camwnd ){
+ if ( g_camera_model != 0 ) {
+ CamWnd_Add_Handlers_Move( camwnd );
+ g_camera_model->setCameraView( 0, Callback() );
+ g_camera_model = 0;
+ Camera_updateModelview( camwnd.getCamera() );
+ Camera_updateProjection( camwnd.getCamera() );
+ CamWnd_Update( camwnd );
+ }
+}
+
+inline CameraModel* Instance_getCameraModel( scene::Instance& instance ){
+ return InstanceTypeCast<CameraModel>::cast( instance );
+}
+
+void CamWnd_LookThroughSelected( CamWnd& camwnd ){
+ if ( g_camera_model != 0 ) {
+ CamWnd_LookThroughCamera( camwnd );
+ }
+
+ if ( GlobalSelectionSystem().countSelected() != 0 ) {
+ scene::Instance& instance = GlobalSelectionSystem().ultimateSelected();
+ CameraModel* cameraModel = Instance_getCameraModel( instance );
+ if ( cameraModel != 0 ) {
+ CamWnd_Remove_Handlers_Move( camwnd );
+ g_camera_model = cameraModel;
+ g_camera_model->setCameraView( &camwnd.getCameraView(), ReferenceCaller<CamWnd, CamWnd_LookThroughCamera>( camwnd ) );
+ }
+ }
+}
+
+void GlobalCamera_LookThroughSelected(){
+ CamWnd_LookThroughSelected( *g_camwnd );
+}
+
+void GlobalCamera_LookThroughCamera(){
+ CamWnd_LookThroughCamera( *g_camwnd );
+}
+
+
+void RenderModeImport( int value ){
+ switch ( value )
+ {
+ case 0:
+ CamWnd_SetMode( cd_wire );
+ break;
+ case 1:
+ CamWnd_SetMode( cd_solid );
+ break;
+ case 2:
+ CamWnd_SetMode( cd_texture );
+ break;
+ case 3:
+ CamWnd_SetMode( cd_lighting );
+ break;
+ default:
+ CamWnd_SetMode( cd_texture );
+ }
+}
+typedef FreeCaller1<int, RenderModeImport> RenderModeImportCaller;
+
+void RenderModeExport( const IntImportCallback& importer ){
+ switch ( CamWnd_GetMode() )
+ {
+ case cd_wire:
+ importer( 0 );
+ break;
+ case cd_solid:
+ importer( 1 );
+ break;
+ case cd_texture:
+ importer( 2 );
+ break;
+ case cd_lighting:
+ importer( 3 );
+ break;
+ }
+}
+typedef FreeCaller1<const IntImportCallback&, RenderModeExport> RenderModeExportCaller;
+
+void Camera_constructPreferences( PreferencesPage& page ){
+ page.appendSlider( "Movement Speed", g_camwindow_globals_private.m_nMoveSpeed, TRUE, 0, 0, 100, MIN_CAM_SPEED, MAX_CAM_SPEED, 1, 10 );
+ page.appendCheckBox( "", "Link strafe speed to movement speed", g_camwindow_globals_private.m_bCamLinkSpeed );
+ page.appendSlider( "Rotation Speed", g_camwindow_globals_private.m_nAngleSpeed, TRUE, 0, 0, 3, 1, 180, 1, 10 );
+ page.appendCheckBox( "", "Invert mouse vertical axis", g_camwindow_globals_private.m_bCamInverseMouse );
+ page.appendCheckBox(
+ "", "Discrete movement",
+ FreeCaller1<bool, CamWnd_Move_Discrete_Import>(),
+ BoolExportCaller( g_camwindow_globals_private.m_bCamDiscrete )
+ );
+ page.appendCheckBox(
+ "", "Enable far-clip plane",
+ FreeCaller1<bool, Camera_SetFarClip>(),
+ BoolExportCaller( g_camwindow_globals_private.m_bCubicClipping )
+ );
+
+ if ( g_pGameDescription->mGameType == "doom3" ) {
+ const char* render_mode[] = { "Wireframe", "Flatshade", "Textured", "Lighting" };
+
+ page.appendCombo(
+ "Render Mode",
+ STRING_ARRAY_RANGE( render_mode ),
+ IntImportCallback( RenderModeImportCaller() ),
+ IntExportCallback( RenderModeExportCaller() )
+ );
+ }
+ else
+ {
+ const char* render_mode[] = { "Wireframe", "Flatshade", "Textured" };
+
+ page.appendCombo(
+ "Render Mode",
+ STRING_ARRAY_RANGE( render_mode ),
+ IntImportCallback( RenderModeImportCaller() ),
+ IntExportCallback( RenderModeExportCaller() )
+ );
+ }
+
+ const char* strafe_mode[] = { "Both", "Forward", "Up" };
+
+ page.appendCombo(
+ "Strafe Mode",
+ g_camwindow_globals_private.m_nStrafeMode,
+ STRING_ARRAY_RANGE( strafe_mode )
+ );
+}
+void Camera_constructPage( PreferenceGroup& group ){
+ PreferencesPage page( group.createPage( "Camera", "Camera View Preferences" ) );
+ Camera_constructPreferences( page );
+}
+void Camera_registerPreferencesPage(){
+ PreferencesDialog_addSettingsPage( FreeCaller1<PreferenceGroup&, Camera_constructPage>() );
+}
+
+#include "preferencesystem.h"
+#include "stringio.h"
+#include "dialog.h"
+
+typedef FreeCaller1<bool, CamWnd_Move_Discrete_Import> CamWndMoveDiscreteImportCaller;
+
+void CameraSpeed_increase(){
+ if ( g_camwindow_globals_private.m_nMoveSpeed <= ( MAX_CAM_SPEED - CAM_SPEED_STEP - 10 ) ) {
+ g_camwindow_globals_private.m_nMoveSpeed += CAM_SPEED_STEP;
+ }
+ else {
+ g_camwindow_globals_private.m_nMoveSpeed = MAX_CAM_SPEED - 10;
+ }
+}
+
+void CameraSpeed_decrease(){
+ if ( g_camwindow_globals_private.m_nMoveSpeed >= ( MIN_CAM_SPEED + CAM_SPEED_STEP ) ) {
+ g_camwindow_globals_private.m_nMoveSpeed -= CAM_SPEED_STEP;
+ }
+ else {
+ g_camwindow_globals_private.m_nMoveSpeed = MIN_CAM_SPEED;
+ }
+}
+
+/// \brief Initialisation for things that have the same lifespan as this module.
+void CamWnd_Construct(){
+ GlobalCommands_insert( "CenterView", FreeCaller<GlobalCamera_ResetAngles>(), Accelerator( GDK_KEY_End ) );
+
+ GlobalToggles_insert( "ToggleCubicClip", FreeCaller<Camera_ToggleFarClip>(), ToggleItem::AddCallbackCaller( g_getfarclip_item ), Accelerator( '\\', (GdkModifierType)GDK_CONTROL_MASK ) );
+ GlobalCommands_insert( "CubicClipZoomIn", FreeCaller<Camera_CubeIn>(), Accelerator( '[', (GdkModifierType)GDK_CONTROL_MASK ) );
+ GlobalCommands_insert( "CubicClipZoomOut", FreeCaller<Camera_CubeOut>(), Accelerator( ']', (GdkModifierType)GDK_CONTROL_MASK ) );
+
+ GlobalCommands_insert( "UpFloor", FreeCaller<Camera_ChangeFloorUp>(), Accelerator( GDK_KEY_Prior ) );
+ GlobalCommands_insert( "DownFloor", FreeCaller<Camera_ChangeFloorDown>(), Accelerator( GDK_KEY_Next ) );
+
+ GlobalToggles_insert( "ToggleCamera", ToggleShown::ToggleCaller( g_camera_shown ), ToggleItem::AddCallbackCaller( g_camera_shown.m_item ), Accelerator( 'C', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) );
+ GlobalCommands_insert( "LookThroughSelected", FreeCaller<GlobalCamera_LookThroughSelected>() );
+ GlobalCommands_insert( "LookThroughCamera", FreeCaller<GlobalCamera_LookThroughCamera>() );
+
+ if ( g_pGameDescription->mGameType == "doom3" ) {
+ GlobalCommands_insert( "TogglePreview", FreeCaller<CamWnd_TogglePreview>(), Accelerator( GDK_KEY_F3 ) );
+ }
+
+ GlobalCommands_insert( "CameraSpeedInc", FreeCaller<CameraSpeed_increase>(), Accelerator( GDK_KEY_KP_Add, (GdkModifierType)GDK_SHIFT_MASK ) );
+ GlobalCommands_insert( "CameraSpeedDec", FreeCaller<CameraSpeed_decrease>(), Accelerator( GDK_KEY_KP_Subtract, (GdkModifierType)GDK_SHIFT_MASK ) );
+
+ GlobalShortcuts_insert( "CameraForward", Accelerator( GDK_KEY_Up ) );
+ GlobalShortcuts_insert( "CameraBack", Accelerator( GDK_KEY_Down ) );
+ GlobalShortcuts_insert( "CameraLeft", Accelerator( GDK_KEY_Left ) );
+ GlobalShortcuts_insert( "CameraRight", Accelerator( GDK_KEY_Right ) );
+ GlobalShortcuts_insert( "CameraStrafeRight", Accelerator( GDK_KEY_period ) );
+ GlobalShortcuts_insert( "CameraStrafeLeft", Accelerator( GDK_KEY_comma ) );
+
+ GlobalShortcuts_insert( "CameraUp", Accelerator( 'D' ) );
+ GlobalShortcuts_insert( "CameraDown", Accelerator( 'C' ) );
+ GlobalShortcuts_insert( "CameraAngleUp", Accelerator( 'A' ) );
+ GlobalShortcuts_insert( "CameraAngleDown", Accelerator( 'Z' ) );
+
+ GlobalShortcuts_insert( "CameraFreeMoveForward", Accelerator( GDK_KEY_Up ) );
+ GlobalShortcuts_insert( "CameraFreeMoveBack", Accelerator( GDK_KEY_Down ) );
+ GlobalShortcuts_insert( "CameraFreeMoveLeft", Accelerator( GDK_KEY_Left ) );
+ GlobalShortcuts_insert( "CameraFreeMoveRight", Accelerator( GDK_KEY_Right ) );
+
+ GlobalToggles_insert( "ShowStats", ShowStatsToggleCaller(), ToggleItem::AddCallbackCaller( g_show_stats ) );
+
+ GlobalPreferenceSystem().registerPreference( "ShowStats", BoolImportStringCaller( g_camwindow_globals_private.m_showStats ), BoolExportStringCaller( g_camwindow_globals_private.m_showStats ) );
+ GlobalPreferenceSystem().registerPreference( "MoveSpeed", IntImportStringCaller( g_camwindow_globals_private.m_nMoveSpeed ), IntExportStringCaller( g_camwindow_globals_private.m_nMoveSpeed ) );
+ GlobalPreferenceSystem().registerPreference( "CamLinkSpeed", BoolImportStringCaller( g_camwindow_globals_private.m_bCamLinkSpeed ), BoolExportStringCaller( g_camwindow_globals_private.m_bCamLinkSpeed ) );
+ GlobalPreferenceSystem().registerPreference( "AngleSpeed", IntImportStringCaller( g_camwindow_globals_private.m_nAngleSpeed ), IntExportStringCaller( g_camwindow_globals_private.m_nAngleSpeed ) );
+ GlobalPreferenceSystem().registerPreference( "CamInverseMouse", BoolImportStringCaller( g_camwindow_globals_private.m_bCamInverseMouse ), BoolExportStringCaller( g_camwindow_globals_private.m_bCamInverseMouse ) );
+ GlobalPreferenceSystem().registerPreference( "CamDiscrete", makeBoolStringImportCallback( CamWndMoveDiscreteImportCaller() ), BoolExportStringCaller( g_camwindow_globals_private.m_bCamDiscrete ) );
+ GlobalPreferenceSystem().registerPreference( "CubicClipping", BoolImportStringCaller( g_camwindow_globals_private.m_bCubicClipping ), BoolExportStringCaller( g_camwindow_globals_private.m_bCubicClipping ) );
+ GlobalPreferenceSystem().registerPreference( "CubicScale", IntImportStringCaller( g_camwindow_globals.m_nCubicScale ), IntExportStringCaller( g_camwindow_globals.m_nCubicScale ) );
+ GlobalPreferenceSystem().registerPreference( "SI_Colors4", Vector3ImportStringCaller( g_camwindow_globals.color_cameraback ), Vector3ExportStringCaller( g_camwindow_globals.color_cameraback ) );
+ GlobalPreferenceSystem().registerPreference( "SI_Colors12", Vector3ImportStringCaller( g_camwindow_globals.color_selbrushes3d ), Vector3ExportStringCaller( g_camwindow_globals.color_selbrushes3d ) );
+ GlobalPreferenceSystem().registerPreference( "CameraRenderMode", makeIntStringImportCallback( RenderModeImportCaller() ), makeIntStringExportCallback( RenderModeExportCaller() ) );
+ GlobalPreferenceSystem().registerPreference( "StrafeMode", IntImportStringCaller( g_camwindow_globals_private.m_nStrafeMode ), IntExportStringCaller( g_camwindow_globals_private.m_nStrafeMode ) );
+
+ CamWnd_constructStatic();
+
+ Camera_registerPreferencesPage();
+}
+void CamWnd_Destroy(){
+ CamWnd_destroyStatic();