Fix: attempt for clipping bug - not fixed yet
This commit is contained in:
@@ -25,9 +25,12 @@ type UiSpritePackOption = {
|
||||
};
|
||||
|
||||
const WINDOW_PADDING = 16;
|
||||
const WINDOW_WORKAREA_MARGIN = 80;
|
||||
const MIN_WINDOW_SIZE = 64;
|
||||
const SIZE_EPSILON = 0.5;
|
||||
const SCALE_EPSILON = 0.0001;
|
||||
const SCALE_MIN = 0.5;
|
||||
const SCALE_MAX = 3.0;
|
||||
|
||||
async function invokeSetSpritePack(packIdOrPath: string): Promise<UiSnapshot> {
|
||||
return invoke<UiSnapshot>("set_sprite_pack", { packIdOrPath });
|
||||
@@ -56,6 +59,24 @@ function fittedWindowSize(
|
||||
return { width, height };
|
||||
}
|
||||
|
||||
function maxVisibleScale(
|
||||
pack: UiSpritePack,
|
||||
workArea: { width: number; height: number }
|
||||
): number {
|
||||
const availableWidth = Math.max(
|
||||
workArea.width - WINDOW_PADDING - WINDOW_WORKAREA_MARGIN,
|
||||
MIN_WINDOW_SIZE
|
||||
);
|
||||
const availableHeight = Math.max(
|
||||
workArea.height - WINDOW_PADDING - WINDOW_WORKAREA_MARGIN,
|
||||
MIN_WINDOW_SIZE
|
||||
);
|
||||
const maxByWidth = availableWidth / Math.max(pack.frame_width, 1);
|
||||
const maxByHeight = availableHeight / Math.max(pack.frame_height, 1);
|
||||
const cap = Math.min(maxByWidth, maxByHeight);
|
||||
return Math.max(SCALE_MIN, Math.min(cap, SCALE_MAX));
|
||||
}
|
||||
|
||||
async function fitWindowForScale(pack: UiSpritePack, scale: number): Promise<void> {
|
||||
const window = getCurrentWindow();
|
||||
const [outerPosition, innerSize] = await Promise.all([window.outerPosition(), window.innerSize()]);
|
||||
@@ -81,8 +102,16 @@ async function fitWindowForScale(pack: UiSpritePack, scale: number): Promise<voi
|
||||
}
|
||||
|
||||
if (monitor !== null) {
|
||||
targetWidth = Math.min(targetWidth, monitor.workArea.size.width);
|
||||
targetHeight = Math.min(targetHeight, monitor.workArea.size.height);
|
||||
const widthCap = Math.max(
|
||||
monitor.workArea.size.width - WINDOW_WORKAREA_MARGIN,
|
||||
MIN_WINDOW_SIZE
|
||||
);
|
||||
const heightCap = Math.max(
|
||||
monitor.workArea.size.height - WINDOW_WORKAREA_MARGIN,
|
||||
MIN_WINDOW_SIZE
|
||||
);
|
||||
targetWidth = Math.min(targetWidth, widthCap);
|
||||
targetHeight = Math.min(targetHeight, heightCap);
|
||||
targetX = centerX - targetWidth / 2;
|
||||
targetY = centerY - targetHeight / 2;
|
||||
}
|
||||
@@ -311,6 +340,7 @@ function MainOverlayWindow(): JSX.Element {
|
||||
function SettingsWindow(): JSX.Element {
|
||||
const [settings, setSettings] = React.useState<UiSettingsSnapshot | null>(null);
|
||||
const [packs, setPacks] = React.useState<UiSpritePackOption[]>([]);
|
||||
const [activePack, setActivePack] = React.useState<UiSpritePack | null>(null);
|
||||
const [error, setError] = React.useState<string | null>(null);
|
||||
const [pending, setPending] = React.useState(false);
|
||||
|
||||
@@ -319,19 +349,32 @@ function SettingsWindow(): JSX.Element {
|
||||
let mounted = true;
|
||||
Promise.all([
|
||||
invoke<UiSettingsSnapshot>("settings_snapshot"),
|
||||
invoke<UiSpritePackOption[]>("list_sprite_packs")
|
||||
invoke<UiSpritePackOption[]>("list_sprite_packs"),
|
||||
invoke<UiSpritePack>("load_active_sprite_pack")
|
||||
])
|
||||
.then(async ([snapshot, options]) => {
|
||||
.then(async ([snapshot, options, pack]) => {
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
setSettings(snapshot);
|
||||
setPacks(options);
|
||||
setActivePack(pack);
|
||||
unlisten = await listen<UiSnapshot>("runtime:snapshot", (event) => {
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
const payload = event.payload;
|
||||
if (payload.active_sprite_pack !== activePack?.id) {
|
||||
void invoke<UiSpritePack>("load_active_sprite_pack")
|
||||
.then((nextPack) => {
|
||||
if (mounted) {
|
||||
setActivePack(nextPack);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
// Keep existing pack metadata if reload fails.
|
||||
});
|
||||
}
|
||||
setSettings((prev) => {
|
||||
if (prev === null) {
|
||||
return prev;
|
||||
@@ -356,7 +399,7 @@ function SettingsWindow(): JSX.Element {
|
||||
unlisten();
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
}, [activePack?.id]);
|
||||
|
||||
const withPending = React.useCallback(async <T,>(fn: () => Promise<T>): Promise<T | null> => {
|
||||
setPending(true);
|
||||
@@ -378,6 +421,10 @@ function SettingsWindow(): JSX.Element {
|
||||
if (next === null) {
|
||||
return;
|
||||
}
|
||||
const refreshedPack = await withPending(() => invoke<UiSpritePack>("load_active_sprite_pack"));
|
||||
if (refreshedPack !== null) {
|
||||
setActivePack(refreshedPack);
|
||||
}
|
||||
setSettings((prev) =>
|
||||
prev === null
|
||||
? prev
|
||||
@@ -396,13 +443,30 @@ function SettingsWindow(): JSX.Element {
|
||||
if (!Number.isFinite(value)) {
|
||||
return;
|
||||
}
|
||||
const next = await withPending(() => invokeSetScale(value));
|
||||
let effectiveScale = value;
|
||||
if (activePack !== null) {
|
||||
try {
|
||||
const monitor = await currentMonitor();
|
||||
if (monitor !== null) {
|
||||
effectiveScale = Math.min(
|
||||
value,
|
||||
maxVisibleScale(activePack, {
|
||||
width: monitor.workArea.size.width,
|
||||
height: monitor.workArea.size.height
|
||||
})
|
||||
);
|
||||
}
|
||||
} catch {
|
||||
// Keep requested value if monitor query fails.
|
||||
}
|
||||
}
|
||||
const next = await withPending(() => invokeSetScale(effectiveScale));
|
||||
if (next === null) {
|
||||
return;
|
||||
}
|
||||
setSettings((prev) => (prev === null ? prev : { ...prev, scale: next.scale }));
|
||||
},
|
||||
[withPending]
|
||||
[activePack, withPending]
|
||||
);
|
||||
|
||||
const onVisibleChange = React.useCallback(
|
||||
@@ -457,8 +521,8 @@ function SettingsWindow(): JSX.Element {
|
||||
<span>Scale: {settings.scale.toFixed(2)}x</span>
|
||||
<input
|
||||
type="range"
|
||||
min={0.5}
|
||||
max={3.0}
|
||||
min={SCALE_MIN}
|
||||
max={SCALE_MAX}
|
||||
step={0.05}
|
||||
value={settings.scale}
|
||||
disabled={pending}
|
||||
|
||||
Reference in New Issue
Block a user