mirror of
https://github.com/exogen/t2-mapper.git
synced 2026-04-27 07:15:46 +00:00
add fog URL param
This commit is contained in:
parent
d7ef09c576
commit
c380893040
27 changed files with 100 additions and 43 deletions
|
|
@ -2,6 +2,7 @@ import { RefObject, useCallback, useRef, useState } from "react";
|
|||
import { FaMapPin } from "react-icons/fa";
|
||||
import { FaClipboardCheck } from "react-icons/fa6";
|
||||
import { Camera, Quaternion, Vector3 } from "three";
|
||||
import { useSettings } from "./SettingsProvider";
|
||||
|
||||
function encodeViewHash({
|
||||
position,
|
||||
|
|
@ -18,9 +19,14 @@ function encodeViewHash({
|
|||
|
||||
export function CopyCoordinatesButton({
|
||||
cameraRef,
|
||||
missionName,
|
||||
missionType,
|
||||
}: {
|
||||
cameraRef: RefObject<Camera | null>;
|
||||
missionName: string;
|
||||
missionType: string;
|
||||
}) {
|
||||
const { fogEnabled } = useSettings();
|
||||
const [showCopied, setShowCopied] = useState(false);
|
||||
const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
|
||||
|
|
@ -29,8 +35,10 @@ export function CopyCoordinatesButton({
|
|||
const camera = cameraRef.current;
|
||||
if (!camera) return;
|
||||
const hash = encodeViewHash(camera);
|
||||
// Update the URL hash
|
||||
const fullPath = `${window.location.pathname}${window.location.search}${hash}`;
|
||||
const params = new URLSearchParams();
|
||||
params.set("mission", `${missionName}~${missionType}`);
|
||||
params.set("fog", fogEnabled.toString());
|
||||
const fullPath = `${window.location.pathname}?${params}${hash}`;
|
||||
const fullUrl = `${window.location.origin}${fullPath}`;
|
||||
window.history.replaceState(null, "", fullPath);
|
||||
try {
|
||||
|
|
@ -42,7 +50,7 @@ export function CopyCoordinatesButton({
|
|||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}, [cameraRef]);
|
||||
}, [cameraRef, missionName, missionType, fogEnabled]);
|
||||
|
||||
return (
|
||||
<button
|
||||
|
|
|
|||
|
|
@ -73,7 +73,11 @@ export function InspectorControls({
|
|||
const settingsFields = (
|
||||
<>
|
||||
<div className="Controls-group">
|
||||
<CopyCoordinatesButton cameraRef={cameraRef} />
|
||||
<CopyCoordinatesButton
|
||||
cameraRef={cameraRef}
|
||||
missionName={missionName}
|
||||
missionType={missionType}
|
||||
/>
|
||||
</div>
|
||||
<div className="Controls-group">
|
||||
<div className="CheckboxField">
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import {
|
||||
createContext,
|
||||
ReactNode,
|
||||
useCallback,
|
||||
useContext,
|
||||
useEffect,
|
||||
useLayoutEffect,
|
||||
|
|
@ -65,7 +66,15 @@ export function useControls() {
|
|||
return useContext(ControlsContext);
|
||||
}
|
||||
|
||||
export function SettingsProvider({ children }: { children: ReactNode }) {
|
||||
export function SettingsProvider({
|
||||
children,
|
||||
fogEnabledOverride,
|
||||
onClearFogEnabledOverride,
|
||||
}: {
|
||||
children: ReactNode;
|
||||
fogEnabledOverride?: boolean | null;
|
||||
onClearFogEnabledOverride: () => void;
|
||||
}) {
|
||||
const [fogEnabled, setFogEnabled] = useState(true);
|
||||
const [highQualityFog, setHighQualityFog] = useState(false);
|
||||
const [speedMultiplier, setSpeedMultiplier] = useState(1);
|
||||
|
|
@ -75,10 +84,18 @@ export function SettingsProvider({ children }: { children: ReactNode }) {
|
|||
const [debugMode, setDebugMode] = useState(false);
|
||||
const [touchMode, setTouchMode] = useState<TouchMode>("moveLookStick");
|
||||
|
||||
const setFogEnabledWithoutOverride: StateSetter<boolean> = useCallback(
|
||||
(value) => {
|
||||
setFogEnabled(value);
|
||||
onClearFogEnabledOverride();
|
||||
},
|
||||
[onClearFogEnabledOverride],
|
||||
);
|
||||
|
||||
const settingsContext: SettingsContext = useMemo(
|
||||
() => ({
|
||||
fogEnabled,
|
||||
setFogEnabled,
|
||||
fogEnabled: fogEnabledOverride ?? fogEnabled,
|
||||
setFogEnabled: setFogEnabledWithoutOverride,
|
||||
highQualityFog,
|
||||
setHighQualityFog,
|
||||
fov,
|
||||
|
|
@ -88,7 +105,15 @@ export function SettingsProvider({ children }: { children: ReactNode }) {
|
|||
animationEnabled,
|
||||
setAnimationEnabled,
|
||||
}),
|
||||
[fogEnabled, highQualityFog, fov, audioEnabled, animationEnabled],
|
||||
[
|
||||
fogEnabled,
|
||||
fogEnabledOverride,
|
||||
setFogEnabledWithoutOverride,
|
||||
highQualityFog,
|
||||
fov,
|
||||
audioEnabled,
|
||||
animationEnabled,
|
||||
],
|
||||
);
|
||||
|
||||
const debugContext: DebugContext = useMemo(
|
||||
|
|
@ -144,7 +169,7 @@ export function SettingsProvider({ children }: { children: ReactNode }) {
|
|||
clearTimeout(saveTimerRef.current);
|
||||
}
|
||||
|
||||
// Debounce localStorage writes (wait 300ms after last change)
|
||||
// Debounce localStorage writes
|
||||
saveTimerRef.current = setTimeout(() => {
|
||||
const settingsToSave: PersistedSettings = {
|
||||
fogEnabled,
|
||||
|
|
|
|||
|
|
@ -1,24 +1,32 @@
|
|||
import { useEffect, useState } from "react";
|
||||
import { useCallback, useRef, useSyncExternalStore } from "react";
|
||||
|
||||
// Only check pointer: coarse. Adding "hover: none" would be more precise but
|
||||
// Samsung Android devices incorrectly report hover: hover for touchscreens.
|
||||
// See: https://www.ctrl.blog/entry/css-media-hover-samsung.html
|
||||
const query = "(pointer: coarse)";
|
||||
const getServerSnapshot = () => null;
|
||||
|
||||
export function useTouchDevice() {
|
||||
const [isTouch, setIsTouch] = useState<boolean | null>(null);
|
||||
const queryRef = useRef<ReturnType<typeof window.matchMedia>>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const subscribe = useCallback((onStoreChange: () => void) => {
|
||||
const mql = window.matchMedia(query);
|
||||
setIsTouch(mql.matches);
|
||||
const handleChange = (e: MediaQueryListEvent) => {
|
||||
setIsTouch(e.matches);
|
||||
};
|
||||
mql.addEventListener("change", handleChange);
|
||||
mql.addEventListener("change", onStoreChange);
|
||||
queryRef.current = mql;
|
||||
return () => {
|
||||
mql.removeEventListener("change", handleChange);
|
||||
mql.removeEventListener("change", onStoreChange);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const getSnapshot = useCallback(() => {
|
||||
return queryRef.current.matches;
|
||||
}, []);
|
||||
|
||||
const isTouch = useSyncExternalStore<boolean | null>(
|
||||
subscribe,
|
||||
getSnapshot,
|
||||
getServerSnapshot,
|
||||
);
|
||||
|
||||
return isTouch;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue