diff --git a/src/components/sfx/SfxPlayer.gd b/src/components/sfx/SfxPlayer.gd index effa4bf..99a244d 100644 --- a/src/components/sfx/SfxPlayer.gd +++ b/src/components/sfx/SfxPlayer.gd @@ -15,6 +15,10 @@ signal on_action_select signal toggle_sfx(state: bool) signal toggle_music(state: bool) +func _init() -> void: + if Utils.get_platform() == Utils.Platform.WEB: + create_mute_callbac() + func _ready() -> void: on_section_chaged.connect(_play_section_chaged) on_section_select.connect(_play_section_select) @@ -48,3 +52,35 @@ func _play_section_select(): func _play_action_select(): action_select.play() + +var js_audio_callback: JavaScriptObject + +func create_mute_callbac() -> void: + js_audio_callback = JavaScriptBridge.create_callback(_set_audio_state) + JavaScriptBridge.eval(""" +var godotAudioBridge = { + callback: null, + setCallback: (cb) => this.callback = cb, + setAudioState: (data) => this.callback(JSON.stringify(data)), +}; + """, true) + var godot_bridge = JavaScriptBridge.get_interface("godotAudioBridge") + godot_bridge.setCallback(js_audio_callback) + +func _set_audio_state(data: Array) -> void: + var json := JSON.new() + var err := json.parse(data[0]) + if err != OK: + push_error(error_string(err)) + return + var args = json.data + var state: bool + var volume: float + if args.get("state") != null: + state = args.get("state") + print('set state: ', state) + _on_toggle_music(state) + _on_toggle_sfx(state) + if args.get("volume") != null: + volume = args.get("volume") + print('set volume: ', volume) diff --git a/web/src/components/GodotFrame.tsx b/web/src/components/GodotFrame.tsx index 4d274e3..89d963b 100644 --- a/web/src/components/GodotFrame.tsx +++ b/web/src/components/GodotFrame.tsx @@ -1,19 +1,67 @@ -import { useState } from "react"; -import Iframe from "react-iframe"; +import { useState, useRef, useEffect } from "react"; import { Button } from "../shadcn/ui/button"; -import { FaPlay } from "react-icons/fa"; +import { FaPlay, FaExpand, FaVolumeUp, FaVolumeMute } from "react-icons/fa"; import { useQuery } from "@tanstack/react-query"; import { getGameVersionInfo } from "../lib/versions"; +interface AudioBridge { + state?: boolean; + volume?: number; +} +interface GodotBridge { + setAudioState(data: AudioBridge): unknown; +} +interface WindowBridge extends Window { + godotAudioBridge: GodotBridge; +} + export const GodotFrame = () => { const [showIframe, setShowIframe] = useState(false); + const [muted, setMuted] = useState(false); + const iframeRef = useRef(null); const { data: gameVersionData } = useQuery({ queryKey: ["version-data"], queryFn: async () => await getGameVersionInfo(), }); + + const handleFullscreen = () => { + if (iframeRef.current) { + iframeRef.current.requestFullscreen(); + } + }; + + const handleKeyDown = (event: { key: string }) => { + if (event.key === "Escape") { + if (document.fullscreenElement) { + document.exitFullscreen(); + } + } + }; + + const handleMuteToggle = () => { + setMuted((prevMuted) => { + const newMuted = !prevMuted; + if (iframeRef.current && iframeRef.current.contentWindow) { + const w = iframeRef.current.contentWindow as WindowBridge; + w.godotAudioBridge.setAudioState({ state: prevMuted }); + } + return newMuted; + }); + }; + + useEffect(() => { + document.addEventListener("keydown", handleKeyDown); + return () => { + document.removeEventListener("keydown", handleKeyDown); + }; + }, []); + return (
-
+
{!showIframe && (
)} {showIframe && ( -