Commit 4c6160de authored by Stoll's avatar Stoll
Browse files

Fix: Emojis loaded correctly

parent 98fab318
import React from "react";
interface ScreenshotButtonProps {
mountRef: React.RefObject<HTMLDivElement | null>;
overlayRef: React.RefObject<HTMLDivElement | null>;
reticleRef?: React.RefObject<any>; // Optional if you have a reticle
}
const ScreenshotButton: React.FC<ScreenshotButtonProps> = ({
mountRef,
overlayRef,
reticleRef,
}) => {
const captureAndDownload = () => {
const canvas =
(mountRef.current?.querySelector("canvas") ||
document.querySelector("canvas")) as HTMLCanvasElement | null;
if (!canvas || !overlayRef.current) return;
const overlayEl = overlayRef.current;
const prevPointer = overlayEl.style.pointerEvents;
const prevOpacity = overlayEl.style.opacity;
overlayEl.style.pointerEvents = "none";
overlayEl.style.opacity = "0";
const reticle = reticleRef?.current;
const prevReticleVisible = reticle?.visible ?? false;
if (reticle) reticle.visible = false;
requestAnimationFrame(() => {
canvas.toBlob((blob) => {
overlayEl.style.pointerEvents = prevPointer;
overlayEl.style.opacity = prevOpacity;
if (reticle) reticle.visible = prevReticleVisible;
if (!blob) return;
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
const ts = new Date().toISOString().replace(/[:.]/g, "-");
a.href = url;
a.download = `ar-snapshot-${ts}.png`;
document.body.appendChild(a);
a.click();
a.remove();
URL.revokeObjectURL(url);
}, "image/png");
});
};
return (
<button
onClick={captureAndDownload}
aria-label="Save snapshot"
style={{
position: "absolute",
top: "4rem",
right: "1.5rem",
zIndex: 1000,
padding: "10px 12px",
borderRadius: 12,
border: "none",
background: "white",
fontSize: 18,
boxShadow: "0 2px 8px rgba(0,0,0,0.25)",
cursor: "pointer",
}}
>
📷
</button>
);
};
export default ScreenshotButton;
......@@ -10,6 +10,7 @@ import {ARBottomBar} from "./ARBottomBar";
import {RoomEnvironment} from "three/examples/jsm/environments/RoomEnvironment";
import {addLightToScene, createCamera, createPlacementRing, createRenderer, setSceneBackground} from "./Setup.ts";
import ScreenshotButton from "./ScreenshotButton.tsx"; // bottom UI for selecting objects
import {ModelEmojiMap, ModelName, ModelTypeMap} from "../model/ModelType.ts"; // bottom UI for selecting objects
......@@ -139,7 +140,7 @@ export const XRRenderer: React.FC = () => {
if (name === ModelName.CUBE) {
objectToAdd = new Cube(position);
} else {
objectToAdd = new GLTFModel(`/${ModelTypeMap[name as ModelName]}/${name}.glb`, position, `/${ModelTypeMap[name as ModelName]}/colormap.png`)
objectToAdd = new GLTFModel(`/${ModelTypeMap[name as ModelName]}/${name.toLowerCase().replace(/\s/g, "")}.glb`, position, `/${ModelTypeMap[name as ModelName]}/colormap.png`)
}
const audio = new Audio('/sounds/cash.mp3');
......@@ -164,62 +165,23 @@ export const XRRenderer: React.FC = () => {
};
}, []); // empty dependency array → runs only once
// --- 🔸 Screenshot function ---
const captureAndDownload = () => {
// Get the <canvas> element from the renderer
const canvas = (mountRef.current?.querySelector("canvas") ||
document.querySelector("canvas")) as HTMLCanvasElement | null;
if (!canvas || !overlayRef.current) return;
// Hide UI overlay for a clean capture
const overlayEl = overlayRef.current;
const prevPointer = overlayEl.style.pointerEvents;
const prevOpacity = overlayEl.style.opacity;
overlayEl.style.pointerEvents = "none";
overlayEl.style.opacity = "0";
// Hide reticle (optional)
const reticle = reticleRef.current;
const prevReticleVisible = reticle?.visible ?? false;
if (reticle) reticle.visible = false;
// Wait one frame → take screenshot
requestAnimationFrame(() => {
canvas.toBlob((blob) => {
// Restore UI and reticle visibility
overlayEl.style.pointerEvents = prevPointer;
overlayEl.style.opacity = prevOpacity;
if (reticle) reticle.visible = prevReticleVisible;
if (!blob) return;
// Create download link
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
const ts = new Date().toISOString().replace(/[:.]/g, "-");
a.href = url;
a.download = `ar-snapshot-${ts}.png`;
document.body.appendChild(a);
a.click(); // trigger download
a.remove();
URL.revokeObjectURL(url);
}, "image/png");
});
};
// --- 🔸 Handle user selection from bottom bar ---
const handleSelect = (name: string) => {
setSelectedObject(name); // update state
(window as any).addSelectedObject?.(name); // add object immediately
};
const items = [];
const items: { name: string; emoji: string; }[] | { name: ModelName; emoji: string; }[] = [];
for (const key in ModelName) {
(Object.keys(ModelName) as Array<keyof typeof ModelName>).forEach((key) => {
const model = ModelName[key];
items.push({
name: ModelName[key as keyof typeof ModelName],
emoji: ModelEmojiMap[key as keyof typeof ModelEmojiMap],
name: model,
emoji: ModelEmojiMap[model],
});
}
});
console.log(items);
// --- 🔸 Render layout ---
return (
......@@ -232,26 +194,9 @@ for (const key in ModelName) {
ref={overlayRef}
style={{ position: "absolute", width: "100%", height: "100%" }}
>
{/* 📷 Screenshot button (top-right corner) */}
<button
onClick={captureAndDownload}
aria-label="Save snapshot"
style={{
position: "absolute",
top: "4rem",
right: "1.5rem",
zIndex: 1000,
padding: "10px 12px",
borderRadius: 12,
border: "none",
background: "white",
fontSize: 18,
boxShadow: "0 2px 8px rgba(0,0,0,0.25)",
cursor: "pointer",
}}
>
📷
</button>
{/* Screenshot button moved to its own component */}
<ScreenshotButton mountRef={mountRef} overlayRef={overlayRef} reticleRef={reticleRef} />
{/* Bottom bar appears only during active AR session */}
{/*{isSessionActive && (*/}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment