mirror of
https://github.com/TTimo/GtkRadiant.git
synced 2024-11-10 07:11:54 +00:00
Add smooth camera movement for non-discrete movement code path.
The camera key control routine now accumulates angular and positional velocity, and applies them per frame. There is also a friction component to reduce and then clear them over a few frames. This feels a lot closer to "noclip" movement, and allows mappers to navigate more precisely, which makes selecting brushes and faces in intricate areas much easier. YouTube preview of the movement here: https://www.youtube.com/watch?v=oiKwr3w0o5c
This commit is contained in:
parent
398e89f87f
commit
07a34e72a1
5 changed files with 147 additions and 43 deletions
|
@ -45,7 +45,7 @@ CCamera *firstCam = NULL; // double linked list
|
|||
CCamera *firstFreeCam = NULL; // single linked list
|
||||
CCamera *currentCam = NULL; // single item
|
||||
bool g_bEditOn = false;
|
||||
int g_iEditMode = 0; // 0: editting points 1: adding points
|
||||
int g_iEditMode = 0; // 0: editing points 1: adding points
|
||||
int g_iActiveTarget = -1;
|
||||
int g_iPreviewRunning = 0; // 0: no preview 1: start preview 2: preview in progress
|
||||
|
||||
|
|
|
@ -54,6 +54,10 @@ typedef enum
|
|||
#define MOVE_ROTLEFT 0x008
|
||||
#define MOVE_STRAFERIGHT 0x010
|
||||
#define MOVE_STRAFELEFT 0x020
|
||||
#define MOVE_UP 0x040
|
||||
#define MOVE_DOWN 0x080
|
||||
#define MOVE_ROTUP 0x100
|
||||
#define MOVE_ROTDOWN 0x200
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
|
|
@ -430,31 +430,75 @@ void CamWnd::Cam_MouseControl( float dtime ){
|
|||
}
|
||||
|
||||
void CamWnd::Cam_KeyControl( float dtime ) {
|
||||
static vec3_t avelocity;
|
||||
static vec3_t velocity;
|
||||
|
||||
// Update angles
|
||||
if ( m_Camera.movementflags & MOVE_ROTLEFT ) {
|
||||
m_Camera.angles[YAW] += 15 * dtime * g_PrefsDlg.m_nAngleSpeed;
|
||||
avelocity[YAW] += dtime * g_PrefsDlg.m_nAngleSpeed;
|
||||
}
|
||||
if ( m_Camera.movementflags & MOVE_ROTRIGHT ) {
|
||||
m_Camera.angles[YAW] -= 15 * dtime * g_PrefsDlg.m_nAngleSpeed;
|
||||
avelocity[YAW] -= dtime * g_PrefsDlg.m_nAngleSpeed;
|
||||
}
|
||||
if ( m_Camera.movementflags & MOVE_ROTUP ) {
|
||||
avelocity[PITCH] += dtime * g_PrefsDlg.m_nAngleSpeed;
|
||||
}
|
||||
if ( m_Camera.movementflags & MOVE_ROTDOWN ) {
|
||||
avelocity[PITCH] -= dtime * g_PrefsDlg.m_nAngleSpeed;
|
||||
}
|
||||
|
||||
// Update position
|
||||
// Now rotate the angles by the scaled velocity
|
||||
VectorMA( m_Camera.angles, dtime, avelocity, m_Camera.angles );
|
||||
|
||||
if ( m_Camera.angles[PITCH] > 90.f ) {
|
||||
m_Camera.angles[PITCH] = 90.f;
|
||||
} else if ( m_Camera.angles[PITCH] < -90.f) {
|
||||
m_Camera.angles[PITCH] = -90.f;
|
||||
}
|
||||
|
||||
// And then add some friction to slow us down
|
||||
VectorScale( avelocity, 1.f - dtime, avelocity );
|
||||
if ( VectorLength( avelocity ) < 1.f ) {
|
||||
VectorClear( avelocity );
|
||||
}
|
||||
|
||||
// Update velocity
|
||||
if ( m_Camera.movementflags & MOVE_FORWARD ) {
|
||||
VectorMA( m_Camera.origin, dtime * g_PrefsDlg.m_nMoveSpeed, m_Camera.forward, m_Camera.origin );
|
||||
VectorMA( velocity, dtime * g_PrefsDlg.m_nMoveSpeed, m_Camera.forward, velocity );
|
||||
}
|
||||
if ( m_Camera.movementflags & MOVE_BACK ) {
|
||||
VectorMA( m_Camera.origin, -dtime * g_PrefsDlg.m_nMoveSpeed, m_Camera.forward, m_Camera.origin );
|
||||
VectorMA( velocity, -dtime * g_PrefsDlg.m_nMoveSpeed, m_Camera.forward, velocity );
|
||||
}
|
||||
if ( m_Camera.movementflags & MOVE_STRAFELEFT ) {
|
||||
VectorMA( m_Camera.origin, -dtime * g_PrefsDlg.m_nMoveSpeed, m_Camera.right, m_Camera.origin );
|
||||
VectorMA( velocity, -dtime * g_PrefsDlg.m_nMoveSpeed, m_Camera.right, velocity );
|
||||
}
|
||||
if ( m_Camera.movementflags & MOVE_STRAFERIGHT ) {
|
||||
VectorMA( m_Camera.origin, dtime * g_PrefsDlg.m_nMoveSpeed, m_Camera.right, m_Camera.origin );
|
||||
VectorMA( velocity, dtime * g_PrefsDlg.m_nMoveSpeed, m_Camera.right, velocity );
|
||||
}
|
||||
if ( m_Camera.movementflags & MOVE_UP ) {
|
||||
VectorMA( velocity, dtime * g_PrefsDlg.m_nMoveSpeed, m_Camera.vup, velocity);
|
||||
}
|
||||
if ( m_Camera.movementflags & MOVE_DOWN ) {
|
||||
VectorMA( velocity, -dtime * g_PrefsDlg.m_nMoveSpeed, m_Camera.vup, velocity);
|
||||
}
|
||||
|
||||
// Save a screen update (when m_bFreeMove is enabled, mousecontrol does the update)
|
||||
if ( !m_bFreeMove && m_Camera.movementflags ) {
|
||||
// Now move the origin by the scaled velocity
|
||||
VectorMA( m_Camera.origin, dtime, velocity, m_Camera.origin);
|
||||
|
||||
// And then add some friction to slow us down
|
||||
VectorScale( velocity, 1.f - dtime, velocity );
|
||||
if ( VectorLength( velocity ) < 1.f ) {
|
||||
VectorClear( velocity );
|
||||
}
|
||||
|
||||
// Save a screen update
|
||||
if (!VectorCompare( vec3_origin, velocity ) || !VectorCompare( vec3_origin, avelocity ) ) {
|
||||
|
||||
// When m_bFreeMove is enabled, mousecontrol does the update
|
||||
if ( m_bFreeMove ) {
|
||||
return;
|
||||
}
|
||||
|
||||
int nUpdate = ( g_PrefsDlg.m_bCamXYUpdate ) ? ( W_CAMERA | W_XY ) : ( W_CAMERA );
|
||||
Sys_UpdateWindows( nUpdate );
|
||||
g_pParentWnd->OnTimer();
|
||||
|
|
|
@ -378,6 +378,10 @@ void HandleKeyUp( GtkWidget *widget, gpointer data ){
|
|||
case ID_CAMERA_RIGHT: g_pParentWnd->OnCameraRight( FALSE ); break;
|
||||
case ID_CAMERA_STRAFELEFT: g_pParentWnd->OnCameraStrafeleft( FALSE ); break;
|
||||
case ID_CAMERA_STRAFERIGHT: g_pParentWnd->OnCameraStraferight( FALSE ); break;
|
||||
case ID_CAMERA_UP: g_pParentWnd->OnCameraUp( FALSE ); break;
|
||||
case ID_CAMERA_DOWN: g_pParentWnd->OnCameraDown( FALSE ); break;
|
||||
case ID_CAMERA_ANGLEUP: g_pParentWnd->OnCameraAngleup( FALSE ); break;
|
||||
case ID_CAMERA_ANGLEDOWN: g_pParentWnd->OnCameraAngledown( FALSE ); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -695,10 +699,10 @@ gint HandleCommand( GtkWidget *widget, gpointer data ){
|
|||
case ID_CAMERA_BACK: g_pParentWnd->OnCameraBack( TRUE ); break;
|
||||
case ID_CAMERA_LEFT: g_pParentWnd->OnCameraLeft( TRUE ); break;
|
||||
case ID_CAMERA_RIGHT: g_pParentWnd->OnCameraRight( TRUE ); break;
|
||||
case ID_CAMERA_UP: g_pParentWnd->OnCameraUp(); break;
|
||||
case ID_CAMERA_DOWN: g_pParentWnd->OnCameraDown(); break;
|
||||
case ID_CAMERA_ANGLEUP: g_pParentWnd->OnCameraAngleup(); break;
|
||||
case ID_CAMERA_ANGLEDOWN: g_pParentWnd->OnCameraAngledown(); break;
|
||||
case ID_CAMERA_UP: g_pParentWnd->OnCameraUp( TRUE ); break;
|
||||
case ID_CAMERA_DOWN: g_pParentWnd->OnCameraDown( TRUE ); break;
|
||||
case ID_CAMERA_ANGLEUP: g_pParentWnd->OnCameraAngleup( TRUE ); break;
|
||||
case ID_CAMERA_ANGLEDOWN: g_pParentWnd->OnCameraAngledown( TRUE ); break;
|
||||
case ID_CAMERA_STRAFELEFT: g_pParentWnd->OnCameraStrafeleft( TRUE ); break;
|
||||
case ID_CAMERA_STRAFERIGHT: g_pParentWnd->OnCameraStraferight( TRUE ); break;
|
||||
case ID_GRID_TOGGLE: g_pParentWnd->OnGridToggle(); break;
|
||||
|
@ -832,9 +836,9 @@ static gint mainframe_keypress( GtkWidget* widget, GdkEventKey* event, gpointer
|
|||
static gint mainframe_keyrelease( GtkWidget* widget, GdkEventKey* event, gpointer data ){
|
||||
unsigned int code = gdk_keyval_to_upper( event->keyval );
|
||||
|
||||
if ( gtk_accelerator_valid( event->keyval, (GdkModifierType)0 ) ) {
|
||||
return TRUE;
|
||||
}
|
||||
// if ( gtk_accelerator_valid( event->keyval, (GdkModifierType)0 ) ) {
|
||||
// return TRUE;
|
||||
// }
|
||||
|
||||
for ( int i = 0; i < g_nCommandCount; i++ )
|
||||
{
|
||||
|
@ -849,6 +853,10 @@ static gint mainframe_keyrelease( GtkWidget* widget, GdkEventKey* event, gpointe
|
|||
case ID_CAMERA_RIGHT:
|
||||
case ID_CAMERA_STRAFELEFT:
|
||||
case ID_CAMERA_STRAFERIGHT:
|
||||
case ID_CAMERA_UP:
|
||||
case ID_CAMERA_DOWN:
|
||||
case ID_CAMERA_ANGLEUP:
|
||||
case ID_CAMERA_ANGLEDOWN:
|
||||
{
|
||||
HandleKeyUp( NULL, GINT_TO_POINTER( g_Commands[i].m_nCommand ) );
|
||||
g_signal_stop_emission_by_name( G_OBJECT( widget ), "key-release-event" );
|
||||
|
@ -7253,32 +7261,80 @@ void MainFrame::OnCameraRight( bool keydown ){
|
|||
}
|
||||
}
|
||||
|
||||
void MainFrame::OnCameraUp(){
|
||||
m_pCamWnd->Camera()->origin[2] += SPEED_MOVE;
|
||||
int nUpdate = ( g_PrefsDlg.m_bCamXYUpdate ) ? ( W_CAMERA | W_XY | W_Z ) : ( W_CAMERA );
|
||||
Sys_UpdateWindows( nUpdate );
|
||||
}
|
||||
|
||||
void MainFrame::OnCameraDown(){
|
||||
m_pCamWnd->Camera()->origin[2] -= SPEED_MOVE;
|
||||
int nUpdate = ( g_PrefsDlg.m_bCamXYUpdate ) ? ( W_CAMERA | W_XY | W_Z ) : ( W_CAMERA );
|
||||
Sys_UpdateWindows( nUpdate );
|
||||
}
|
||||
|
||||
void MainFrame::OnCameraAngleup(){
|
||||
m_pCamWnd->Camera()->angles[0] += SPEED_TURN;
|
||||
if ( m_pCamWnd->Camera()->angles[0] > 85 ) {
|
||||
m_pCamWnd->Camera()->angles[0] = 85;
|
||||
void MainFrame::OnCameraUp( bool keydown ){
|
||||
if ( g_PrefsDlg.m_bCamDiscrete ) {
|
||||
if ( keydown ) {
|
||||
m_pCamWnd->Camera()->origin[2] += SPEED_MOVE;
|
||||
int nUpdate = ( g_PrefsDlg.m_bCamXYUpdate ) ? ( W_CAMERA | W_XY ) : ( W_CAMERA );
|
||||
Sys_UpdateWindows( nUpdate );
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( keydown ) {
|
||||
m_pCamWnd->Camera()->movementflags |= MOVE_UP;
|
||||
}
|
||||
else{
|
||||
m_pCamWnd->Camera()->movementflags &= ~MOVE_UP;
|
||||
}
|
||||
}
|
||||
Sys_UpdateWindows( W_CAMERA | W_XY_OVERLAY );
|
||||
}
|
||||
|
||||
void MainFrame::OnCameraAngledown(){
|
||||
m_pCamWnd->Camera()->angles[0] -= SPEED_TURN;
|
||||
if ( m_pCamWnd->Camera()->angles[0] < -85 ) {
|
||||
m_pCamWnd->Camera()->angles[0] = -85;
|
||||
void MainFrame::OnCameraDown( bool keydown ){
|
||||
if ( g_PrefsDlg.m_bCamDiscrete ) {
|
||||
if ( keydown ) {
|
||||
m_pCamWnd->Camera()->origin[2] -= SPEED_MOVE;
|
||||
int nUpdate = ( g_PrefsDlg.m_bCamXYUpdate ) ? ( W_CAMERA | W_XY ) : ( W_CAMERA );
|
||||
Sys_UpdateWindows( nUpdate );
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( keydown ) {
|
||||
m_pCamWnd->Camera()->movementflags |= MOVE_DOWN;
|
||||
}
|
||||
else{
|
||||
m_pCamWnd->Camera()->movementflags &= ~MOVE_DOWN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainFrame::OnCameraAngleup( bool keydown ){
|
||||
if ( g_PrefsDlg.m_bCamDiscrete ) {
|
||||
if ( keydown ) {
|
||||
m_pCamWnd->Camera()->angles[PITCH] += SPEED_TURN;
|
||||
if ( m_pCamWnd->Camera()->angles[PITCH] > 85 ) {
|
||||
m_pCamWnd->Camera()->angles[PITCH] = 85;
|
||||
}
|
||||
Sys_UpdateWindows( W_CAMERA | W_XY_OVERLAY );
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( keydown ) {
|
||||
m_pCamWnd->Camera()->movementflags |= MOVE_ROTUP;
|
||||
}
|
||||
else{
|
||||
m_pCamWnd->Camera()->movementflags &= ~MOVE_ROTUP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainFrame::OnCameraAngledown( bool keydown ){
|
||||
if ( g_PrefsDlg.m_bCamDiscrete ) {
|
||||
if ( keydown ) {
|
||||
m_pCamWnd->Camera()->angles[PITCH] -= SPEED_TURN;
|
||||
if ( m_pCamWnd->Camera()->angles[PITCH] < -85 ) {
|
||||
m_pCamWnd->Camera()->angles[PITCH] = -85;
|
||||
}
|
||||
Sys_UpdateWindows( W_CAMERA | W_XY_OVERLAY );
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( keydown ) {
|
||||
m_pCamWnd->Camera()->movementflags |= MOVE_ROTDOWN;
|
||||
}
|
||||
else{
|
||||
m_pCamWnd->Camera()->movementflags &= ~MOVE_ROTDOWN;
|
||||
}
|
||||
}
|
||||
Sys_UpdateWindows( W_CAMERA | W_XY_OVERLAY );
|
||||
}
|
||||
|
||||
void MainFrame::OnCameraStrafeleft( bool keydown ){
|
||||
|
|
|
@ -703,16 +703,16 @@ void OnHelpLinks();
|
|||
void OnHelpBugreport();
|
||||
void OnViewClipper();
|
||||
void OnToggleDetail();
|
||||
void OnCameraAngledown();
|
||||
void OnCameraAngleup();
|
||||
void OnCameraAngledown( bool keydown );
|
||||
void OnCameraAngleup( bool keydown );
|
||||
void OnCameraBack( bool keydown );
|
||||
void OnCameraDown();
|
||||
void OnCameraDown( bool keydown );
|
||||
void OnCameraForward( bool keydown );
|
||||
void OnCameraLeft( bool keydown );
|
||||
void OnCameraRight( bool keydown );
|
||||
void OnCameraStrafeleft( bool keydown );
|
||||
void OnCameraStraferight( bool keydown );
|
||||
void OnCameraUp();
|
||||
void OnCameraUp( bool keydown );
|
||||
void OnGridToggle();
|
||||
void OnPrefs();
|
||||
void OnTogglecamera();
|
||||
|
|
Loading…
Reference in a new issue