Skip to content

Commit

Permalink
Merge branch 'develop' into steam-beta
Browse files Browse the repository at this point in the history
  • Loading branch information
Raphiiko committed Jul 25, 2024
2 parents 5b73007 + e1f54f3 commit a226a73
Show file tree
Hide file tree
Showing 8 changed files with 179 additions and 21 deletions.
29 changes: 19 additions & 10 deletions src-overlay-ui/src/routes/+layout.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { browser } from "$app/environment";
import ipcService from "$lib/services/ipc.service";
import type { Load } from "@sveltejs/kit";
import { loadTranslations } from "$lib/translations";
import { get } from "svelte/store";
import { fontLoader } from "src-shared-ts/src/font-loader";
import { browser } from '$app/environment';
import ipcService from '$lib/services/ipc.service';
import type { Load } from '@sveltejs/kit';
import { loadTranslations } from '$lib/translations';
import { get } from 'svelte/store';
import { fontLoader } from 'src-shared-ts/src/font-loader';

export const trailingSlash = "always";
export const trailingSlash = 'always';
export const prerender = true;
export const ssr = false;

Expand All @@ -15,14 +15,23 @@ if (browser) {
export const load: Load = async ({ url }) => {
// Obtain query params
const urlParams = new URLSearchParams(window.location.search);
const corePort = parseInt(urlParams.get("corePort") ?? "5177", 10);
const corePort = parseInt(urlParams.get('corePort') ?? '5177', 10);
// If the core port was provided, initialize the font loader
if (corePort > 0 && corePort < 65536) fontLoader.init(corePort);
// if (corePort > 0 && corePort < 65536) fontLoader.init(corePort);
// Load fonts from Google if running outside of the overlay (development mode)
if (!window.CefSharp) loadDevFonts();
// Initialize IPC
await ipcService.init();
// Load translations
const { pathname } = url;
await loadTranslations(get(ipcService.state).locale ?? "en", pathname);
await loadTranslations(get(ipcService.state).locale ?? 'en', pathname);

return {};
};

function loadDevFonts() {
const link = document.createElement('link');
link.href = 'https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap';
link.rel = 'stylesheet';
document.head.appendChild(link);
}
13 changes: 9 additions & 4 deletions src-ui/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,11 +226,10 @@ import { BrightnessAutomationDetailsComponent } from './views/dashboard-view/vie
import { DurationInputSettingComponent } from './components/duration-input-setting/duration-input-setting.component';
import { CCTControlService } from './services/cct-control/cct-control.service';
import { CCTControlModalComponent } from './components/cct-control-modal/cct-control-modal.component';
import {
SettingsBrightnessCctViewComponent,
} from './views/dashboard-view/views/settings-brightness-cct-view/settings-brightness-cct-view.component';
import { SettingsBrightnessCctViewComponent } from './views/dashboard-view/views/settings-brightness-cct-view/settings-brightness-cct-view.component';
import { CCTInputSettingComponent } from './components/cct-input-setting/cct-input-setting.component';
import { BrightnessAdvancedModeToggleComponent } from './components/brightness-advanced-mode-toggle/brightness-advanced-mode-toggle.component';
import { FBTAvatarReloadHotfixService } from './services/hotfixes/f-b-t-avatar-reload-hotfix.service';

[
localeEN,
Expand Down Expand Up @@ -490,7 +489,9 @@ export class AppModule {
private nightmareDetectionAutomationService: NightmareDetectionAutomationService,
private bigscreenBeyondLedAutomationService: BigscreenBeyondLedAutomationService,
private bigscreenBeyondFanAutomationService: BigscreenBeyondFanAutomationService,
private vrchatAvatarAutomationsService: VRChatAvatarAutomationsService
private vrchatAvatarAutomationsService: VRChatAvatarAutomationsService,
// Hotfixes
private fbtAvatarReloadHotfixService: FBTAvatarReloadHotfixService
) {
this.init();
}
Expand Down Expand Up @@ -779,6 +780,10 @@ export class AppModule {
'VRChatAvatarAutomationsService initialization',
this.vrchatAvatarAutomationsService.init()
),
this.logInit(
'FBTAvatarReloadHotfixService initialization',
this.fbtAvatarReloadHotfixService.init()
),
]);
await info(`[Init] Initialization complete! (took ${Date.now() - initStartTime}ms)`);
})(),
Expand Down
2 changes: 2 additions & 0 deletions src-ui/app/models/automations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,7 @@ export interface SleepingAnimationsAutomationConfig extends AutomationConfig {
unlockFeetOnAutomationDisable: boolean;
releaseFootLockOnPoseChange: boolean;
footLockReleaseWindow: number;
enableAvatarReloadOnFBTDisableHotfix: boolean;
}

