Fix: Clipping bug
This commit is contained in:
@@ -59,25 +59,16 @@ 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));
|
||||
function effectiveScaleForWindowSize(pack: UiSpritePack, width: number, height: number): number {
|
||||
const availableWidth = Math.max(width - WINDOW_PADDING, MIN_WINDOW_SIZE);
|
||||
const availableHeight = Math.max(height - WINDOW_PADDING, MIN_WINDOW_SIZE);
|
||||
const scaleByWidth = availableWidth / Math.max(pack.frame_width, 1);
|
||||
const scaleByHeight = availableHeight / Math.max(pack.frame_height, 1);
|
||||
const scale = Math.min(scaleByWidth, scaleByHeight);
|
||||
return Math.max(SCALE_MIN, Math.min(scale, SCALE_MAX));
|
||||
}
|
||||
|
||||
async function fitWindowForScale(pack: UiSpritePack, scale: number): Promise<void> {
|
||||
async function fitWindowForScale(pack: UiSpritePack, scale: number): Promise<number> {
|
||||
const window = getCurrentWindow();
|
||||
const [outerPosition, innerSize] = await Promise.all([window.outerPosition(), window.innerSize()]);
|
||||
const target = fittedWindowSize(pack.frame_width, pack.frame_height, scale);
|
||||
@@ -118,20 +109,24 @@ async function fitWindowForScale(pack: UiSpritePack, scale: number): Promise<voi
|
||||
|
||||
const widthChanged = Math.abs(targetWidth - innerSize.width) > SIZE_EPSILON;
|
||||
const heightChanged = Math.abs(targetHeight - innerSize.height) > SIZE_EPSILON;
|
||||
if (!widthChanged && !heightChanged) {
|
||||
return;
|
||||
if (widthChanged || heightChanged) {
|
||||
await window.setSize(new PhysicalSize(targetWidth, targetHeight));
|
||||
if (monitor !== null) {
|
||||
const minX = Math.round(monitor.workArea.position.x);
|
||||
const minY = Math.round(monitor.workArea.position.y);
|
||||
const maxX = Math.round(
|
||||
monitor.workArea.position.x + monitor.workArea.size.width - targetWidth
|
||||
);
|
||||
const maxY = Math.round(
|
||||
monitor.workArea.position.y + monitor.workArea.size.height - targetHeight
|
||||
);
|
||||
targetX = maxX < minX ? minX : Math.min(Math.max(targetX, minX), maxX);
|
||||
targetY = maxY < minY ? minY : Math.min(Math.max(targetY, minY), maxY);
|
||||
}
|
||||
await window.setPosition(new PhysicalPosition(Math.round(targetX), Math.round(targetY)));
|
||||
}
|
||||
|
||||
await window.setSize(new PhysicalSize(targetWidth, targetHeight));
|
||||
if (monitor !== null) {
|
||||
const minX = Math.round(monitor.workArea.position.x);
|
||||
const minY = Math.round(monitor.workArea.position.y);
|
||||
const maxX = Math.round(monitor.workArea.position.x + monitor.workArea.size.width - targetWidth);
|
||||
const maxY = Math.round(monitor.workArea.position.y + monitor.workArea.size.height - targetHeight);
|
||||
targetX = maxX < minX ? minX : Math.min(Math.max(targetX, minX), maxX);
|
||||
targetY = maxY < minY ? minY : Math.min(Math.max(targetY, minY), maxY);
|
||||
}
|
||||
await window.setPosition(new PhysicalPosition(Math.round(targetX), Math.round(targetY)));
|
||||
return effectiveScaleForWindowSize(pack, targetWidth, targetHeight);
|
||||
}
|
||||
|
||||
function MainOverlayWindow(): JSX.Element {
|
||||
@@ -142,7 +137,7 @@ function MainOverlayWindow(): JSX.Element {
|
||||
const rendererRef = React.useRef<PixiPetRenderer | null>(null);
|
||||
const activePackRef = React.useRef<UiSpritePack | null>(null);
|
||||
const loadedPackKeyRef = React.useRef<string | null>(null);
|
||||
const scaleFitRef = React.useRef<number | null>(null);
|
||||
const effectiveScaleSyncRef = React.useRef<number | null>(null);
|
||||
const loadingPackRef = React.useRef(false);
|
||||
const mountedRef = React.useRef(false);
|
||||
|
||||
@@ -166,16 +161,34 @@ function MainOverlayWindow(): JSX.Element {
|
||||
return true;
|
||||
};
|
||||
|
||||
const tryFitWindow = async (pack: UiSpritePack, scale: number): Promise<boolean> => {
|
||||
const tryFitWindow = async (pack: UiSpritePack, scale: number): Promise<number | null> => {
|
||||
try {
|
||||
await fitWindowForScale(pack, scale);
|
||||
scaleFitRef.current = scale;
|
||||
return true;
|
||||
return await fitWindowForScale(pack, scale);
|
||||
} catch (err) {
|
||||
if (mountedRef.current) {
|
||||
setError(String(err));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const syncEffectiveScale = async (snapshotScale: number, effectiveScale: number): Promise<void> => {
|
||||
if (Math.abs(snapshotScale - effectiveScale) < SCALE_EPSILON) {
|
||||
return;
|
||||
}
|
||||
if (
|
||||
effectiveScaleSyncRef.current !== null &&
|
||||
Math.abs(effectiveScaleSyncRef.current - effectiveScale) < SCALE_EPSILON
|
||||
) {
|
||||
return;
|
||||
}
|
||||
effectiveScaleSyncRef.current = effectiveScale;
|
||||
try {
|
||||
await invokeSetScale(effectiveScale);
|
||||
} catch (err) {
|
||||
if (mountedRef.current) {
|
||||
setError(String(err));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -183,6 +196,12 @@ function MainOverlayWindow(): JSX.Element {
|
||||
if (!mountedRef.current) {
|
||||
return;
|
||||
}
|
||||
if (
|
||||
effectiveScaleSyncRef.current !== null &&
|
||||
Math.abs(effectiveScaleSyncRef.current - value.scale) < SCALE_EPSILON
|
||||
) {
|
||||
effectiveScaleSyncRef.current = null;
|
||||
}
|
||||
setSnapshot(value);
|
||||
rendererRef.current?.applySnapshot(value);
|
||||
|
||||
@@ -196,8 +215,11 @@ function MainOverlayWindow(): JSX.Element {
|
||||
const pack = await invoke<UiSpritePack>("load_active_sprite_pack");
|
||||
reloaded = await recreateRenderer(pack, value);
|
||||
if (reloaded) {
|
||||
await tryFitWindow(pack, value.scale);
|
||||
if (mountedRef.current) {
|
||||
const effectiveScale = await tryFitWindow(pack, value.scale);
|
||||
if (effectiveScale !== null) {
|
||||
await syncEffectiveScale(value.scale, effectiveScale);
|
||||
}
|
||||
if (mountedRef.current && effectiveScale !== null) {
|
||||
setError(null);
|
||||
}
|
||||
}
|
||||
@@ -214,14 +236,11 @@ function MainOverlayWindow(): JSX.Element {
|
||||
if (activePackRef.current === null) {
|
||||
return;
|
||||
}
|
||||
if (
|
||||
scaleFitRef.current !== null &&
|
||||
Math.abs(scaleFitRef.current - value.scale) < SCALE_EPSILON
|
||||
) {
|
||||
return;
|
||||
const effectiveScale = await tryFitWindow(activePackRef.current, value.scale);
|
||||
if (effectiveScale !== null) {
|
||||
await syncEffectiveScale(value.scale, effectiveScale);
|
||||
}
|
||||
const fitApplied = await tryFitWindow(activePackRef.current, value.scale);
|
||||
if (fitApplied && mountedRef.current) {
|
||||
if (effectiveScale !== null && mountedRef.current) {
|
||||
setError(null);
|
||||
}
|
||||
};
|
||||
@@ -443,30 +462,13 @@ function SettingsWindow(): JSX.Element {
|
||||
if (!Number.isFinite(value)) {
|
||||
return;
|
||||
}
|
||||
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));
|
||||
const next = await withPending(() => invokeSetScale(value));
|
||||
if (next === null) {
|
||||
return;
|
||||
}
|
||||
setSettings((prev) => (prev === null ? prev : { ...prev, scale: next.scale }));
|
||||
},
|
||||
[activePack, withPending]
|
||||
[withPending]
|
||||
);
|
||||
|
||||
const onVisibleChange = React.useCallback(
|
||||
|
||||
Reference in New Issue
Block a user