@epicgames-ps/lib-pixelstreamingfrontend-ue5.4
Version:
Frontend library for Unreal Engine 5.4 Pixel Streaming
125 lines (112 loc) • 4.03 kB
text/typescript
// Copyright Epic Games, Inc. All Rights Reserved.
import type { OptionParametersIds } from './Config';
import { SettingBase } from './SettingBase';
/**
* An Option setting object with a text label. Allows you to specify an array of options and select one of them.
*/
export class SettingOption<
CustomIds extends string = OptionParametersIds
> extends SettingBase {
id: OptionParametersIds | CustomIds;
onChangeEmit: (changedValue: string) => void;
_options: Array<string>;
useUrlParams: boolean;
constructor(
id: OptionParametersIds | CustomIds,
label: string,
description: string,
defaultTextValue: string,
options: Array<string>,
useUrlParams: boolean,
// eslint-disable-next-line @typescript-eslint/no-empty-function
defaultOnChangeListener: (changedValue: unknown, setting: SettingBase) => void = () => { /* Do nothing, to be overridden. */ }
) {
super(id, label, description, defaultTextValue, defaultOnChangeListener);
this.options = options;
const urlParams = new URLSearchParams(window.location.search);
const stringToMatch: string =
useUrlParams && urlParams.has(this.id)
? this.getUrlParamText()
: defaultTextValue;
this.selected = stringToMatch;
this.useUrlParams = useUrlParams;
}
/**
* Parse the text value from the url parameters.
* @returns The text value parsed from the url if the url parameters contains /?id=value, but empty string if just /?id or no url param found.
*/
getUrlParamText(): string {
const urlParams = new URLSearchParams(window.location.search);
if (urlParams.has(this.id)) {
return urlParams.get(this.id) ?? '';
}
return '';
}
/**
* Persist the setting value in URL.
*/
public updateURLParams() {
if (this.useUrlParams) {
// set url params
const urlParams = new URLSearchParams(window.location.search);
urlParams.set(this.id, this.selected);
window.history.replaceState(
{},
'',
urlParams.toString() !== ''
? `${location.pathname}?${urlParams}`
: `${location.pathname}`
);
}
}
/**
* Add a change listener to the select element.
*/
public addOnChangedListener(onChangedFunc: (newValue: string) => void) {
this.onChange = onChangedFunc;
}
/**
* @returns All available options as an array
*/
public get options(): Array<string> {
return this._options;
}
/**
* Set options
* @param values Array of options
*/
public set options(values: Array<string>) {
this._options = values;
this.onChangeEmit(this.selected);
}
/**
* @returns Selected option as a string
*/
public get selected(): string {
return this.value as string;
}
/**
* Set selected option if it matches one of the available options
* @param value Selected option
*/
public set selected(value: string) {
// A user may not specify the full possible value so we instead use the closest match.
// eg ?xxx=H264 would select 'H264 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f'
let filteredList = this.options.filter(
(option: string) => option.indexOf(value) !== -1
);
if (filteredList.length) {
this.value = filteredList[0];
return;
}
// A user has specified a codec with a fmtp string but this codec + fmtp line isn't available.
// in that case, just use the codec
filteredList = this.options.filter(
(option: string) => option.indexOf(value.split(' ')[0]) !== -1
);
if (filteredList.length) {
this.value = filteredList[0];
return;
}
}
}