export type VRChatVoiceMode = 'TOGGLE' | 'PUSH_TO_TALK';
Expand Down Expand Up @@ -683,6 +684,7 @@ export const AUTOMATION_CONFIGS_DEFAULT: AutomationConfigs = {
unlockFeetOnAutomationDisable: true,
releaseFootLockOnPoseChange: true,
footLockReleaseWindow: 600,
enableAvatarReloadOnFBTDisableHotfix: false,
oscScripts: {},
},
JOIN_NOTIFICATIONS: {
Expand Down
90 changes: 90 additions & 0 deletions src-ui/app/services/hotfixes/f-b-t-avatar-reload-hotfix.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { Injectable } from '@angular/core';
import { OpenVRService } from '../openvr.service';
import {
asyncScheduler,
distinctUntilChanged,
filter,
map,
pairwise,
switchMap,
take,
throttleTime,
} from 'rxjs';
import { isEqual } from 'lodash';
import { OscService } from '../osc.service';
import { sleep } from '../../utils/promise-utils';
import { info } from 'tauri-plugin-log-api';
import { SleepingAnimationsAutomationService } from '../osc-automations/sleeping-animations-automation.service';
import { VRChatService } from '../vrchat.service';
import { AutomationConfigService } from '../automation-config.service';

@Injectable({
providedIn: 'root',
})
export class FBTAvatarReloadHotfixService {
private enabled = false;

constructor(
private openvr: OpenVRService,
private osc: OscService,
private vrchat: VRChatService,
private sleepAnimations: SleepingAnimationsAutomationService,
private automationConfig: AutomationConfigService
) {}

async init() {
this.automationConfig.configs
.pipe(map((configs) => configs.SLEEPING_ANIMATIONS.enableAvatarReloadOnFBTDisableHotfix))
.subscribe((enabled) => (this.enabled = enabled));
this.openvr.devices
.pipe(
// Only run if this hotfix is enabled
filter(() => this.enabled),
// Detect all trackers turning off
map((devices) =>
devices
.filter((d) => d.class === 'GenericTracker' && (d.canPowerOff || d.isTurningOff))
.map((d) => d.serialNumber)
),
pairwise(),
distinctUntilChanged((a, b) => isEqual(a, b)),
filter(([prev, curr]) => prev.length > 0 && curr.length === 0),
// Only run while VRChat is active
switchMap(() => this.vrchat.vrchatProcessActive.pipe(take(1))),
filter(Boolean),
// Only trigger once every 5s max
throttleTime(5000, asyncScheduler, { leading: true, trailing: false })
)
.subscribe(() => this.triggerHotfix());
}

private async triggerHotfix() {
info(
'[FBTAvatarReloadHotfix] All trackers have been turned off. Running hotfix to reload avatar'
);
// Wait for VRC to process the trackers fully turning off
await sleep(3000);

// Open the quick menu
await this.osc.send_int('/input/QuickMenuToggleLeft', 0);
await sleep(150);
await this.osc.send_int('/input/QuickMenuToggleLeft', 1);
await sleep(150);
await this.osc.send_int('/input/QuickMenuToggleLeft', 0);

// Wait a bit
await sleep(500);

// Close the quick menu
await this.osc.send_int('/input/QuickMenuToggleLeft', 0);
await sleep(150);
await this.osc.send_int('/input/QuickMenuToggleLeft', 1);
await sleep(150);
await this.osc.send_int('/input/QuickMenuToggleLeft', 0);

// Inform sleeping automations to reapply
await this.sleepAnimations.retrigger();

info('[FBTAvatarReloadHotfix] Hotfix applied');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
map,
pairwise,
startWith,
Subject,
} from 'rxjs';
import { SleepService } from '../sleep.service';
import { SleepingPose } from '../../models/sleeping-pose';
Expand All @@ -28,6 +29,7 @@ export class SleepingAnimationsAutomationService {
private config: SleepingAnimationsAutomationConfig = structuredClone(
AUTOMATION_CONFIGS_DEFAULT.SLEEPING_ANIMATIONS
);
private retrigger$ = new Subject<void>();

constructor(
private automationConfig: AutomationConfigService,
Expand All @@ -50,6 +52,8 @@ export class SleepingAnimationsAutomationService {
combineLatest([
// Pose changes
this.sleep.pose,
// External retriggers
this.retrigger$.pipe(startWith(void 0)),
// Retrigger when automation is enabled
this.automationConfig.configs.pipe(
map((configs) => configs.SLEEPING_ANIMATIONS.enabled),
Expand Down Expand Up @@ -147,4 +151,8 @@ export class SleepingAnimationsAutomationService {
async forcePose(pose: SleepingPose) {
this.sleep.forcePose(pose);
}

async retrigger() {
this.retrigger$.next();
}
}
4 changes: 4 additions & 0 deletions src-ui/app/utils/promise-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,7 @@ export function pTimeout<T>(
});
return Promise.race([promise, timeout]) as Promise<T>;
}

export function sleep(ms: number) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
Original file line number Diff line number Diff line change
Expand Up @@ -284,5 +284,38 @@ <h3 translate>oscAutomations.sleepingAnimations.options.general.footLock.title</
</div>
</div>
</div>
<div class="setting-category">
<h3 translate>oscAutomations.sleepingAnimations.options.general.advanced.title</h3>
<div class="settings">
<div class="setting-row">
<div class="setting-row-label" translate>
<span translate
>oscAutomations.sleepingAnimations.options.general.advanced.avatarReloadHotfix.title</span
>
<span
[innerHtml]="
'oscAutomations.sleepingAnimations.options.general.advanced.avatarReloadHotfix.description'
| translate
"
></span>
</div>
<div class="setting-row-action">
<label class="switch-toggle">
<input
type="checkbox"
[checked]="config.enableAvatarReloadOnFBTDisableHotfix"
(change)="
updateConfig({
enableAvatarReloadOnFBTDisableHotfix:
!config.enableAvatarReloadOnFBTDisableHotfix
})
"
/>
<span class="switch-toggle-slider"></span>
</label>
</div>
</div>
</div>
</div>
</div>
</div>
21 changes: 14 additions & 7 deletions src-ui/assets/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@
"SET_VOLUME": "Change Volume",
"UNMUTE": "Unmute"
},
"applyOnStart": {
"description": {
"onSleepDisable": "Run this automation when OyasumiVR starts with the sleep mode disabled",
"onSleepEnable": "Run this automation when OyasumiVR starts with the sleep mode enabled"
},
"title": "Apply on start"
},
"automations": {
"label": "{count, plural, one {1 Automation} other {# Automations}}"
},
Expand Down Expand Up @@ -58,13 +65,6 @@
"volume": {
"description": "What volume level to set for the audio device when this automation runs",
"title": "Volume"
},
"applyOnStart": {
"title": "Apply on start",
"description": {
"onSleepEnable": "Run this automation when OyasumiVR starts with the sleep mode enabled",
"onSleepDisable": "Run this automation when OyasumiVR starts with the sleep mode disabled"
}
}
},
"auto-invite-request-accept": {
Expand Down Expand Up @@ -1249,6 +1249,13 @@
"title": "Foot Lock"
},
"general": {
"advanced": {
"avatarReloadHotfix": {
"title": "Hotfix for using avatar animations with FBT",
"description": "Enable this if you want to use avatar animations after OyasumiVR has turned off your full body trackers. <a href=\"https://github.com/Raphiiko/OyasumiVR/wiki/Hotfix-for-using-avatar-animations-with-FBT\" target=\"_blank\">What is this and why is it needed?</a>"
},
"title": "Advanced Options"
},
"footLock": {
"description": "A foot lock commonly prevents the player from moving or rotating when it is enabled.",
"title": "Foot Lock"
Expand Down

0 comments on commit a226a73

Please sign in to comment.