Replace E effect cycling with effect selection menu
This commit is contained in:
@@ -63,7 +63,7 @@
|
|||||||
<p><b>M:</b> Mute/unmute</p>
|
<p><b>M:</b> Mute/unmute</p>
|
||||||
<p><b>Shift+M:</b> Toggle stereo/mono output</p>
|
<p><b>Shift+M:</b> Toggle stereo/mono output</p>
|
||||||
<p><b>! (Shift+1):</b> Toggle loopback monitor</p>
|
<p><b>! (Shift+1):</b> Toggle loopback monitor</p>
|
||||||
<p><b>E:</b> Cycle voice effect</p>
|
<p><b>E:</b> Select voice effect</p>
|
||||||
<p><b>Dash or Equals:</b> Lower/raise active effect value</p>
|
<p><b>Dash or Equals:</b> Lower/raise active effect value</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
// Maintainer-controlled web client version.
|
// Maintainer-controlled web client version.
|
||||||
// Format: YYYY.MM.DD Rn (example: 2026.02.20 R2)
|
// Format: YYYY.MM.DD Rn (example: 2026.02.20 R2)
|
||||||
window.CHGRID_WEB_VERSION = "2026.02.21 R80";
|
window.CHGRID_WEB_VERSION = "2026.02.21 R81";
|
||||||
|
|||||||
@@ -111,6 +111,13 @@ export class AudioEngine {
|
|||||||
return EFFECT_SEQUENCE[this.effectIndex];
|
return EFFECT_SEQUENCE[this.effectIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setOutboundEffect(effectId: EffectId): { id: EffectId; label: string } {
|
||||||
|
const nextIndex = EFFECT_SEQUENCE.findIndex((effect) => effect.id === effectId);
|
||||||
|
this.effectIndex = nextIndex >= 0 ? nextIndex : this.effectIndex;
|
||||||
|
this.rebuildOutboundEffectGraph();
|
||||||
|
return EFFECT_SEQUENCE[this.effectIndex];
|
||||||
|
}
|
||||||
|
|
||||||
getCurrentEffect(): { id: EffectId; label: string; value: number; defaultValue: number } {
|
getCurrentEffect(): { id: EffectId; label: string; value: number; defaultValue: number } {
|
||||||
const effect = EFFECT_SEQUENCE[this.effectIndex];
|
const effect = EFFECT_SEQUENCE[this.effectIndex];
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -1092,6 +1092,7 @@ function disconnect(): void {
|
|||||||
state.editingPropertyKey = null;
|
state.editingPropertyKey = null;
|
||||||
state.itemPropertyOptionValues = [];
|
state.itemPropertyOptionValues = [];
|
||||||
state.itemPropertyOptionIndex = 0;
|
state.itemPropertyOptionIndex = 0;
|
||||||
|
state.effectSelectIndex = 0;
|
||||||
pendingEscapeDisconnect = false;
|
pendingEscapeDisconnect = false;
|
||||||
|
|
||||||
connecting = false;
|
connecting = false;
|
||||||
@@ -1327,8 +1328,11 @@ function handleNormalModeInput(code: string, shiftKey: boolean): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (code === 'KeyE') {
|
if (code === 'KeyE') {
|
||||||
const effect = audio.cycleOutboundEffect();
|
const currentEffect = audio.getCurrentEffect();
|
||||||
updateStatus(effect.label);
|
const currentIndex = EFFECT_SEQUENCE.findIndex((effect) => effect.id === currentEffect.id);
|
||||||
|
state.effectSelectIndex = currentIndex >= 0 ? currentIndex : 0;
|
||||||
|
state.mode = 'effectSelect';
|
||||||
|
updateStatus(`Select effect: ${EFFECT_SEQUENCE[state.effectSelectIndex].label}`);
|
||||||
audio.sfxUiBlip();
|
audio.sfxUiBlip();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1625,6 +1629,46 @@ function handleChatModeInput(code: string, key: string): void {
|
|||||||
applyTextInputEdit(code, key, 500);
|
applyTextInputEdit(code, key, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleEffectSelectModeInput(code: string, key: string): void {
|
||||||
|
if (code === 'ArrowDown' || code === 'ArrowUp') {
|
||||||
|
state.effectSelectIndex =
|
||||||
|
code === 'ArrowDown'
|
||||||
|
? (state.effectSelectIndex + 1) % EFFECT_SEQUENCE.length
|
||||||
|
: (state.effectSelectIndex - 1 + EFFECT_SEQUENCE.length) % EFFECT_SEQUENCE.length;
|
||||||
|
updateStatus(`Select effect: ${EFFECT_SEQUENCE[state.effectSelectIndex].label}`);
|
||||||
|
audio.sfxUiBlip();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nextByInitial = findNextIndexByInitial(
|
||||||
|
EFFECT_SEQUENCE,
|
||||||
|
state.effectSelectIndex,
|
||||||
|
key,
|
||||||
|
(effect) => effect.label,
|
||||||
|
);
|
||||||
|
if (nextByInitial >= 0) {
|
||||||
|
state.effectSelectIndex = nextByInitial;
|
||||||
|
updateStatus(`Select effect: ${EFFECT_SEQUENCE[state.effectSelectIndex].label}`);
|
||||||
|
audio.sfxUiBlip();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (code === 'Enter') {
|
||||||
|
const selected = EFFECT_SEQUENCE[state.effectSelectIndex];
|
||||||
|
const effect = audio.setOutboundEffect(selected.id);
|
||||||
|
state.mode = 'normal';
|
||||||
|
updateStatus(effect.label);
|
||||||
|
audio.sfxUiBlip();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (code === 'Escape') {
|
||||||
|
state.mode = 'normal';
|
||||||
|
updateStatus('Cancelled.');
|
||||||
|
audio.sfxUiCancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function handleListModeInput(code: string, key: string): void {
|
function handleListModeInput(code: string, key: string): void {
|
||||||
if (state.sortedPeerIds.length === 0) {
|
if (state.sortedPeerIds.length === 0) {
|
||||||
state.mode = 'normal';
|
state.mode = 'normal';
|
||||||
@@ -2164,6 +2208,8 @@ function setupInputHandlers(): void {
|
|||||||
handleNicknameModeInput(code, event.key);
|
handleNicknameModeInput(code, event.key);
|
||||||
} else if (state.mode === 'chat') {
|
} else if (state.mode === 'chat') {
|
||||||
handleChatModeInput(code, event.key);
|
handleChatModeInput(code, event.key);
|
||||||
|
} else if (state.mode === 'effectSelect') {
|
||||||
|
handleEffectSelectModeInput(code, event.key);
|
||||||
} else if (state.mode === 'listUsers') {
|
} else if (state.mode === 'listUsers') {
|
||||||
handleListModeInput(code, event.key);
|
handleListModeInput(code, event.key);
|
||||||
} else if (state.mode === 'listItems') {
|
} else if (state.mode === 'listItems') {
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ export type GameMode =
|
|||||||
| 'normal'
|
| 'normal'
|
||||||
| 'nickname'
|
| 'nickname'
|
||||||
| 'chat'
|
| 'chat'
|
||||||
|
| 'effectSelect'
|
||||||
| 'listUsers'
|
| 'listUsers'
|
||||||
| 'listItems'
|
| 'listItems'
|
||||||
| 'addItem'
|
| 'addItem'
|
||||||
@@ -69,6 +70,7 @@ export type GameState = {
|
|||||||
editingPropertyKey: string | null;
|
editingPropertyKey: string | null;
|
||||||
itemPropertyOptionValues: string[];
|
itemPropertyOptionValues: string[];
|
||||||
itemPropertyOptionIndex: number;
|
itemPropertyOptionIndex: number;
|
||||||
|
effectSelectIndex: number;
|
||||||
addItemTypeIndex: number;
|
addItemTypeIndex: number;
|
||||||
isMuted: boolean;
|
isMuted: boolean;
|
||||||
player: Player;
|
player: Player;
|
||||||
@@ -98,6 +100,7 @@ export function createInitialState(): GameState {
|
|||||||
editingPropertyKey: null,
|
editingPropertyKey: null,
|
||||||
itemPropertyOptionValues: [],
|
itemPropertyOptionValues: [],
|
||||||
itemPropertyOptionIndex: 0,
|
itemPropertyOptionIndex: 0,
|
||||||
|
effectSelectIndex: 0,
|
||||||
addItemTypeIndex: 0,
|
addItemTypeIndex: 0,
|
||||||
isMuted: false,
|
isMuted: false,
|
||||||
player: {
|
player: {
|
||||||
|
|||||||
Reference in New Issue
Block a user