diff --git a/engine/client/cl_input.c b/engine/client/cl_input.c index 82dcbf470..a658fe380 100644 --- a/engine/client/cl_input.c +++ b/engine/client/cl_input.c @@ -2264,6 +2264,8 @@ void CL_SendCmd (double frametime, qboolean mainloop) CL_FinishMove(cmd, plnum); + VectorCopy(pv->aimangles, pv->simangles); + Cam_FinishMove(pv, cmd); #ifdef CSQC_DAT diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index e904fe00f..3cd814cd2 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -71,6 +71,7 @@ cvar_t cl_nolerp = CVARD("cl_nolerp", "0", "Disables interpolation. If set, miss cvar_t cl_nolerp_netquake = CVARD("cl_nolerp_netquake", "0", "Disables interpolation when connected to an NQ server. Does affect players, even the local player. You probably don't want to set this."); cvar_t cl_fullpitch_nq = CVARAFD("cl_fullpitch", "0", "pq_fullpitch", CVAR_SEMICHEAT, "When set, attempts to unlimit the default view pitch. Note that some servers will screw over your angles if you use this, resulting in terrible gameplay, while some may merely clamp your angle serverside. This is also considered a cheat in quakeworld, ^1so this will not function there^7. For the equivelent in quakeworld, use serverinfo minpitch+maxpitch instead, which applies to all players fairly."); #endif +static cvar_t cl_forcevrui = CVARD("cl_forcevrui", "0", "Force the use of VR UIs, even with no VR headset active."); cvar_t *hud_tracking_show; cvar_t *hud_miniscores_show; extern cvar_t net_compress; @@ -4921,6 +4922,7 @@ void CL_Init (void) Cvar_Register (&cl_idlefps, cl_screengroup); Cvar_Register (&cl_yieldcpu, cl_screengroup); Cvar_Register (&cl_timeout, cl_controlgroup); + Cvar_Register (&cl_forcevrui, cl_controlgroup); Cvar_Register (&lookspring, cl_inputgroup); Cvar_Register (&lookstrafe, cl_inputgroup); Cvar_Register (&sensitivity, cl_inputgroup); @@ -6471,6 +6473,7 @@ double Host_Frame (double time) { RSpeedMark(); vid.ime_allow = false; + vrui.enabled = cl_forcevrui.ival; if (SCR_UpdateScreen()) fps_count++; if (R2D_Flush) diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index d6c5e1f00..f8b9662cd 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -7004,6 +7004,9 @@ static void CL_ParseBaseAngle(int seat) VectorCopy (newang, cl.playerview[seat].viewangles); } VectorCopy (newang, cl.playerview[seat].intermissionangles); + + if (fl & 8) + VRUI_SnapAngle(); } #define SHOWNET(x) if(cl_shownet.value>=2)Con_Printf ("%3i:%s\n", msg_readcount-1, x); @@ -8491,6 +8494,7 @@ void CLNQ_ParseServerMessage (void) VectorCopy (ang, inf->packet_entities.fixedangles[destsplit]); } VectorCopy (cl.playerview[destsplit].viewangles, cl.playerview[destsplit].intermissionangles); + VRUI_SnapAngle(); } break; diff --git a/engine/client/cl_screen.c b/engine/client/cl_screen.c index 75be43959..a381e17ff 100644 --- a/engine/client/cl_screen.c +++ b/engine/client/cl_screen.c @@ -576,6 +576,7 @@ void SCR_CenterPrint (int pnum, const char *str, qboolean skipgamecode) p->time_off = scr_centertime.value; p->time_start = cl.time; + VRUI_SnapAngle(); } void VARGS Stats_Message(char *msg, ...) @@ -996,6 +997,9 @@ void SCR_DrawCursor(void) } } + if (vrui.enabled && kcurs->handle) + kcurs->dirty = true; + if (kcurs->dirty) { if (kcurs->scale <= 0 || !*kcurs->name) @@ -1007,7 +1011,7 @@ void SCR_DrawCursor(void) kcurs->dirty = false; oldcurs = kcurs->handle; - if (rf->VID_CreateCursor && strcmp(kcurs->name, "none")) + if (rf->VID_CreateCursor && !vrui.enabled && strcmp(kcurs->name, "none")) { image_t dummytex; flocation_t loc; @@ -2374,7 +2378,10 @@ void SCR_DrawConsole (qboolean noback) if (!Key_Dest_Has(kdm_console|kdm_menu)) Con_DrawNotify (); // only draw notify in game } - Con_DrawConsole (scr_con_current, noback); + if (vrui.enabled) //make the console all-or-nothing when its a vr ui. + Con_DrawConsole (scr_con_target?vid.height:0, noback); + else + Con_DrawConsole (scr_con_current, noback); if (scr_con_current || Key_Dest_Has(kdm_cwindows)) clearconsole = 0; } @@ -3291,8 +3298,6 @@ void SCR_DrawTwoDimensional(qboolean nohud) qboolean consolefocused = !!Key_Dest_Has(kdm_console|kdm_cwindows); RSpeedMark(); - r_refdef.playerview = &cl.playerview[0]; - R2D_ImageColours(1, 1, 1, 1); // diff --git a/engine/client/console.c b/engine/client/console.c index 3190d0309..91b91c58a 100644 --- a/engine/client/console.c +++ b/engine/client/console.c @@ -637,6 +637,7 @@ void Con_ToggleConsole_Force(void) { con_curwindow = con; Key_Dest_Add(kdm_cwindows); + VRUI_SnapAngle(); } } else @@ -644,7 +645,10 @@ void Con_ToggleConsole_Force(void) if (Key_Dest_Has(kdm_console)) Key_Dest_Remove(kdm_console); else + { Key_Dest_Add(kdm_console); + VRUI_SnapAngle(); + } } } void Con_ToggleConsole_f (void) @@ -983,6 +987,8 @@ void Con_PrintCon (console_t *con, const char *txt, unsigned int parseflags) con->current->flags |= CONL_CENTERED; if (parseflags & PFS_NONOTIFY) con->current->flags |= CONL_NONOTIFY; + else if (!Key_Dest_Has(~kdm_game) && (con->flags & CONF_NOTIFY)) + VRUI_SnapAngle(); #if defined(HAVE_SPEECHTOTEXT) if (con->current) @@ -2906,12 +2912,15 @@ static void Con_DrawMouseOver(console_t *mouseconsole) } else shader = NULL; - key = Info_ValueForKey(info, "modelviewer"); - if (*key) + if (!vrui.enabled) { - model = Mod_ForName(key, MLV_WARN); - if (model->loadstate != MLS_LOADED) - model = NULL; + key = Info_ValueForKey(info, "modelviewer"); + if (*key) + { + model = Mod_ForName(key, MLV_WARN); + if (model->loadstate != MLS_LOADED) + model = NULL; + } } key = Info_ValueForKey(info, "playaudio"); diff --git a/engine/client/in_generic.c b/engine/client/in_generic.c index 841d5ddf8..72b5e4cdc 100644 --- a/engine/client/in_generic.c +++ b/engine/client/in_generic.c @@ -492,7 +492,7 @@ void IN_Commands(void) ptr[ev->devid].delta[1] += ev->mouse.y; //if we're emulating a cursor, make sure that's updated too. - if (touchcursor < 0 && Key_MouseShouldBeFree()) + if (touchcursor < 0 && !vrui.enabled && Key_MouseShouldBeFree()) { mousecursor_x += ev->mouse.x; mousecursor_y += ev->mouse.y; @@ -521,6 +521,7 @@ void IN_Commands(void) case IEV_MOUSEABS: //Con_Printf("IEV_MOUSEABS %i: %f %f\n", ev->devid, ev->mouse.x, ev->mouse.y); /*mouse cursors only really work with one pointer*/ + if (!vrui.enabled) if (ev->devid == touchcursor || (touchcursor < 0 && ev->devid < MAXPOINTERS && (ptr[ev->devid].oldpos[0] != ev->mouse.x || ptr[ev->devid].oldpos[1] != ev->mouse.y))) { float fl; @@ -657,7 +658,7 @@ void IN_MoveMouse(struct mouse_s *mouse, float *movements, int pnum, float frame mousemove_x += mx; mousemove_y += my; - if (Key_MouseShouldBeFree()) + if (!vrui.enabled && Key_MouseShouldBeFree()) mx=my=0; if (mouse->type == M_TOUCH) diff --git a/engine/client/in_win.c b/engine/client/in_win.c index 11c2a27d2..04e38c25f 100644 --- a/engine/client/in_win.c +++ b/engine/client/in_win.c @@ -709,7 +709,7 @@ void INS_UpdateGrabs(int fullscreen, int activeapp) grabmouse = false; else if (fullscreen || in_simulatemultitouch.ival || in_windowed_mouse.value) { - if (!Key_MouseShouldBeFree()) + if (vrui.enabled || !Key_MouseShouldBeFree()) grabmouse = true; else grabmouse = false; diff --git a/engine/client/keys.c b/engine/client/keys.c index 8e9707818..71ecc3f55 100644 --- a/engine/client/keys.c +++ b/engine/client/keys.c @@ -1868,6 +1868,15 @@ qboolean Key_Console (console_t *con, int key, unsigned int unicode) return true; } + if (key == K_GP_BACK) + { + Key_Dest_Remove(kdm_console); + Key_Dest_Remove(kdm_cwindows); + if (!cls.state && !Key_Dest_Has(~kdm_game)) + M_ToggleMenu_f (); + return true; + } + if ((key == K_MOUSE1 || key == K_MOUSE2)) { int olddown[2] = {con->mousedown[0],con->mousedown[1]}; diff --git a/engine/client/m_items.c b/engine/client/m_items.c index d0be7a727..5a25bef45 100644 --- a/engine/client/m_items.c +++ b/engine/client/m_items.c @@ -408,6 +408,12 @@ static qboolean M_MouseMoved(emenu_t *menu) if (menu->mouseitem != option) { menu->mouseitem = option; + if (vrui.enabled) + { + menu->selecteditem = option; + if (menu->cursoritem) + menu->cursoritem->common.posy = menu->selecteditem->common.posy; + } menu->tooltiptime = realtime + 1; MenuTooltipChange(menu, menu->mouseitem->common.tooltip); } @@ -1774,7 +1780,7 @@ static void M_Draw (menu_t *menu) menu_mousedown = false; return; } - if ((!menu_script || scr_con_current)) + if (!vrui.enabled && (!menu_script || scr_con_current)) { if (m->nobacktint || (m->selecteditem && m->selecteditem->common.type == mt_slider && (m->selecteditem->slider.var == &v_gamma || m->selecteditem->slider.var == &v_contrast))) /*no menu tint if we're trying to adjust gamma*/; diff --git a/engine/client/m_options.c b/engine/client/m_options.c index ff476529e..63083f61d 100644 --- a/engine/client/m_options.c +++ b/engine/client/m_options.c @@ -4340,7 +4340,7 @@ static void Mods_Draw(int x, int y, struct menucustom_s *c, struct emenu_s *m) static qboolean Mods_Key(struct menucustom_s *c, struct emenu_s *m, int key, unsigned int unicode) { int gameidx = c->dint; - if (key == K_MOUSE1 || key == K_ENTER || key == K_GP_A) + if (key == K_MOUSE1 || key == K_ENTER || key == K_GP_A || key == K_GP_START) { qboolean wasgameless = !*FS_GetGamedir(false); if (!Mods_GetMod(c->dint)) diff --git a/engine/client/menu.c b/engine/client/menu.c index ea3cebd71..cdddf4b19 100644 --- a/engine/client/menu.c +++ b/engine/client/menu.c @@ -120,11 +120,15 @@ void Menu_Push(menu_t *menu, qboolean prompt) } if (menu == promptmenu) { + if (!Key_Dest_Has(kdm_prompt)) + VRUI_SnapAngle(); Key_Dest_Add(kdm_prompt); Menu_UpdateFocus(); } if (menu == topmenu) { + if (!Key_Dest_Has(kdm_menu)) + VRUI_SnapAngle(); Key_Dest_Add(kdm_menu); Menu_UpdateFocus(); } diff --git a/engine/client/screen.h b/engine/client/screen.h index d0a3094a4..cb9ad4f2d 100644 --- a/engine/client/screen.h +++ b/engine/client/screen.h @@ -35,6 +35,14 @@ extern cvar_t scr_viewsize; qboolean SCR_RSShot (void); +typedef struct +{ + qboolean enabled; + vec3_t angles; +} vrui_t; +extern vrui_t vrui; +void VRUI_SnapAngle(void); + //void SCR_DrawConsole (qboolean noback); //void SCR_SetUpToDrawConsole (void); diff --git a/engine/client/view.c b/engine/client/view.c index 07d5792d0..263cda9ee 100644 --- a/engine/client/view.c +++ b/engine/client/view.c @@ -2464,18 +2464,20 @@ void V_RenderView (qboolean no2d) Surf_LessenStains(); - if (cls.state != ca_active) - return; +// if (cls.state != ca_active) +// return; if (cl.intermissionmode != IM_NONE) maxseats = 1; else if (cl_forceseat.ival && cl_splitscreen.ival >= 4) maxseats = 1; + else + maxseats = max(1, cl.splitclients); R_PushDlights (); r_secondaryview = 0; - for (seatnum = 0; seatnum < cl.splitclients && seatnum < maxseats; seatnum++) + for (seatnum = 0; seatnum < maxseats; seatnum++) { pl = (maxseats==1&&cl_forceseat.ival>=1)?(cl_forceseat.ival-1)%cl.splitclients:seatnum; V_ClearRefdef(&cl.playerview[pl]); @@ -2512,18 +2514,21 @@ void V_RenderView (qboolean no2d) SCR_VRectForPlayer(&r_refdef.grect, seatnum, maxseats); V_RenderPlayerViews(r_refdef.playerview); -#ifdef PLUGINS - Plug_SBar (r_refdef.playerview); -#else - if (Sbar_ShouldDraw(r_refdef.playerview)) + if (!vrui.enabled) { - SCR_TileClear (sb_lines); - Sbar_Draw (r_refdef.playerview); - Sbar_DrawScoreboard (r_refdef.playerview); - } - else - SCR_TileClear (0); +#ifdef PLUGINS + Plug_SBar (r_refdef.playerview); +#else + if (Sbar_ShouldDraw(r_refdef.playerview)) + { + SCR_TileClear (sb_lines); + Sbar_Draw (r_refdef.playerview); + Sbar_DrawScoreboard (r_refdef.playerview); + } + else + SCR_TileClear (0); #endif + } } if (seatnum > 1) { diff --git a/engine/gl/gl_alias.c b/engine/gl/gl_alias.c index c238ccd55..f76ac2226 100644 --- a/engine/gl/gl_alias.c +++ b/engine/gl/gl_alias.c @@ -2954,6 +2954,8 @@ void BE_GenModelBatches(batch_t **batches, const dlight_t *dl, unsigned int bemo case mod_brush: if (r_drawentities.ival == 2 && cls.allow_cheats) //2 is considered a cheat, because it can be used as a wallhack (whereas mdls are not normally considered as occluding). continue; + if (emodel->lightmaps.maxstyle >= cl_max_lightstyles) + continue; Surf_GenBrushBatches(batches, ent); break; case mod_alias: diff --git a/engine/gl/gl_rmain.c b/engine/gl/gl_rmain.c index f00b06be0..87f1858c7 100644 --- a/engine/gl/gl_rmain.c +++ b/engine/gl/gl_rmain.c @@ -715,6 +715,75 @@ static void R_RenderScene_Internal(void) cl_numvisedicts = tmpvisents; depthcleared = false; //whatever is in the depth buffer is no longer useful. + + if (vrui.enabled) + { + vec3_t uifwd, uiright, uiup; + vec3_t diff; + float d; + vec3_t ctrlang, ctrlorg, aimdir; + +// extern usercmd_t cl_pendingcmd[MAX_SPLITS]; + AngleVectors(vrui.angles, uifwd, uiright, uiup); + + VectorAngles(uiright, uifwd, r_worldentity.angles, false); + AngleVectors(r_worldentity.angles, r_worldentity.axis[0], r_worldentity.axis[1], r_worldentity.axis[2]); + VectorNegate(r_worldentity.axis[1], r_worldentity.axis[1]); + r_worldentity.scale = 1;//0.2; + VectorMA(r_refdef.vieworg, Cvar_Get("2dz", "256", 0, "")->value*r_worldentity.scale, r_worldentity.axis[2], r_worldentity.origin); + VectorMA(r_worldentity.origin, -(int)(vid.width/2)*r_worldentity.scale, r_worldentity.axis[0], r_worldentity.origin); + VectorMA(r_worldentity.origin, -(int)(vid.height/2)*r_worldentity.scale, r_worldentity.axis[1], r_worldentity.origin); + GL_SetShaderState2D(true); + + VectorCopy(r_refdef.viewangles, ctrlang); + if (r_refdef.playerview->vrdev[VRDEV_RIGHT].status&VRSTATUS_ANG) + { + ctrlang[0] = SHORT2ANGLE(r_refdef.playerview->vrdev[VRDEV_RIGHT].angles[0]); + ctrlang[1] = SHORT2ANGLE(r_refdef.playerview->vrdev[VRDEV_RIGHT].angles[1]); + ctrlang[2] = SHORT2ANGLE(r_refdef.playerview->vrdev[VRDEV_RIGHT].angles[2]); + } + else + VectorCopy(r_refdef.viewangles, ctrlang); + if (r_refdef.playerview->vrdev[VRDEV_RIGHT].status&VRSTATUS_ORG) + VectorCopy(r_refdef.playerview->vrdev[VRDEV_RIGHT].origin, ctrlorg); + else + VectorCopy(r_refdef.vieworg, ctrlorg); + + AngleVectors(ctrlang, aimdir, NULL, NULL); + VectorSubtract(r_worldentity.origin, ctrlorg, diff); + //d = DotProduct(diff, vpn); //figure out how far we need to move it to get an impact. + d = DotProduct(diff, r_worldentity.axis[2]); + d /= DotProduct(aimdir, r_worldentity.axis[2]); //compensate for the length. + VectorMA(ctrlorg, d, aimdir, diff); //calc the impact point... + VectorSubtract(diff, r_worldentity.origin, diff); + mousecursor_x = DotProduct(diff, r_worldentity.axis[0]); + mousecursor_y = DotProduct(diff, r_worldentity.axis[1]); + mousecursor_x = bound(0, mousecursor_x, vid.width-1); + mousecursor_y = bound(0, mousecursor_y, vid.height-1); + +#ifdef PLUGINS + Plug_SBar (r_refdef.playerview); +#else + if (Sbar_ShouldDraw(r_refdef.playerview)) + { + SCR_TileClear (sb_lines); + Sbar_Draw (r_refdef.playerview); + Sbar_DrawScoreboard (r_refdef.playerview); + } + else + SCR_TileClear (0); +#endif + + SCR_DrawTwoDimensional(true); + + VectorClear(r_worldentity.origin); + VectorClear(r_worldentity.angles); + VectorSet(r_worldentity.axis[0], 1,0,0); + VectorSet(r_worldentity.axis[1], 0,1,0); + VectorSet(r_worldentity.axis[2], 0,0,1); + r_worldentity.scale = 1; + GL_SetShaderState2D(false); + } } static void R_RenderEyeScene (texid_t rendertarget, vec4_t fovoverride, vec3_t eyeangorg[2]) { @@ -729,6 +798,7 @@ static void R_RenderEyeScene (texid_t rendertarget, vec4_t fovoverride, vec3_t e if ((size_t)(refdef.playerview-cl.playerview) < MAX_SPLITS) CL_ClampPitch (refdef.playerview-cl.playerview, 0); + vrui.enabled = true; if (rendertarget) { r = GLBE_FBO_Update(&fbo_vr, FBO_RB_DEPTH, &rendertarget, 1, r_nulltex, rendertarget->width, rendertarget->height, 0); @@ -742,44 +812,6 @@ static void R_RenderEyeScene (texid_t rendertarget, vec4_t fovoverride, vec3_t e R_SetupGL (eyeangorg, fovoverride, NULL, rendertarget); R_RenderScene_Internal(); - /*//if (eyematrix) - { - vec3_t newa, newo; - matrix3x4 headmatrix; //position of the head in local space - //eyematrix //position of the eye in head space... - matrix3x4 headeyematrix; - matrix3x4 correctionmatrix; //to nudge the 2d stuff into view - matrix3x4 viewmatrix; //final transform - extern usercmd_t cl_pendingcmd[MAX_SPLITS]; - newa[0] = SHORT2ANGLE(cl_pendingcmd[0].vr[VRDEV_HEAD].angles[0]); - newa[1] = SHORT2ANGLE(cl_pendingcmd[0].vr[VRDEV_HEAD].angles[1]); - newa[2] = SHORT2ANGLE(cl_pendingcmd[0].vr[VRDEV_HEAD].angles[2]); - Matrix3x4_RM_FromAngles(newa, cl_pendingcmd[0].vr[VRDEV_HEAD].origin, headmatrix[0]); - - newa[0] = Cvar_Get("2dpitch", "-90", 0, "")->value; - newa[1] = Cvar_Get("2dyaw", "0", 0, "")->value; - newa[2] = Cvar_Get("2droll", "90", 0, "")->value; - //why /4, not /2? wtf? - newo[0] = vid.width/4 + Cvar_Get("2dfwd", "0", 0, "")->value; - newo[1] = vid.height/4 + Cvar_Get("2dleft", "0", 0, "")->value; - newo[2] = Cvar_Get("2dup", "-256", 0, "")->value; - Matrix3x4_RM_FromAngles(newa, newo, correctionmatrix[0]); - - Matrix3x4_Multiply(headmatrix[0], eyematrix[0], headeyematrix[0]); - Matrix3x4_Multiply(headeyematrix[0], correctionmatrix[0], viewmatrix[0]); - Matrix3x4_RM_ToVectors(viewmatrix[0], vpn, vright, vup, r_origin); - VectorNegate(vright, vright); - - Matrix4x4_CM_ModelViewMatrixFromAxis(r_refdef.m_view, vpn, vright, vup, r_origin); - GL_SetShaderState2D(true); - - Menu_Draw(); - SCR_DrawConsole(false); - if (R2D_Flush) - R2D_Flush(); - GL_SetShaderState2D(false); - }*/ - if (rendertarget) { GLBE_FBO_Pop(r); @@ -1982,7 +2014,9 @@ void GLR_RenderView (void) if (!(r_refdef.flags & RDF_NOWORLDMODEL)) { //FIXME: fbo stuff - if (!r_worldentity.model || r_worldentity.model->loadstate != MLS_LOADED || !cl.worldmodel) + if (!r_worldentity.model || !cl.worldmodel) + r_refdef.flags |= RDF_NOWORLDMODEL; + else if (r_worldentity.model->loadstate != MLS_LOADED || !cl.worldmodel) { GL_Set2D (false); R2D_ImageColours(0, 0, 0, 1); diff --git a/engine/gl/gl_screen.c b/engine/gl/gl_screen.c index 498ccc3ac..b97785441 100644 --- a/engine/gl/gl_screen.c +++ b/engine/gl/gl_screen.c @@ -45,6 +45,16 @@ extern cvar_t vid_conautoscale; extern qboolean scr_con_forcedraw; extern qboolean depthcleared; +vrui_t vrui; + +void VRUI_SnapAngle(void) +{ +// VectorCopy(cl.playerview[0].viewangles, vrui.angles); + vrui.angles[0] = 0; + vrui.angles[1] = cl.playerview[0].aimangles[1]; + vrui.angles[2] = 0; +} + /* ================== SCR_UpdateScreen @@ -184,7 +194,7 @@ qboolean GLSCR_UpdateScreen (void) #endif else { - if (r_worldentity.model && cls.state == ca_active) + if ((r_worldentity.model && cls.state == ca_active) || vid.vr || vrui.enabled) V_RenderView (nohud); else noworld = true; @@ -218,7 +228,9 @@ qboolean GLSCR_UpdateScreen (void) nohud = true; } - SCR_DrawTwoDimensional(nohud); + r_refdef.playerview = &cl.playerview[0]; + if (!vrui.enabled) + SCR_DrawTwoDimensional(nohud); V_UpdatePalette (false); R2D_BrightenScreen(); diff --git a/engine/gl/gl_vidlinuxglx.c b/engine/gl/gl_vidlinuxglx.c index 5e8fd7e6b..2f3a372f1 100644 --- a/engine/gl/gl_vidlinuxglx.c +++ b/engine/gl/gl_vidlinuxglx.c @@ -2764,7 +2764,7 @@ static void UpdateGrabs(void) if (!vid.activeapp) wantmgrabs = false; allownullcursor = wantmgrabs; //this says whether we can possibly want it. if false then we disallow the null cursor. Yes, this might break mods that do their own sw cursors. such mods are flawed in other ways too. - if (Key_MouseShouldBeFree()) + if (!vrui.enabled && Key_MouseShouldBeFree()) wantmgrabs = false; // if (modeswitchpending) // wantmgrabs = false; diff --git a/engine/gl/gl_vidwayland.c b/engine/gl/gl_vidwayland.c index 5f6e2fd46..541b3e627 100644 --- a/engine/gl/gl_vidwayland.c +++ b/engine/gl/gl_vidwayland.c @@ -1464,7 +1464,7 @@ static void WL_SwapBuffers(void) } //if the game wants absolute mouse positions... - wantabs = !vid.activeapp || Key_MouseShouldBeFree() || !in_windowed_mouse.value; + wantabs = !vid.activeapp || (!vrui.enabled && Key_MouseShouldBeFree()) || !in_windowed_mouse.value; //and force it on if we're lacking one of the plethora of extensions that were needed to get the damn thing actually usable. wantabs |= !w.relative_pointer || !w.pointer_constraints; if (!wantabs && w.cursorfocus && !w.locked_pointer && w.pointer_constraints)