Files
VRCX/src/stores/vr.js
rs189 a2dc6ba9a4 Linux: SteamVR overlay support (#1299)
* fix: open folder and select item on linux

* feat: linux wrist overlay

* feat: linux hmd overlay

* feat: replace unix sockets with shm on linux

* fix: reduce linux wrist overlay fps

* fix: hide electron offscreen windows

* fix: destroy electron offscreen windows when not in use

* fix: open folder and select item on linux

* feat: cpu, uptime and device monitoring on linux

* feat: native wayland gl context with x11 fallback on linux

* fix: use platform agnostic wording for common folders

* fix: crash dumps folder button on linux

* fix: enable missing VR notification options on linux

* fix: update cef, eslint config to include updated AppApiVr names

* merge: rebase linux VR changes to upstream

* Clean up

* Load custom file contents rather than path

Fixes loading custom file in debug mode

* fix: call SetVR on linux as well

* fix: AppApiVrElectron init, properly create and dispose of shm

* Handle avatar history error

* Lint

* Change overlay dispose logic

* macOS DOTNET_ROOT

* Remove moving dotnet bin

* Fix

* fix: init overlay on SteamVR restart

* Fix fetching empty instance, fix user dialog not fetching

* Trim direct access inputs

* Make icon higher res, because mac build would fail 😂

* macOS fixes

* will it build? that's the question

* fix: ensure offscreen windows are ready before vrinit

* will it build? that's the question

* will it build? that's the question

* meow

* one, more, time

* Fix crash and overlay ellipsis

* a

---------

Co-authored-by: Natsumi <cmcooper123@hotmail.com>
2025-07-19 12:07:43 +12:00

203 lines
7.2 KiB
JavaScript

import { defineStore } from 'pinia';
import { reactive, watch } from 'vue';
import { isRpcWorld } from '../shared/utils';
import { watchState } from '../service/watchState';
import { useFriendStore } from './friend';
import { useGameStore } from './game';
import { useGameLogStore } from './gameLog';
import { useLocationStore } from './location';
import { usePhotonStore } from './photon';
import { useAdvancedSettingsStore } from './settings/advanced';
import { useAppearanceSettingsStore } from './settings/appearance';
import { useNotificationsSettingsStore } from './settings/notifications';
import { useWristOverlaySettingsStore } from './settings/wristOverlay';
import { useSharedFeedStore } from './sharedFeed';
import { useUserStore } from './user';
export const useVrStore = defineStore('Vr', () => {
const friendStore = useFriendStore();
const advancedSettingsStore = useAdvancedSettingsStore();
const wristOverlaySettingsStore = useWristOverlaySettingsStore();
const locationStore = useLocationStore();
const notificationsSettingsStore = useNotificationsSettingsStore();
const photonStore = usePhotonStore();
const appearanceSettingsStore = useAppearanceSettingsStore();
const gameStore = useGameStore();
const gameLogStore = useGameLogStore();
const userStore = useUserStore();
const sharedFeedStore = useSharedFeedStore();
const state = reactive({
overlayActive: false
});
watch(
() => watchState.isFriendsLoaded,
(isFriendsLoaded) => {
if (isFriendsLoaded) {
vrInit();
}
},
{ flush: 'sync' }
);
// also runs from CEF C# on overlay browser startup
function vrInit() {
updateVRConfigVars();
updateVRLastLocation();
updateVrNowPlaying();
// run these methods again to send data to the overlay
sharedFeedStore.updateSharedFeed(true);
friendStore.onlineFriendCount = 0; // force an update
friendStore.updateOnlineFriendCoutner();
state.overlayActive = true;
}
async function saveOpenVROption() {
sharedFeedStore.updateSharedFeed(true);
updateVRConfigVars();
updateVRLastLocation();
AppApi.ExecuteVrOverlayFunction('notyClear', '');
updateOpenVR();
}
function updateVrNowPlaying() {
const json = JSON.stringify(gameLogStore.nowPlaying);
AppApi.ExecuteVrFeedFunction('nowPlayingUpdate', json);
AppApi.ExecuteVrOverlayFunction('nowPlayingUpdate', json);
}
function updateVRLastLocation() {
let progressPie = false;
if (advancedSettingsStore.progressPie) {
progressPie = true;
if (advancedSettingsStore.progressPieFilter) {
if (!isRpcWorld(locationStore.lastLocation.location)) {
progressPie = false;
}
}
}
let onlineFor = null;
if (!wristOverlaySettingsStore.hideUptimeFromFeed) {
onlineFor = userStore.currentUser.$online_for;
}
const lastLocation = {
date: locationStore.lastLocation.date,
location: locationStore.lastLocation.location,
name: locationStore.lastLocation.name,
playerList: Array.from(
locationStore.lastLocation.playerList.values()
),
friendList: Array.from(
locationStore.lastLocation.friendList.values()
),
progressPie,
onlineFor
};
const json = JSON.stringify(lastLocation);
AppApi.ExecuteVrFeedFunction('lastLocationUpdate', json);
AppApi.ExecuteVrOverlayFunction('lastLocationUpdate', json);
}
function updateVRConfigVars() {
let notificationTheme = 'relax';
if (appearanceSettingsStore.isDarkMode) {
notificationTheme = 'sunset';
}
const VRConfigVars = {
overlayNotifications:
notificationsSettingsStore.overlayNotifications,
hideDevicesFromFeed: wristOverlaySettingsStore.hideDevicesFromFeed,
vrOverlayCpuUsage: wristOverlaySettingsStore.vrOverlayCpuUsage,
minimalFeed: wristOverlaySettingsStore.minimalFeed,
notificationPosition:
notificationsSettingsStore.notificationPosition,
notificationTimeout: notificationsSettingsStore.notificationTimeout,
photonOverlayMessageTimeout:
photonStore.photonOverlayMessageTimeout,
notificationTheme,
backgroundEnabled: wristOverlaySettingsStore.vrBackgroundEnabled,
dtHour12: appearanceSettingsStore.dtHour12,
pcUptimeOnFeed: wristOverlaySettingsStore.pcUptimeOnFeed,
appLanguage: appearanceSettingsStore.appLanguage,
notificationOpacity: advancedSettingsStore.notificationOpacity
};
const json = JSON.stringify(VRConfigVars);
AppApi.ExecuteVrFeedFunction('configUpdate', json);
AppApi.ExecuteVrOverlayFunction('configUpdate', json);
}
function updateOpenVR() {
let newState = {
active: false,
hmdOverlay: false,
wristOverlay: false,
menuButton: false,
overlayHand: 0
};
if (
notificationsSettingsStore.openVR &&
gameStore.isSteamVRRunning &&
((gameStore.isGameRunning && !gameStore.isGameNoVR) ||
wristOverlaySettingsStore.openVRAlways)
) {
let hmdOverlay = false;
if (
notificationsSettingsStore.overlayNotifications ||
advancedSettingsStore.progressPie ||
photonStore.photonEventOverlay ||
photonStore.timeoutHudOverlay
) {
hmdOverlay = true;
}
newState = {
active: true,
hmdOverlay,
wristOverlay: wristOverlaySettingsStore.overlayWrist,
menuButton: wristOverlaySettingsStore.overlaybutton,
overlayHand: wristOverlaySettingsStore.overlayHand
};
}
AppApi.SetVR(
newState.active,
newState.hmdOverlay,
newState.wristOverlay,
newState.menuButton,
newState.overlayHand
);
if (LINUX) {
window.electron.updateVr(
newState.active,
newState.hmdOverlay,
newState.wristOverlay,
newState.menuButton,
newState.overlayHand
);
if (state.overlayActive !== newState.active) {
if (
window.electron.getWristOverlayWindow() ||
window.electron.getHmdOverlayWindow()
) {
vrInit();
state.overlayActive = newState.active;
}
setTimeout(() => vrInit(), 1000); // give the overlay time to load
}
}
}
return {
state,
vrInit,
saveOpenVROption,
updateVrNowPlaying,
updateVRLastLocation,
updateVRConfigVars,
updateOpenVR
};
});