* up/down floor walker: examine all types of scene nodes (was brushes only)

consider only top/down and selected instances (was whole scene)
				fix jam at close coords
				also jump to bottommost coord of considered objects
This commit is contained in:
Garux 2018-06-08 21:05:47 +03:00
parent 2f38cfb4a3
commit aff5c8093e
2 changed files with 42 additions and 32 deletions

View File

@ -1441,51 +1441,61 @@ CamWnd::~CamWnd(){
class FloorHeightWalker : public scene::Graph::Walker class FloorHeightWalker : public scene::Graph::Walker
{ {
float m_current; Vector3 m_current;
float& m_bestUp;
float& m_bestDown;
public: public:
FloorHeightWalker( float current, float& bestUp, float& bestDown ) : mutable float m_bestUp;
m_current( current ), m_bestUp( bestUp ), m_bestDown( bestDown ){ mutable float m_bestDown;
bestUp = g_MaxWorldCoord; mutable float m_bottom;
bestDown = -g_MaxWorldCoord; FloorHeightWalker( const Vector3& current ) :
m_current( current ), m_bestUp( g_MaxWorldCoord ), m_bestDown( g_MinWorldCoord ), m_bottom( g_MaxWorldCoord ){
} }
bool pre( const scene::Path& path, scene::Instance& instance ) const { bool pre( const scene::Path& path, scene::Instance& instance ) const {
if ( path.top().get().visible() if( !path.top().get().visible() )
&& Node_isBrush( path.top() ) ) { // this node is a floor
const AABB& aabb = instance.worldAABB();
float floorHeight = aabb.origin.z() + aabb.extents.z();
if ( floorHeight > m_current && floorHeight < m_bestUp ) {
m_bestUp = floorHeight;
}
if ( floorHeight < m_current && floorHeight > m_bestDown ) {
m_bestDown = floorHeight;
}
}
else if( !path.top().get().visible() ){
return false; return false;
if ( !path.top().get().isRoot() && !node_is_group( path.top() ) ) {
const AABB& aabb = instance.worldAABB();
if( instance.isSelected() || ( m_current.x() > aabb.origin.x() - aabb.extents.x()
&& m_current.x() < aabb.origin.x() + aabb.extents.x()
&& m_current.y() > aabb.origin.y() - aabb.extents.y()
&& m_current.y() < aabb.origin.y() + aabb.extents.y() ) ){
const float floorHeight = aabb.origin.z() + aabb.extents.z() + 32.f;
if ( floorHeight > m_current.z() + 0.1f && floorHeight < m_bestUp ) /* 0.1f epsilon to prevent jam at (close?) coords */
m_bestUp = floorHeight;
if ( floorHeight < m_current.z() - 0.1f && floorHeight > m_bestDown )
m_bestDown = floorHeight;
const float bottom = aabb.origin.z() - aabb.extents.z() - 16.f;
if( m_bottom > bottom )
m_bottom = bottom;
}
} }
return true; return true;
} }
}; };
void CamWnd::Cam_ChangeFloor( bool up ){ void CamWnd::Cam_ChangeFloor( bool up ){
float current = m_Camera.origin[2] - 48; FloorHeightWalker walker( m_Camera.origin );
float bestUp; GlobalSceneGraph().traverse( walker );
float bestDown; float current = m_Camera.origin.z();
GlobalSceneGraph().traverse( FloorHeightWalker( current, bestUp, bestDown ) );
if ( up && bestUp != g_MaxWorldCoord ) { if ( up ){
current = bestUp; if( walker.m_bottom != g_MaxWorldCoord && walker.m_bottom > current )
current = walker.m_bottom;
else if( walker.m_bestUp != g_MaxWorldCoord )
current = walker.m_bestUp;
} }
if ( !up && bestDown != -g_MaxWorldCoord ) { else{
current = bestDown; if ( walker.m_bestDown != g_MinWorldCoord )
current = walker.m_bestDown;
else if( walker.m_bottom != g_MaxWorldCoord && walker.m_bottom < current )
current = walker.m_bottom;
} }
m_Camera.origin[2] = current + 48; if( m_Camera.origin.z() != current ){
m_Camera.origin.z() = current;
Camera_updateModelview( getCamera() ); Camera_updateModelview( getCamera() );
CamWnd_Update( *this ); CamWnd_Update( *this );
CameraMovedNotify(); CameraMovedNotify();
}
} }

View File

@ -1999,7 +1999,7 @@ GtkMenuItem* create_edit_menu(){
create_menu_item_with_mnemonic( menu, "Select Connected Entities", "SelectConnectedEntities" ); create_menu_item_with_mnemonic( menu, "Select Connected Entities", "SelectConnectedEntities" );
menu_separator( menu ); menu_separator( menu );
create_menu_item_with_mnemonic( menu, "Shortcuts...", FreeCaller<DoCommandListDlg>() ); create_menu_item_with_mnemonic( menu, "_Shortcuts...", FreeCaller<DoCommandListDlg>() );
create_menu_item_with_mnemonic( menu, "Pre_ferences...", "Preferences" ); create_menu_item_with_mnemonic( menu, "Pre_ferences...", "Preferences" );
return edit_menu_item; return edit_menu_item;