Skip to content

Commit

Permalink
feat(web): js bridge w/ iframe
Browse files Browse the repository at this point in the history
  • Loading branch information
akorzunin committed Aug 6, 2024
1 parent abbffa8 commit c175268
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 16 deletions.
36 changes: 36 additions & 0 deletions src/components/sfx/SfxPlayer.gd
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
95 changes: 79 additions & 16 deletions web/src/components/GodotFrame.tsx
Original file line number Diff line number Diff line change
@@ -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<HTMLIFrameElement>(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 (
<div className="grid justify-items-center px-6 pt-6">
<div className="w-screen-lg relative aspect-video min-h-[70vh]">
<div
className="w-screen-lg relative aspect-video min-w-[90vw]"
style={{ maxHeight: "60vh" }}
>
{!showIframe && (
<div className="absolute inset-0 flex items-center justify-center bg-muted bg-opacity-75">
<Button onClick={() => setShowIframe(true)}>
Expand All @@ -23,18 +71,33 @@ export const GodotFrame = () => {
</div>
)}
{showIframe && (
<Iframe
url={import.meta.env.DEV ? "/download/" : "download/web/index.html"}
id=""
className="inset-0"
height="100%"
width="100%"
title="SuperIcosahedron"
display="initial"
loading="lazy"
scrolling="no"
frameBorder={0}
/>
<>
<iframe
src={"download/web/index.html"}
id="iframeId"
className="inset-0 overflow-hidden"
height="100%"
width="100%"
title="SuperIcosahedron"
allow="autoplay"
loading="lazy"
ref={iframeRef}
/>
<Button
className="absolute bottom-10 left-10"
onClick={handleFullscreen}
>
<FaExpand />
&nbsp;Fullscreen
</Button>
<Button
className="absolute bottom-10 right-10"
onClick={handleMuteToggle}
>
{muted ? <FaVolumeMute /> : <FaVolumeUp />}
&nbsp;{muted ? "Unmute" : "Mute"}
</Button>
</>
)}
<p className="absolute bottom-0 right-2 text-primary-foreground">
build: {gameVersionData?.version} commit: {gameVersionData?.commit}
Expand Down

0 comments on commit c175268

Please sign in to comment.