]> git.xonotic.org Git - xonotic/netradiant.git/commitdiff
Merge commit 'dfce2da577f1e56886ad26e58e37d9eda2d7c8a3' into garux-merge
authorThomas Debesse <dev@illwieckz.net>
Tue, 23 Feb 2021 01:01:27 +0000 (02:01 +0100)
committerThomas Debesse <dev@illwieckz.net>
Tue, 23 Feb 2021 01:01:27 +0000 (02:01 +0100)
20 files changed:
libs/mathlib.h
libs/mathlib/mathlib.c
libs/splines/math_matrix.h
radiant/brush.h
radiant/camwindow.cpp
radiant/camwindow.h
radiant/commands.cpp
radiant/entityinspector.cpp
radiant/entitylist.cpp
radiant/mainframe.cpp
radiant/mainframe.h
radiant/map.cpp
radiant/map.h
radiant/patchmanip.cpp
radiant/select.cpp
radiant/select.h
radiant/selection.cpp
radiant/texwindow.cpp
radiant/xywindow.cpp
radiant/xywindow.h

index fb135b8ae0de4d4797f5cdf3eb7f838f6d3e1a86..8ed115d606d7973d6c16bb692974b5c57ad6a956 100644 (file)
@@ -102,12 +102,19 @@ void _CrossProduct( vec3_t v1, vec3_t v2, vec3_t cross );
 // This define affect the precision of VectorNormalize() function only.
 #define MATHLIB_VECTOR_NORMALIZE_PRECISION_FIX 1
 vec_t VectorAccurateNormalize( const vec3_t in, vec3_t out );
-vec_t VectorFastNormalize( const vec3_t in, vec3_t out );
+vec_t VectorFastNormalize_( const vec3_t in, vec3_t out );
 #if MATHLIB_VECTOR_NORMALIZE_PRECISION_FIX
 #define VectorNormalize VectorAccurateNormalize
 #else
-#define VectorNormalize VectorFastNormalize
+#define VectorNormalize VectorFastNormalize_
 #endif
+
+#if 0 //use fastnormalize in a few -light spots
+       #define VectorFastNormalize VectorFastNormalize_
+#else
+       #define VectorFastNormalize VectorNormalize
+#endif
+
 vec_t ColorNormalize( const vec3_t in, vec3_t out );
 void VectorInverse( vec3_t v );
 void VectorPolar( vec3_t v, float radius, float theta, float phi );
index 9b530e2d487c557b8be48c84b7f4c1484a003c08..f8af1c7bb7da8db8eb420513172cedfbc548ef07 100644 (file)
@@ -179,7 +179,7 @@ vec_t VectorAccurateNormalize( const vec3_t in, vec3_t out ) {
        return (vec_t) length;
 }
 
-vec_t VectorFastNormalize( const vec3_t in, vec3_t out ) {
+vec_t VectorFastNormalize_( const vec3_t in, vec3_t out ) {
 
        // SmileTheory: This is ioquake3's VectorNormalize2
        //              for when accuracy matters less than speed
index b4427dcde922c6159953971174c4b2b595140c6c..b981567e0cd2adf9ad591ad7ded7d4001c8a85e2 100644 (file)
@@ -75,8 +75,13 @@ friend mat3_t   SkewSymmetric( idVec3 const &src );
 ID_INLINE mat3_t::mat3_t() {
 }
 
-ID_INLINE mat3_t::mat3_t(float src[3][3]) {
-    memcpy(mat, src, sizeof(float) * 3 * 3);
+ID_INLINE mat3_t::mat3_t( float src[ 3 ][ 3 ] ) {
+       //memcpy( mat, src, sizeof( src ) );
+       for( unsigned int i = 0; i < 3; i++ ) {
+               mat[i].x = src[i][0];
+               mat[i].y = src[i][1];
+               mat[i].z = src[i][2];
+       }
 }
 
 ID_INLINE mat3_t::mat3_t( idVec3 const &x, idVec3 const &y, idVec3 const &z ) {
index 74be4f2a6581b9b6b9a11be198dd1e580d6d05cf..e98bd76e86e70b77fe1916dcc1d1207958d5f718 100644 (file)
@@ -2516,6 +2516,34 @@ void forEachLight( const RendererLightCallback& callback ) const {
 }
 };
 
+class BoolSelector : public Selector
+{
+bool m_selected;
+SelectionIntersection m_intersection;
+Selectable* m_selectable;
+public:
+BoolSelector() : m_selected( false ){
+}
+
+void pushSelectable( Selectable& selectable ){
+       m_intersection = SelectionIntersection();
+       m_selectable = &selectable;
+}
+void popSelectable(){
+       if ( m_intersection.valid() ) {
+               m_selected = true;
+       }
+       m_intersection = SelectionIntersection();
+}
+void addIntersection( const SelectionIntersection& intersection ){
+       assign_if_closer( m_intersection, intersection );
+}
+
+bool isSelected(){
+       return m_selected;
+}
+};
+
 class FaceInstance
 {
 Face* m_face;
@@ -2720,7 +2748,9 @@ void selectPlane( Selector& selector, const Line& line, const PlaneCallback& sel
        {
                Vector3 v( vector3_subtracted( line_closest_point( line, ( *i ).vertex ), ( *i ).vertex ) );
                double dot = vector3_dot( getFace().plane3().normal(), v );
-               if ( dot <= 0 ) {
+               //globalOutputStream() << dot << "\n";
+               //epsilon to prevent perpendicular faces pickup
+               if ( dot <= 0.005 ) {
                        return;
                }
        }
@@ -2740,7 +2770,8 @@ bool trySelectPlane( const Line& line ){
        for ( Winding::const_iterator i = getFace().getWinding().begin(); i != getFace().getWinding().end(); ++i ){
                Vector3 v( vector3_subtracted( line_closest_point( line, ( *i ).vertex ), ( *i ).vertex ) );
                double dot = vector3_dot( getFace().plane3().normal(), v );
-               if ( dot <= 0 ) {
+               //epsilon to prevent perpendicular faces pickup
+               if ( dot <= 0.005 ) {
                        return false;
                }
        }
@@ -3127,6 +3158,20 @@ void selectVerticesOnPlanes( SelectionTest& test ){
        }
        while ( faceVertex.getFace() != m_vertex->m_faceVertex.getFace() );
 }
+
+void selectVerticesOnTestedFaces( SelectionTest& test ){
+       FaceVertexId faceVertex = m_vertex->m_faceVertex;
+       do
+       {
+               BoolSelector selector;
+               m_faceInstances[faceVertex.getFace()].testSelect( selector, test );
+               if( selector.isSelected() ){
+                       setSelected( true );
+               }
+               faceVertex = next_vertex( m_vertex->m_faces, faceVertex );
+       }
+       while ( faceVertex.getFace() != m_vertex->m_faceVertex.getFace() );
+}
 };
 
 class BrushInstanceVisitor
@@ -3609,6 +3654,15 @@ void selectVerticesOnPlanes( SelectionTest& test ){
 }
 
 
+void selectVerticesOnTestedFaces( SelectionTest& test ){
+       test.BeginMesh( localToWorld() );
+
+       for ( VertexInstances::iterator i = m_vertexInstances.begin(); i != m_vertexInstances.end(); ++i ){
+               ( *i ).selectVerticesOnTestedFaces( test );
+       }
+}
+
+
 void transformComponents( const Matrix4& matrix ){
        for ( FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i )
        {
index 2e412badcfe5b71184d5c68c0abfa1e2042065c8..41024bbe13a8200d802544e8e11e8762d2b2fa2c 100644 (file)
@@ -1696,20 +1696,22 @@ void GlobalCamera_ResetAngles(){
 
 void GlobalCamera_FocusOnSelected(){
        CamWnd& camwnd = *g_camwnd;
-
+/*
        Vector3 angles( Camera_getAngles( camwnd ) );
        Vector3 radangles( degrees_to_radians( angles[0] ), degrees_to_radians( angles[1] ), degrees_to_radians( angles[2] ) );
        Vector3 viewvector;
        viewvector[0] = cos( radangles[1] ) * cos( radangles[0] );
        viewvector[1] = sin( radangles[1] ) * cos( radangles[0] );
        viewvector[2] = sin( radangles[0] );
-
+*/
        Vector3 camorigin( Camera_getOrigin( camwnd ) );
 
        AABB aabb( aabb_for_minmax( Select_getWorkZone().d_work_min, Select_getWorkZone().d_work_max ) );
 
        View& view = *( camwnd.getCamera().m_view );
 
+       Vector3 viewvector( -view.GetModelview()[2], -view.GetModelview()[6], -view.GetModelview()[10] );
+
        Plane3 frustumPlanes[4];
        frustumPlanes[0] = plane3_translated( view.getFrustum().left, camorigin - aabb.origin );
        frustumPlanes[1] = plane3_translated( view.getFrustum().right, camorigin - aabb.origin );
@@ -1733,6 +1735,13 @@ void GlobalCamera_FocusOnSelected(){
                        }
                }
        }
+/*
+       globalOutputStream() << viewvector << "\n";
+       globalOutputStream() << view.GetModelview()[0] << " " << view.GetModelview()[1] << " " << view.GetModelview()[2] << " " << view.GetModelview()[3] << "\n"
+        << view.GetModelview()[4] << " " << view.GetModelview()[5] << " " << view.GetModelview()[6] << " " << view.GetModelview()[7] << "\n"
+         << view.GetModelview()[8] << " " << view.GetModelview()[9] << " " << view.GetModelview()[10] << " " << view.GetModelview()[11] << "\n"
+          << view.GetModelview()[12] << " " << view.GetModelview()[13] << " " << view.GetModelview()[14] << " " << view.GetModelview()[15] << "\n";
+*/
        Camera_setOrigin( camwnd, aabb.origin - viewvector * offset );
 }
 
index 438af28fc349d5ee08c9766c69ffe8a15451f8d8..0c537561c9366661034a422225bc4fa796f5ef54 100644 (file)
@@ -47,6 +47,8 @@ void GlobalCamera_Benchmark();
 const Vector3& Camera_getOrigin( CamWnd& camwnd );
 void Camera_setOrigin( CamWnd& camwnd, const Vector3& origin );
 
+void GlobalCamera_FocusOnSelected();
+
 enum
 {
        CAMERA_PITCH = 0, // up / down
index 9c1b7682246febb16f70c082faba1da1b418dbd2..d541e46ff142e80f7b0744650148708b49dd9a35 100644 (file)
@@ -219,6 +219,11 @@ void accelerator_edit_button_clicked( ui::Button btn, gpointer dialogptr ){
        if ( !gtk_tree_selection_get_selected( sel, &model, &iter ) ) {
                return;
        }
+       if ( dialog.m_waiting_for_key ) {
+               // unhighlight highlit
+               dialog.m_waiting_for_key = false;
+               gtk_list_store_set( GTK_LIST_STORE( dialog.m_model ), &dialog.m_command_iter, 2, false, -1 );
+       }
        dialog.m_command_iter = iter;
        dialog.m_model = ui::TreeModel::from(model);
 
@@ -232,6 +237,14 @@ void accelerator_edit_button_clicked( ui::Button btn, gpointer dialogptr ){
        dialog.m_waiting_for_key = true;
 }
 
+gboolean accelerator_tree_butt_press( GtkWidget* widget, GdkEventButton* event, gpointer dialogptr ){
+       if ( event->type == GDK_2BUTTON_PRESS && event->button == 1 ) {
+               accelerator_edit_button_clicked( ui::Button( ui::null ), dialogptr );
+               return TRUE;
+       }
+       return FALSE;
+}
+
 bool accelerator_window_key_press( ui::Window widget, GdkEventKey *event, gpointer dialogptr ){
        command_list_dialog_t &dialog = *(command_list_dialog_t *) dialogptr;
 
@@ -408,7 +421,9 @@ void DoCommandListDlg(){
                        auto view = ui::TreeView(ui::TreeModel::from(store._handle));
                        dialog.m_list = view;
 
-                       gtk_tree_view_set_enable_search(view, false ); // annoying
+                       //gtk_tree_view_set_enable_search( GTK_TREE_VIEW( view ), false ); // annoying
+
+                       g_signal_connect( G_OBJECT( view ), "button_press_event", G_CALLBACK( accelerator_tree_butt_press ), &dialog );
 
                        {
                                auto renderer = ui::CellRendererText(ui::New);
index 564d7173e3cfb328a9dbf4554fa5849567e9d1e0..60e68c187c3b25dd2fb5ec5903e42d48f7114071 100644 (file)
@@ -35,6 +35,7 @@
 #include <set>
 #include <gdk/gdkkeysyms.h>
 #include <uilib/uilib.h>
+#include <gtk/gtkstock.h>
 
 
 #include "os/path.h"
@@ -64,6 +65,8 @@
 #include "textureentry.h"
 #include "groupdialog.h"
 
+#include "select.h"
+
 ui::Entry numeric_entry_new(){
        auto entry = ui::Entry(ui::New);
        entry.show();
@@ -766,6 +769,8 @@ GtkCheckButton* g_entitySpawnflagsCheck[MAX_FLAGS];
 ui::Entry g_entityKeyEntry{ui::null};
 ui::Entry g_entityValueEntry{ui::null};
 
+GtkToggleButton* g_focusToggleButton;
+
 ui::ListStore g_entlist_store{ui::null};
 ui::ListStore g_entprops_store{ui::null};
 const EntityClass* g_current_flags = 0;
@@ -1396,6 +1401,21 @@ static gint EntityInspector_hideWindowKB( GtkWidget* widget, GdkEventKey* event,
        return FALSE;
 }
 
+void EntityInspector_selectTargeting( GtkButton *button, gpointer user_data ){
+       bool focus = gtk_toggle_button_get_active( g_focusToggleButton );
+       Select_ConnectedEntities( true, false, focus );
+}
+
+void EntityInspector_selectTargets( GtkButton *button, gpointer user_data ){
+       bool focus = gtk_toggle_button_get_active( g_focusToggleButton );
+       Select_ConnectedEntities( false, true, focus );
+}
+
+void EntityInspector_selectConnected( GtkButton *button, gpointer user_data ){
+       bool focus = gtk_toggle_button_get_active( g_focusToggleButton );
+       Select_ConnectedEntities( true, true, focus );
+}
+
 ui::Widget EntityInspector_constructWindow( ui::Window toplevel ){
     auto vbox = ui::VBox( FALSE, 2 );
        vbox.show();
@@ -1596,22 +1616,73 @@ ui::Widget EntityInspector_constructWindow( ui::Window toplevel ){
                                }
 
                                {
-                                       auto hbox = ui::HBox( TRUE, 4 );
+                                       auto hbox = ui::HBox( FALSE, 4 );
                                        hbox.show();
                                        vbox2.pack_start( hbox, FALSE, TRUE, 0 );
 
                                        {
                                                auto button = ui::Button( "Clear All" );
+#define GARUX_DISABLE_BUTTON_NOFOCUS
+#ifndef GARUX_DISABLE_BUTTON_NOFOCUS
+                                               GTK_WIDGET_UNSET_FLAGS( GTK_WIDGET( button ), GTK_CAN_FOCUS );
+#endif // GARUX_DISABLE_BUTTON_NOFOCUS
                                                button.show();
                                                button.connect( "clicked", G_CALLBACK( EntityInspector_clearAllKeyValues ), 0 );
                                                hbox.pack_start( button, TRUE, TRUE, 0 );
                                        }
                                        {
                                                auto button = ui::Button( "Delete Key" );
+#ifndef GARUX_DISABLE_BUTTON_NOFOCUS
+                                               GTK_WIDGET_UNSET_FLAGS( GTK_WIDGET( button ), GTK_CAN_FOCUS );
+#endif // GARUX_DISABLE_BUTTON_NOFOCUS
                                                button.show();
                                                button.connect( "clicked", G_CALLBACK( EntityInspector_clearKeyValue ), 0 );
                                                hbox.pack_start( button, TRUE, TRUE, 0 );
                                        }
+                                       {
+                                               GtkButton* button = GTK_BUTTON( gtk_button_new_with_label( "<" ) );
+                                               gtk_widget_set_tooltip_text( GTK_WIDGET( button ), "Select targeting entities" );
+#ifndef GARUX_DISABLE_BUTTON_NOFOCUS
+                                               GTK_WIDGET_UNSET_FLAGS( GTK_WIDGET( button ), GTK_CAN_FOCUS );
+#endif // GARUX_DISABLE_BUTTON_NOFOCUS
+                                               gtk_widget_show( GTK_WIDGET( button ) );
+                                               g_signal_connect( G_OBJECT( button ), "clicked", G_CALLBACK( EntityInspector_selectTargeting ), 0 );
+                                               gtk_box_pack_start( hbox, GTK_WIDGET( button ), FALSE, FALSE, 0 );
+                                       }
+                                       {
+                                               GtkButton* button = GTK_BUTTON( gtk_button_new_with_label( ">" ) );
+                                               gtk_widget_set_tooltip_text( GTK_WIDGET( button ), "Select targets" );
+#ifndef GARUX_DISABLE_BUTTON_NOFOCUS
+                                               GTK_WIDGET_UNSET_FLAGS( GTK_WIDGET( button ), GTK_CAN_FOCUS );
+#endif // GARUX_DISABLE_BUTTON_NOFOCUS
+                                               gtk_widget_show( GTK_WIDGET( button ) );
+                                               g_signal_connect( G_OBJECT( button ), "clicked", G_CALLBACK( EntityInspector_selectTargets ), 0 );
+                                               gtk_box_pack_start( hbox, GTK_WIDGET( button ), FALSE, FALSE, 0 );
+                                       }
+                                       {
+                                               GtkButton* button = GTK_BUTTON( gtk_button_new_with_label( "<->" ) );
+                                               gtk_widget_set_tooltip_text( GTK_WIDGET( button ), "Select connected entities" );
+#ifndef GARUX_DISABLE_BUTTON_NOFOCUS
+                                               GTK_WIDGET_UNSET_FLAGS( GTK_WIDGET( button ), GTK_CAN_FOCUS );
+#endif // GARUX_DISABLE_BUTTON_NOFOCUS
+                                               gtk_widget_show( GTK_WIDGET( button ) );
+                                               g_signal_connect( G_OBJECT( button ), "clicked", G_CALLBACK( EntityInspector_selectConnected ), 0 );
+                                               gtk_box_pack_start( hbox, GTK_WIDGET( button ), FALSE, FALSE, 0 );
+                                       }
+                                       {
+                                               GtkWidget* button = gtk_toggle_button_new();
+                                               GtkImage* image = GTK_IMAGE( gtk_image_new_from_stock( GTK_STOCK_ZOOM_IN, GTK_ICON_SIZE_SMALL_TOOLBAR ) );
+                                               gtk_widget_show( GTK_WIDGET( image ) );
+                                               gtk_container_add( GTK_CONTAINER( button ), GTK_WIDGET( image ) );
+                                               gtk_button_set_relief( GTK_BUTTON( button ), GTK_RELIEF_NONE );
+#ifndef GARUX_DISABLE_BUTTON_NOFOCUS
+                                               GTK_WIDGET_UNSET_FLAGS( button, GTK_CAN_FOCUS );
+#endif // GARUX_DISABLE_BUTTON_NOFOCUS
+                                               gtk_box_pack_start( hbox, button, FALSE, FALSE, 0 );
+                                               gtk_widget_set_tooltip_text( button, "Focus on Selected" );
+                                               gtk_widget_show( button );
+                                               g_focusToggleButton = GTK_TOGGLE_BUTTON( button );
+                                       }
                                }
                        }
 
index 0230fe6d01cf9a7e2e2a80e169cbc4050efa9e05..6c2d0889fce1eadd82ae64a943584f0bbb398ca5 100644 (file)
@@ -25,6 +25,8 @@
 
 #include <uilib/uilib.h>
 #include <gtk/gtk.h>
+#include <gtk/gtkcheckbutton.h>
+#include <gtk/gtkvbox.h>
 
 #include "string/string.h"
 #include "scenelib.h"
@@ -40,6 +42,8 @@
 
 #include "treemodel.h"
 
+#include "mainframe.h"
+
 void RedrawEntityList();
 typedef FreeCaller<void(), RedrawEntityList> RedrawEntityListCaller;
 
@@ -60,6 +64,7 @@ IdleDraw m_idleDraw;
 WindowPositionTracker m_positionTracker;
 
 ui::Window m_window;
+ui::Widget m_check;
 ui::TreeView m_tree_view{ui::null};
 ui::TreeModel m_tree_model{ui::null};
 bool m_selection_disabled;
@@ -68,6 +73,7 @@ EntityList() :
        m_dirty( EntityList::eDefault ),
        m_idleDraw( RedrawEntityListCaller() ),
        m_window( ui::null ),
+       m_check( ui::null ),
        m_selection_disabled( false ){
 }
 
@@ -154,6 +160,9 @@ static gboolean entitylist_tree_select( ui::TreeSelection selection, ui::TreeMod
                getEntityList().m_selection_disabled = true;
                selectable->setSelected( path_currently_selected == FALSE );
                getEntityList().m_selection_disabled = false;
+               if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( getEntityList().m_check ) ) ){
+                       FocusAllViews();
+               }
                return TRUE;
        }
 
@@ -292,8 +301,13 @@ void EntityList_constructWindow( ui::Window main_window ){
        getEntityList().m_window = window;
 
        {
+               ui::VBox vbox = ui::VBox( FALSE, 0 );
+               gtk_container_set_border_width( GTK_CONTAINER( vbox ), 0 );
+               vbox.show();
+               window.add( vbox );
+
                auto scr = create_scrolled_window( ui::Policy::AUTOMATIC, ui::Policy::AUTOMATIC );
-               window.add(scr);
+               vbox.pack_start( scr, TRUE, TRUE, 0 );
 
                {
             auto view = ui::TreeView(ui::New);
@@ -316,6 +330,13 @@ void EntityList_constructWindow( ui::Window main_window ){
                        scr.add(view);
                        getEntityList().m_tree_view = view;
                }
+               {
+                       ui::Widget check = ui::Widget::from( gtk_check_button_new_with_label( "Focus on Selected" ) );
+                       gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( check ), FALSE );
+                       check.show();
+                       vbox.pack_start( check, FALSE, FALSE, 0 );
+                       getEntityList().m_check = check;
+               }
        }
 
        EntityList_ConnectSignals( getEntityList().m_tree_view );
index 4e4efa67fb9ac9cee605ad1d2ef517eaeaef29b9..3f39db58f56627fcf85753493441a5640f6b514e 100644 (file)
@@ -1310,6 +1310,12 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const {
                         && selectable->isSelected() ) {
                        return false;
                }
+               if( doMakeUnique && instance.childSelected() ){
+                       NodeSmartReference clone( Node_Clone_Selected( path.top() ) );
+                       Map_gatherNamespaced( clone );
+                       Node_getTraversable( path.parent().get() )->insert( clone );
+                       return false;
+               }
        }
 
        return true;
@@ -2065,6 +2071,7 @@ ui::MenuItem create_edit_menu(){
 //     }
        create_menu_item_with_mnemonic( menu, "Select All Of Type", "SelectAllOfType" );
        create_menu_item_with_mnemonic( menu, "_Expand Selection To Entities", "ExpandSelectionToEntities" );
+       create_menu_item_with_mnemonic( menu, "Select Connected Entities", "SelectConnectedEntities" );
 
        menu_separator( menu );
        create_menu_item_with_mnemonic( menu, "Pre_ferences...", "Preferences" );
@@ -2143,6 +2150,7 @@ ui::MenuItem create_view_menu( MainFrame::EViewStyle style ){
                        create_menu_item_with_mnemonic( orthographic_menu, "Center on Selected", "NextView" );
                }
 
+               create_menu_item_with_mnemonic( orthographic_menu, "Focus on Selected", "XYFocusOnSelected" );
                create_menu_item_with_mnemonic( orthographic_menu, "Center on Selected", "CenterXYView" );
                menu_separator( orthographic_menu );
                create_menu_item_with_mnemonic( orthographic_menu, "_XY 100%", "Zoom100" );
@@ -3571,6 +3579,10 @@ void Maximize_View(){
                g_maximizeview.toggle();
 }
 
+void FocusAllViews(){
+       XY_Centralize(); //using centralizing here, not focusing function
+       GlobalCamera_FocusOnSelected();
+}
 
 #include "preferencesystem.h"
 #include "stringio.h"
@@ -3608,6 +3620,7 @@ void MainFrame_Construct(){
        GlobalCommands_insert( "SelectInside", makeCallbackF(Select_Inside) );
        GlobalCommands_insert( "SelectTouching", makeCallbackF(Select_Touching) );
        GlobalCommands_insert( "ExpandSelectionToEntities", makeCallbackF(Scene_ExpandSelectionToEntities), Accelerator( 'E', (GdkModifierType)( GDK_MOD1_MASK | GDK_CONTROL_MASK ) ) );
+       GlobalCommands_insert( "SelectConnectedEntities", makeCallbackF(SelectConnectedEntities), Accelerator( 'E', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) );
        GlobalCommands_insert( "Preferences", makeCallbackF(PreferencesDialog_showDialog), Accelerator( 'P' ) );
 
        GlobalCommands_insert( "ToggleConsole", makeCallbackF(Console_ToggleShow), Accelerator( 'O' ) );
index 296319cc44f7645513ce4ec23f5298a2d2e7ad15..e2d2e0d70d10e0e558acf8e4e8d65fc8d15063c1 100644 (file)
@@ -282,4 +282,6 @@ void XYWindowMouseDown_disconnect( MouseEventHandlerId id );
 
 extern ui::Widget g_page_entity;
 
+void FocusAllViews();
+
 #endif
index e52a3d188075da20a3d93b16a4251162721447f9..bfce674bf0f9977bd22052cd72c37892c6a5ef3e 100644 (file)
@@ -765,6 +765,50 @@ scene::Node& Node_Clone( scene::Node& node ){
        return clone;
 }
 
+bool Node_instanceSelected( scene::Node& node );
+
+class CloneAllSelected : public scene::Traversable::Walker
+{
+mutable scene::Path m_path;
+public:
+CloneAllSelected( scene::Node& root )
+       : m_path( makeReference( root ) ){
+}
+bool pre( scene::Node& node ) const {
+       if ( node.isRoot() ) {
+               return false;
+       }
+
+       if( Node_instanceSelected( node ) ){
+               m_path.push( makeReference( node_clone( node ) ) );
+               m_path.top().get().IncRef();
+       }
+
+       return true;
+}
+void post( scene::Node& node ) const {
+       if ( node.isRoot() ) {
+               return;
+       }
+
+       if( Node_instanceSelected( node ) ){
+               Node_getTraversable( m_path.parent() )->insert( m_path.top() );
+
+               m_path.top().get().DecRef();
+               m_path.pop();
+       }
+}
+};
+
+scene::Node& Node_Clone_Selected( scene::Node& node ){
+       scene::Node& clone = node_clone( node );
+       scene::Traversable* traversable = Node_getTraversable( node );
+       if ( traversable != 0 ) {
+               traversable->traverse( CloneAllSelected( clone ) );
+       }
+       return clone;
+}
+
 
 typedef std::map<CopiedString, std::size_t> EntityBreakdown;
 
index c68b02751e270df0790012a283216e01dd98ccca..d23e3928500256c1603eb43233286e1269359775 100644 (file)
@@ -125,6 +125,7 @@ bool Map_Save();
 bool Map_SaveAs();
 
 scene::Node& Node_Clone( scene::Node& node );
+scene::Node& Node_Clone_Selected( scene::Node& node );
 
 void DoMapInfo();
 
index 7e21b4fcdedb9ea4a32a29d5777ecff1780f2d96..4578cad42c4181a8f55217b978d065e4715a73fb 100644 (file)
@@ -804,8 +804,10 @@ void Patch_registerCommands(){
        GlobalCommands_insert( "PatchDeleteFirstRow", makeCallbackF(Patch_DeleteFirstRow), Accelerator( GDK_KEY_KP_Subtract, (GdkModifierType)GDK_CONTROL_MASK ) );
        GlobalCommands_insert( "PatchDeleteLastRow", makeCallbackF(Patch_DeleteLastRow) );
        GlobalCommands_insert( "InvertCurve", makeCallbackF(Patch_Invert), Accelerator( 'I', (GdkModifierType)GDK_CONTROL_MASK ) );
-       GlobalCommands_insert( "RedisperseRows", makeCallbackF(Patch_RedisperseRows), Accelerator( 'E', (GdkModifierType)GDK_CONTROL_MASK ) );
-       GlobalCommands_insert( "RedisperseCols", makeCallbackF(Patch_RedisperseCols), Accelerator( 'E', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) );
+       // GlobalCommands_insert( "RedisperseRows", makeCallbackF(Patch_RedisperseRows), Accelerator( 'E', (GdkModifierType)GDK_CONTROL_MASK ) );
+       GlobalCommands_insert( "RedisperseRows", makeCallbackF(Patch_RedisperseRows) );
+       // GlobalCommands_insert( "RedisperseCols", makeCallbackF(Patch_RedisperseCols), Accelerator( 'E', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) );
+       GlobalCommands_insert( "RedisperseCols", makeCallbackF(Patch_RedisperseCols) );
        GlobalCommands_insert( "SmoothRows", makeCallbackF(Patch_SmoothRows), Accelerator( 'W', (GdkModifierType)GDK_CONTROL_MASK ) );
        GlobalCommands_insert( "SmoothCols", makeCallbackF(Patch_SmoothCols), Accelerator( 'W', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) );
        GlobalCommands_insert( "MatrixTranspose", makeCallbackF(Patch_Transpose), Accelerator( 'M', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) );
index f6546bd8cb44fc9411a25cd54bbde9fc0e931927..582c7d70cc3b070e1662c63a97fbbd34b0b3f1c2 100644 (file)
@@ -465,6 +465,13 @@ void Select_SetShader( const char* shader ){
        Scene_BrushSetShader_Component_Selected( GlobalSceneGraph(), shader );
 }
 
+void Select_SetShader_Undo( const char* shader ){
+       if ( GlobalSelectionSystem().countSelectedComponents() != 0 || GlobalSelectionSystem().countSelected() != 0 ) {
+               UndoableCommand undo( "textureNameSetSelected" );
+               Select_SetShader( shader );
+       }
+}
+
 void Select_SetTexdef( const TextureProjection& projection ){
        if ( GlobalSelectionSystem().Mode() != SelectionSystem::eComponent ) {
                Scene_BrushSetTexdef_Selected( GlobalSceneGraph(), projection );
@@ -1365,3 +1372,79 @@ void DoScaleDlg(){
 
        g_scale_dialog.window.show();
 }
+
+
+class EntityGetSelectedPropertyValuesWalker_nonEmpty : public scene::Graph::Walker
+{
+PropertyValues& m_propertyvalues;
+const char *m_prop;
+const NodeSmartReference worldspawn;
+public:
+EntityGetSelectedPropertyValuesWalker_nonEmpty( const char *prop, PropertyValues& propertyvalues )
+       : m_propertyvalues( propertyvalues ), m_prop( prop ), worldspawn( Map_FindOrInsertWorldspawn( g_map ) ){
+}
+bool pre( const scene::Path& path, scene::Instance& instance ) const {
+       Entity* entity = Node_getEntity( path.top() );
+       if ( entity != 0 ){
+               if( path.top().get() != worldspawn ){
+                       Selectable* selectable = Instance_getSelectable( instance );
+                       if ( ( selectable != 0 && selectable->isSelected() ) || instance.childSelected() ) {
+                               const char* keyvalue = entity->getKeyValue( m_prop );
+                               if ( !string_empty( keyvalue ) && !propertyvalues_contain( m_propertyvalues, keyvalue ) ) {
+                                       m_propertyvalues.push_back( keyvalue );
+                               }
+                       }
+               }
+               return false;
+       }
+       return true;
+}
+};
+
+void Scene_EntityGetPropertyValues_nonEmpty( scene::Graph& graph, const char *prop, PropertyValues& propertyvalues ){
+       graph.traverse( EntityGetSelectedPropertyValuesWalker_nonEmpty( prop, propertyvalues ) );
+}
+
+#include "preferences.h"
+
+void Select_ConnectedEntities( bool targeting, bool targets, bool focus ){
+       PropertyValues target_propertyvalues;
+       PropertyValues targetname_propertyvalues;
+       const char *target_prop = "target";
+       const char *targetname_prop;
+       if ( g_pGameDescription->mGameType == "doom3" ) {
+               targetname_prop = "name";
+       }
+       else{
+               targetname_prop = "targetname";
+       }
+
+       if( targeting ){
+               Scene_EntityGetPropertyValues_nonEmpty( GlobalSceneGraph(), targetname_prop, targetname_propertyvalues );
+       }
+       if( targets ){
+               Scene_EntityGetPropertyValues_nonEmpty( GlobalSceneGraph(), target_prop, target_propertyvalues );
+       }
+
+       if( target_propertyvalues.empty() && targetname_propertyvalues.empty() ){
+               globalErrorStream() << "SelectConnectedEntities: nothing found\n";
+               return;
+       }
+
+       if( !targeting || !targets ){
+               GlobalSelectionSystem().setSelectedAll( false );
+       }
+       if ( targeting && !targetname_propertyvalues.empty() ) {
+               Scene_EntitySelectByPropertyValues( GlobalSceneGraph(), target_prop, targetname_propertyvalues );
+       }
+       if ( targets && !target_propertyvalues.empty() ) {
+               Scene_EntitySelectByPropertyValues( GlobalSceneGraph(), targetname_prop, target_propertyvalues );
+       }
+       if( focus ){
+               FocusAllViews();
+       }
+}
+
+void SelectConnectedEntities(){
+       Select_ConnectedEntities( true, true, false );
+}
index 5a602742fd766e007e412ccce49fa784f97706db..88d25f68abef201c0e8fbba377882f4468d60c71 100644 (file)
@@ -46,11 +46,15 @@ void Selection_MoveUp();
 
 void Select_AllOfType();
 
+void Select_ConnectedEntities( bool targeting, bool targets, bool focus );
+void SelectConnectedEntities();
+
 void DoRotateDlg();
 void DoScaleDlg();
 
 
 void Select_SetShader( const char* shader );
+void Select_SetShader_Undo( const char* shader );
 
 class TextureProjection;
 void Select_SetTexdef( const TextureProjection& projection );
index 2ac9844517fd49c83203c2c6734afcc2d6cd5e33..53389df78bab57262e31bd82206df2bc2a9a4f84 100644 (file)
@@ -1893,12 +1893,12 @@ bool Scene_forEachPlaneSelectable_selectPlanes( scene::Graph& graph, Selector& s
 
 
 #include "brush.h"
-/*
-class TestedBrushPlanesSelectVeritces : public scene::Graph::Walker
+
+class TestedBrushFacesSelectVeritces : public scene::Graph::Walker
 {
 SelectionTest& m_test;
 public:
-TestedBrushPlanesSelectVeritces( SelectionTest& test )
+TestedBrushFacesSelectVeritces( SelectionTest& test )
        : m_test( test ){
 }
 bool pre( const scene::Path& path, scene::Instance& instance ) const {
@@ -1907,7 +1907,7 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const {
                if ( selectable != 0 && selectable->isSelected() ) {
                        BrushInstance* brushInstance = Instance_getBrush( instance );
                        if ( brushInstance != 0 ) {
-                               brushInstance->selectVerticesOnPlanes( m_test );
+                               brushInstance->selectVerticesOnTestedFaces( m_test );
                        }
                }
        }
@@ -1915,10 +1915,10 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const {
 }
 };
 
-void Scene_forEachTestedBrushPlane_selectVertices( scene::Graph& graph, SelectionTest& test ){
-       graph.traverse( TestedBrushPlanesSelectVeritces( test ) );
+void Scene_forEachTestedBrushFace_selectVertices( scene::Graph& graph, SelectionTest& test ){
+       graph.traverse( TestedBrushFacesSelectVeritces( test ) );
 }
-*/
+
 class BrushPlanesSelectVeritces : public scene::Graph::Walker
 {
 SelectionTest& m_test;
@@ -2687,8 +2687,8 @@ void testSelect( const View& view, const Matrix4& pivot2world ){
                                        m_dragSelectable.setSelected( false );
                                }
                                if( deepSelector.best().empty() ){
-                                       //Scene_forEachTestedBrushPlane_selectVertices( GlobalSceneGraph(), test );     //todo? drag clicked face
-                                       Scene_forEachBrushPlane_selectVertices( GlobalSceneGraph(), test );
+                                       Scene_forEachTestedBrushFace_selectVertices( GlobalSceneGraph(), test );        //drag clicked face
+                                       //Scene_forEachBrushPlane_selectVertices( GlobalSceneGraph(), test );
                                        m_selected = true;
                                }
                        }
index 00969834e90e47146e3a65723589043bb39c1885..3ad553d6932311e6c960e8f14263bf30f2b119e0 100644 (file)
@@ -1076,16 +1076,15 @@ IShader* Texture_At( TextureBrowser& textureBrowser, int mx, int my ){
    By mouse click
    ==============
  */
-void SelectTexture( TextureBrowser& textureBrowser, int mx, int my, guint32 flags ){
+void SelectTexture( TextureBrowser& textureBrowser, int mx, int my, guint32 flags, bool texturizeSelection ){
        if ( ( flags & GDK_SHIFT_MASK ) == 0 ) {
                IShader* shader = Texture_At( textureBrowser, mx, my );
                if ( shader != 0 ) {
                        TextureBrowser_SetSelectedShader( textureBrowser, shader->getName() );
                        TextureBrowser_textureSelected( shader->getName() );
 
-                       if ( !FindTextureDialog_isOpen() && !textureBrowser.m_rmbSelected ) {
-                               UndoableCommand undo( "textureNameSetSelected" );
-                               Select_SetShader( shader->getName() );
+                       if ( !FindTextureDialog_isOpen() && !textureBrowser.m_rmbSelected && !texturizeSelection ) {
+                               Select_SetShader_Undo( shader->getName() );
                        }
                }
        }
@@ -1127,8 +1126,8 @@ void TextureBrowser_Tracking_MouseDown( TextureBrowser& textureBrowser ){
        textureBrowser.m_freezePointer.freeze_pointer( textureBrowser.m_parent, textureBrowser.m_gl_widget, TextureBrowser_trackingDelta, &textureBrowser );
 }
 
-void TextureBrowser_Selection_MouseDown( TextureBrowser& textureBrowser, guint32 flags, int pointx, int pointy ){
-       SelectTexture( textureBrowser, pointx, textureBrowser.height - 1 - pointy, flags );
+void TextureBrowser_Selection_MouseDown( TextureBrowser& textureBrowser, guint32 flags, int pointx, int pointy, bool texturizeSelection ){
+       SelectTexture( textureBrowser, pointx, textureBrowser.height - 1 - pointy, flags, texturizeSelection );
 }
 
 void TextureBrowser_Selection_MouseUp( TextureBrowser& textureBrowser, guint32 flags, int pointx, int pointy ){
@@ -1482,7 +1481,7 @@ gboolean TextureBrowser_button_press( ui::Widget widget, GdkEventButton* event,
                if ( event->button == 3 ) {
                        if ( GlobalTextureBrowser().m_tags ) {
                                textureBrowser->m_rmbSelected = true;
-                               TextureBrowser_Selection_MouseDown( *textureBrowser, event->state, static_cast<int>( event->x ), static_cast<int>( event->y ) );
+                               TextureBrowser_Selection_MouseDown( *textureBrowser, event->state, static_cast<int>( event->x ), static_cast<int>( event->y ), false );
 
                                BuildStoreAssignedTags( textureBrowser->m_assigned_store, textureBrowser->shader.c_str(), textureBrowser );
                                BuildStoreAvailableTags( textureBrowser->m_available_store, textureBrowser->m_assigned_store, textureBrowser->m_all_tags, textureBrowser );
@@ -1498,8 +1497,8 @@ gboolean TextureBrowser_button_press( ui::Widget widget, GdkEventButton* event,
                                TextureBrowser_Tracking_MouseDown( *textureBrowser );
                        }
                }
-               else if ( event->button == 1 ) {
-                       TextureBrowser_Selection_MouseDown( *textureBrowser, event->state, static_cast<int>( event->x ), static_cast<int>( event->y ) );
+               else if ( event->button == 1 || event->button == 2 ) {
+                       TextureBrowser_Selection_MouseDown( *textureBrowser, event->state, static_cast<int>( event->x ), static_cast<int>( event->y ), event->button == 2 );
 
                        if ( GlobalTextureBrowser().m_tags ) {
                                textureBrowser->m_rmbSelected = false;
@@ -1511,7 +1510,6 @@ gboolean TextureBrowser_button_press( ui::Widget widget, GdkEventButton* event,
                #define GARUX_DISABLE_2BUTTON
                #ifndef GARUX_DISABLE_2BUTTON
                CopiedString texName = textureBrowser->shader;
-               //const char* sh = texName.c_str();
                char* sh = const_cast<char*>( texName.c_str() );
                char* dir = strrchr( sh, '/' );
                if( dir != NULL ){
@@ -2067,6 +2065,7 @@ void TextureBrowser_searchTags(){
                                TextureDirectory_loadTexture( path.c_str(), name.c_str() );
                        }
                }
+               TextureBrowser_SetHideUnused( g_TextureBrowser, false );
                g_TextureBrowser.m_searchedTags = true;
                g_TextureBrowser_currentDirectory = tags_searched;
 
index 3e81deefa49f0c974b8107a358e1b223de017a57..c597b2e9505b9f5630fdf8da73b75660da2a19f1 100644 (file)
@@ -557,6 +557,20 @@ void XYWnd::ZoomInWithMouse( int pointx, int pointy ){
        }
 }
 
+void XYWnd::FocusOnBounds( AABB& bounds ){
+       SetOrigin( bounds.origin );
+       int nDim1 = ( m_viewType == YZ ) ? 1 : 0;
+       int nDim2 = ( m_viewType == XY ) ? 1 : 2;
+       if( bounds.extents[ nDim1 ] < 128.f )
+               bounds.extents[ nDim1 ] = 128.f;
+       if( bounds.extents[ nDim2 ] < 128.f )
+               bounds.extents[ nDim2 ] = 128.f;
+       float scale1 = Width() / ( 3.f * bounds.extents[ nDim1 ] );
+       float scale2 = Height() / ( 3.f * bounds.extents[ nDim2 ] );
+       SetScale( MIN( scale1, scale2 ) );
+
+}
+
 VIEWTYPE GlobalXYWnd_getCurrentViewType(){
        ASSERT_NOTNULL( g_pParentWnd );
        ASSERT_NOTNULL( g_pParentWnd->ActiveXY() );
@@ -2708,7 +2722,7 @@ void XYWnd::OnEntityCreate( const char* item ){
 
 
 
-void GetFocusPosition( Vector3& position ){
+void GetCenterPosition( Vector3& position ){
        if ( GlobalSelectionSystem().countSelected() != 0 ) {
                Select_GetMid( position );
        }
@@ -2718,15 +2732,15 @@ void GetFocusPosition( Vector3& position ){
        }
 }
 
-void XYWnd_Focus( XYWnd* xywnd ){
+void XYWnd_Centralize( XYWnd* xywnd ){
        Vector3 position;
-       GetFocusPosition( position );
+       GetCenterPosition( position );
        xywnd->PositionView( position );
 }
 
-void XY_Split_Focus(){
+void XY_Split_Centralize(){
        Vector3 position;
-       GetFocusPosition( position );
+       GetCenterPosition( position );
        if ( g_pParentWnd->GetXYWnd() ) {
                g_pParentWnd->GetXYWnd()->PositionView( position );
        }
@@ -2738,10 +2752,52 @@ void XY_Split_Focus(){
        }
 }
 
+void XY_Centralize(){
+       if ( g_pParentWnd->CurrentStyle() == MainFrame::eSplit || g_pParentWnd->CurrentStyle() == MainFrame::eFloating ) {
+               // centralize all
+               XY_Split_Centralize();
+               return;
+       }
+
+       XYWnd* xywnd = g_pParentWnd->GetXYWnd();
+       XYWnd_Centralize( xywnd );
+}
+
+
+
+void GetSelectionBbox( AABB& bounds ){
+       if ( GlobalSelectionSystem().countSelected() != 0 ) {
+               Scene_BoundsSelected( GlobalSceneGraph(), bounds );
+       }
+       else
+       {
+               bounds = AABB( Camera_getOrigin( *g_pParentWnd->GetCamWnd() ), Vector3( 128.f, 128.f, 128.f ) );
+       }
+}
+
+void XYWnd_Focus( XYWnd* xywnd ){
+       AABB bounds;
+       GetSelectionBbox( bounds );
+       xywnd->FocusOnBounds( bounds );
+}
+
+void XY_Split_Focus(){
+       AABB bounds;
+       GetSelectionBbox( bounds );
+       if ( g_pParentWnd->GetXYWnd() ) {
+               g_pParentWnd->GetXYWnd()->FocusOnBounds( bounds );
+       }
+       if ( g_pParentWnd->GetXZWnd() ) {
+               g_pParentWnd->GetXZWnd()->FocusOnBounds( bounds );
+       }
+       if ( g_pParentWnd->GetYZWnd() ) {
+               g_pParentWnd->GetYZWnd()->FocusOnBounds( bounds );
+       }
+}
+
 void XY_Focus(){
        if ( g_pParentWnd->CurrentStyle() == MainFrame::eSplit || g_pParentWnd->CurrentStyle() == MainFrame::eFloating ) {
-               // cannot do this in a split window
-               // do something else that the user may want here
+               // focus all
                XY_Split_Focus();
                return;
        }
@@ -2750,16 +2806,18 @@ void XY_Focus(){
        XYWnd_Focus( xywnd );
 }
 
+
+
 void XY_TopFrontSide( VIEWTYPE viewtype ){
        if ( g_pParentWnd->CurrentStyle() == MainFrame::eSplit ) {
                // cannot do this in a split window
                // do something else that the user may want here
-               XY_Split_Focus();
+               XY_Split_Centralize();
                return;
        }
        XYWnd* xywnd = g_pParentWnd->CurrentStyle() == MainFrame::eFloating ? g_pParentWnd->ActiveXY() : g_pParentWnd->GetXYWnd();
        xywnd->SetViewType( viewtype );
-       XYWnd_Focus( xywnd );
+       XYWnd_Centralize( xywnd );
 }
 
 void XY_Top(){
@@ -2784,14 +2842,14 @@ void XY_NextView( XYWnd* xywnd ){
        else{
                xywnd->SetViewType( XY );
        }
-       XYWnd_Focus( xywnd );
+       XYWnd_Centralize( xywnd );
 }
 
 void XY_Next(){
        if ( g_pParentWnd->CurrentStyle() == MainFrame::eSplit ) {
                // cannot do this in a split window
                // do something else that the user may want here
-               XY_Split_Focus();
+               XY_Split_Centralize();
                return;
        }
        XYWnd* xywnd = g_pParentWnd->CurrentStyle() == MainFrame::eFloating ? g_pParentWnd->ActiveXY() : g_pParentWnd->GetXYWnd();
@@ -3157,7 +3215,8 @@ void XYWindow_Construct(){
        GlobalCommands_insert( "ViewSide", makeCallbackF(XY_Side), Accelerator( GDK_KEY_KP_Page_Down ) );
        GlobalCommands_insert( "ViewFront", makeCallbackF(XY_Front), Accelerator( GDK_KEY_KP_End ) );
        GlobalCommands_insert( "Zoom100", makeCallbackF(XY_Zoom100) );
-       GlobalCommands_insert( "CenterXYView", makeCallbackF(XY_Focus), Accelerator( GDK_KEY_Tab, (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) );
+       GlobalCommands_insert( "CenterXYView", makeCallbackF(XY_Centralize), Accelerator( GDK_Tab, (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) );
+       GlobalCommands_insert( "XYFocusOnSelected", makeCallbackF(XY_Focus), Accelerator( GDK_grave ) );
 
        GlobalPreferenceSystem().registerPreference( "ClipCaulk", make_property_string( g_clip_useCaulk ) );
 
@@ -3187,8 +3246,6 @@ void XYWindow_Construct(){
        GlobalPreferenceSystem().registerPreference( "SI_Colors11", make_property_string( g_xywindow_globals.color_selbrushes ) );
 
 
-
-
        GlobalPreferenceSystem().registerPreference( "XZVIS", make_property_string<ToggleShown_Bool>( g_xz_front_shown ) );
        GlobalPreferenceSystem().registerPreference( "YZVIS", make_property_string<ToggleShown_Bool>( g_yz_side_shown ) );
 
index 966f374996a95f6b738eaf2b3bf16855b651c49b..4eb6cf55f1f40fbd8a9739deaf6c5470c5c76012 100644 (file)
@@ -127,6 +127,7 @@ guint m_zoom_focusOut;
 void ZoomIn();
 void ZoomOut();
 void ZoomInWithMouse( int pointx, int pointy );
+void FocusOnBounds( AABB& bounds );
 
 void RenderActive();
 void SetActive( bool b ){
@@ -249,6 +250,7 @@ inline void XYWnd_Update( XYWnd& xywnd ){
        xywnd.queueDraw();
 }
 
+void XY_Centralize();
 
 struct xywindow_globals_t
 {