mirror of
https://github.com/TTimo/GtkRadiant.git
synced 2025-02-12 07:14:11 +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 *firstFreeCam = NULL; // single linked list
|
||||||
CCamera *currentCam = NULL; // single item
|
CCamera *currentCam = NULL; // single item
|
||||||
bool g_bEditOn = false;
|
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_iActiveTarget = -1;
|
||||||
int g_iPreviewRunning = 0; // 0: no preview 1: start preview 2: preview in progress
|
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_ROTLEFT 0x008
|
||||||
#define MOVE_STRAFERIGHT 0x010
|
#define MOVE_STRAFERIGHT 0x010
|
||||||
#define MOVE_STRAFELEFT 0x020
|
#define MOVE_STRAFELEFT 0x020
|
||||||
|
#define MOVE_UP 0x040
|
||||||
|
#define MOVE_DOWN 0x080
|
||||||
|
#define MOVE_ROTUP 0x100
|
||||||
|
#define MOVE_ROTDOWN 0x200
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
|
|
@ -430,31 +430,75 @@ void CamWnd::Cam_MouseControl( float dtime ){
|
||||||
}
|
}
|
||||||
|
|
||||||
void CamWnd::Cam_KeyControl( float dtime ) {
|
void CamWnd::Cam_KeyControl( float dtime ) {
|
||||||
|
static vec3_t avelocity;
|
||||||
|
static vec3_t velocity;
|
||||||
|
|
||||||
// Update angles
|
// Update angles
|
||||||
if ( m_Camera.movementflags & MOVE_ROTLEFT ) {
|
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 ) {
|
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 ) {
|
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 ) {
|
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 ) {
|
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 ) {
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save a screen update (when m_bFreeMove is enabled, mousecontrol does the update)
|
|
||||||
if ( !m_bFreeMove && m_Camera.movementflags ) {
|
|
||||||
int nUpdate = ( g_PrefsDlg.m_bCamXYUpdate ) ? ( W_CAMERA | W_XY ) : ( W_CAMERA );
|
int nUpdate = ( g_PrefsDlg.m_bCamXYUpdate ) ? ( W_CAMERA | W_XY ) : ( W_CAMERA );
|
||||||
Sys_UpdateWindows( nUpdate );
|
Sys_UpdateWindows( nUpdate );
|
||||||
g_pParentWnd->OnTimer();
|
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_RIGHT: g_pParentWnd->OnCameraRight( FALSE ); break;
|
||||||
case ID_CAMERA_STRAFELEFT: g_pParentWnd->OnCameraStrafeleft( FALSE ); break;
|
case ID_CAMERA_STRAFELEFT: g_pParentWnd->OnCameraStrafeleft( FALSE ); break;
|
||||||
case ID_CAMERA_STRAFERIGHT: g_pParentWnd->OnCameraStraferight( 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_BACK: g_pParentWnd->OnCameraBack( TRUE ); break;
|
||||||
case ID_CAMERA_LEFT: g_pParentWnd->OnCameraLeft( TRUE ); break;
|
case ID_CAMERA_LEFT: g_pParentWnd->OnCameraLeft( TRUE ); break;
|
||||||
case ID_CAMERA_RIGHT: g_pParentWnd->OnCameraRight( TRUE ); break;
|
case ID_CAMERA_RIGHT: g_pParentWnd->OnCameraRight( TRUE ); break;
|
||||||
case ID_CAMERA_UP: g_pParentWnd->OnCameraUp(); break;
|
case ID_CAMERA_UP: g_pParentWnd->OnCameraUp( TRUE ); break;
|
||||||
case ID_CAMERA_DOWN: g_pParentWnd->OnCameraDown(); break;
|
case ID_CAMERA_DOWN: g_pParentWnd->OnCameraDown( TRUE ); break;
|
||||||
case ID_CAMERA_ANGLEUP: g_pParentWnd->OnCameraAngleup(); break;
|
case ID_CAMERA_ANGLEUP: g_pParentWnd->OnCameraAngleup( TRUE ); break;
|
||||||
case ID_CAMERA_ANGLEDOWN: g_pParentWnd->OnCameraAngledown(); break;
|
case ID_CAMERA_ANGLEDOWN: g_pParentWnd->OnCameraAngledown( TRUE ); break;
|
||||||
case ID_CAMERA_STRAFELEFT: g_pParentWnd->OnCameraStrafeleft( TRUE ); break;
|
case ID_CAMERA_STRAFELEFT: g_pParentWnd->OnCameraStrafeleft( TRUE ); break;
|
||||||
case ID_CAMERA_STRAFERIGHT: g_pParentWnd->OnCameraStraferight( TRUE ); break;
|
case ID_CAMERA_STRAFERIGHT: g_pParentWnd->OnCameraStraferight( TRUE ); break;
|
||||||
case ID_GRID_TOGGLE: g_pParentWnd->OnGridToggle(); 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 ){
|
static gint mainframe_keyrelease( GtkWidget* widget, GdkEventKey* event, gpointer data ){
|
||||||
unsigned int code = gdk_keyval_to_upper( event->keyval );
|
unsigned int code = gdk_keyval_to_upper( event->keyval );
|
||||||
|
|
||||||
if ( gtk_accelerator_valid( event->keyval, (GdkModifierType)0 ) ) {
|
// if ( gtk_accelerator_valid( event->keyval, (GdkModifierType)0 ) ) {
|
||||||
return TRUE;
|
// return TRUE;
|
||||||
}
|
// }
|
||||||
|
|
||||||
for ( int i = 0; i < g_nCommandCount; i++ )
|
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_RIGHT:
|
||||||
case ID_CAMERA_STRAFELEFT:
|
case ID_CAMERA_STRAFELEFT:
|
||||||
case ID_CAMERA_STRAFERIGHT:
|
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 ) );
|
HandleKeyUp( NULL, GINT_TO_POINTER( g_Commands[i].m_nCommand ) );
|
||||||
g_signal_stop_emission_by_name( G_OBJECT( widget ), "key-release-event" );
|
g_signal_stop_emission_by_name( G_OBJECT( widget ), "key-release-event" );
|
||||||
|
@ -7253,32 +7261,80 @@ void MainFrame::OnCameraRight( bool keydown ){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainFrame::OnCameraUp(){
|
void MainFrame::OnCameraUp( bool keydown ){
|
||||||
|
if ( g_PrefsDlg.m_bCamDiscrete ) {
|
||||||
|
if ( keydown ) {
|
||||||
m_pCamWnd->Camera()->origin[2] += SPEED_MOVE;
|
m_pCamWnd->Camera()->origin[2] += SPEED_MOVE;
|
||||||
int nUpdate = ( g_PrefsDlg.m_bCamXYUpdate ) ? ( W_CAMERA | W_XY | W_Z ) : ( W_CAMERA );
|
int nUpdate = ( g_PrefsDlg.m_bCamXYUpdate ) ? ( W_CAMERA | W_XY ) : ( W_CAMERA );
|
||||||
Sys_UpdateWindows( nUpdate );
|
Sys_UpdateWindows( nUpdate );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ( keydown ) {
|
||||||
|
m_pCamWnd->Camera()->movementflags |= MOVE_UP;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
m_pCamWnd->Camera()->movementflags &= ~MOVE_UP;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainFrame::OnCameraDown(){
|
void MainFrame::OnCameraDown( bool keydown ){
|
||||||
|
if ( g_PrefsDlg.m_bCamDiscrete ) {
|
||||||
|
if ( keydown ) {
|
||||||
m_pCamWnd->Camera()->origin[2] -= SPEED_MOVE;
|
m_pCamWnd->Camera()->origin[2] -= SPEED_MOVE;
|
||||||
int nUpdate = ( g_PrefsDlg.m_bCamXYUpdate ) ? ( W_CAMERA | W_XY | W_Z ) : ( W_CAMERA );
|
int nUpdate = ( g_PrefsDlg.m_bCamXYUpdate ) ? ( W_CAMERA | W_XY ) : ( W_CAMERA );
|
||||||
Sys_UpdateWindows( nUpdate );
|
Sys_UpdateWindows( nUpdate );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ( keydown ) {
|
||||||
|
m_pCamWnd->Camera()->movementflags |= MOVE_DOWN;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
m_pCamWnd->Camera()->movementflags &= ~MOVE_DOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainFrame::OnCameraAngleup(){
|
void MainFrame::OnCameraAngleup( bool keydown ){
|
||||||
m_pCamWnd->Camera()->angles[0] += SPEED_TURN;
|
if ( g_PrefsDlg.m_bCamDiscrete ) {
|
||||||
if ( m_pCamWnd->Camera()->angles[0] > 85 ) {
|
if ( keydown ) {
|
||||||
m_pCamWnd->Camera()->angles[0] = 85;
|
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 );
|
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(){
|
void MainFrame::OnCameraAngledown( bool keydown ){
|
||||||
m_pCamWnd->Camera()->angles[0] -= SPEED_TURN;
|
if ( g_PrefsDlg.m_bCamDiscrete ) {
|
||||||
if ( m_pCamWnd->Camera()->angles[0] < -85 ) {
|
if ( keydown ) {
|
||||||
m_pCamWnd->Camera()->angles[0] = -85;
|
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 );
|
Sys_UpdateWindows( W_CAMERA | W_XY_OVERLAY );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ( keydown ) {
|
||||||
|
m_pCamWnd->Camera()->movementflags |= MOVE_ROTDOWN;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
m_pCamWnd->Camera()->movementflags &= ~MOVE_ROTDOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainFrame::OnCameraStrafeleft( bool keydown ){
|
void MainFrame::OnCameraStrafeleft( bool keydown ){
|
||||||
|
|
|
@ -703,16 +703,16 @@ void OnHelpLinks();
|
||||||
void OnHelpBugreport();
|
void OnHelpBugreport();
|
||||||
void OnViewClipper();
|
void OnViewClipper();
|
||||||
void OnToggleDetail();
|
void OnToggleDetail();
|
||||||
void OnCameraAngledown();
|
void OnCameraAngledown( bool keydown );
|
||||||
void OnCameraAngleup();
|
void OnCameraAngleup( bool keydown );
|
||||||
void OnCameraBack( bool keydown );
|
void OnCameraBack( bool keydown );
|
||||||
void OnCameraDown();
|
void OnCameraDown( bool keydown );
|
||||||
void OnCameraForward( bool keydown );
|
void OnCameraForward( bool keydown );
|
||||||
void OnCameraLeft( bool keydown );
|
void OnCameraLeft( bool keydown );
|
||||||
void OnCameraRight( bool keydown );
|
void OnCameraRight( bool keydown );
|
||||||
void OnCameraStrafeleft( bool keydown );
|
void OnCameraStrafeleft( bool keydown );
|
||||||
void OnCameraStraferight( bool keydown );
|
void OnCameraStraferight( bool keydown );
|
||||||
void OnCameraUp();
|
void OnCameraUp( bool keydown );
|
||||||
void OnGridToggle();
|
void OnGridToggle();
|
||||||
void OnPrefs();
|
void OnPrefs();
|
||||||
void OnTogglecamera();
|
void OnTogglecamera();
|
||||||
|
|
Loading…
Reference in a new issue