fix: keep generated CAD models in frame

This commit is contained in:
134 2026-07-13 19:46:43 +08:00
parent 43837e5048
commit a9390f0abc
3 changed files with 83 additions and 0 deletions

View File

@ -121,6 +121,10 @@ function patchOfficialSource() {
path.join(customizationDir, "localization.ts"),
path.join(sourceDir, "src/lib/hicadLocalization.ts")
);
copyFileSync(
path.join(customizationDir, "FitAllButton.tsx.template"),
path.join(sourceDir, "src/components/FitAllButton.tsx")
);
replaceSource(
"index.html",
' <meta name="description" content="An open-source CAD modeling tool from the future by Zoo." />',
@ -226,6 +230,51 @@ function patchOfficialSource() {
"function launchApp(app: App) {\n initSingletonBehavior(app)",
"function launchApp(app: App) {\n installHiCadLocalization()\n initSingletonBehavior(app)"
);
replaceSource(
"src/registry/extensions/engineScene/viewExtensionControls.tsx",
"import { CustomIcon } from '@src/components/CustomIcon'\n",
"import { CustomIcon } from '@src/components/CustomIcon'\nimport { FitAllButton } from '@src/components/FitAllButton'\n"
);
replaceSource(
"src/registry/extensions/engineScene/viewExtensionControls.tsx",
` <Suspense fallback={null}>\n <Gizmo />\n </Suspense>`,
` <Suspense fallback={null}>\n <div className="flex items-end gap-2">\n <FitAllButton />\n <Gizmo />\n </div>\n </Suspense>`
);
replaceSource(
"src/lib/resetCameraPosition.ts",
` // We need a padding of 0.1 for zoom_to_fit for all E2E tests since they were originally\n // written with zoom_to_fit with padding 0.1\n const padding = 0.1\n if (isPlaywright()) {`,
` // Keep the official E2E framing stable while giving HiCAD users enough\n // breathing room to see the complete model after generation and file loads.\n const padding = isPlaywright() ? 0.1 : 0.35\n if (isPlaywright()) {`
);
replaceSource(
"src/lib/commandBarConfigs/standardViewsConfig.ts",
"engineStreamZoomToFit({ engineCommandManager, padding: 0.1 })",
"engineStreamZoomToFit({ engineCommandManager, padding: 0.35 })"
);
replaceSource(
"src/lib/app.ts",
" padding: 0.2,\n animated: false,",
" padding: 0.35,\n animated: false,"
);
replaceSource(
"src/clientSideScene/ClientSideSceneComp.tsx",
"import { throttle, toSync } from '@src/lib/utils'",
`import {\n engineStreamZoomToFit,\n throttle,\n toSync,\n} from '@src/lib/utils'`
);
replaceSource(
"src/clientSideScene/ClientSideSceneComp.tsx",
` const {\n kclManager: { sceneEntitiesManager, sceneInfra, engineCommandManager },\n } = useSingletons()`,
` const { kclManager } = useSingletons()\n const { sceneEntitiesManager, sceneInfra, engineCommandManager } = kclManager`
);
replaceSource(
"src/clientSideScene/ClientSideSceneComp.tsx",
` // Detect canvas size changes\n const observer = new ResizeObserver(() => {\n // This is called initially too, not just on resize\n sceneInfra.onCanvasResized()\n sceneInfra.camControls.onWindowResize()\n sceneEntitiesManager.onCamChange().catch(reportRejection)\n })\n observer.observe(container)`,
` // Preserve the full-model framing when panels or the browser resize.\n let fitAfterResizeTimer: ReturnType<typeof setTimeout> | undefined\n const observer = new ResizeObserver(() => {\n // This is called initially too, not just on resize\n sceneInfra.onCanvasResized()\n sceneInfra.camControls.onWindowResize()\n sceneEntitiesManager.onCamChange().catch(reportRejection)\n\n clearTimeout(fitAfterResizeTimer)\n fitAfterResizeTimer = setTimeout(() => {\n if (kclManager.artifactGraph.size === 0) return\n engineStreamZoomToFit({\n engineCommandManager,\n padding: 0.35,\n }).catch(reportRejection)\n }, 180)\n })\n observer.observe(container)`
);
replaceSource(
"src/clientSideScene/ClientSideSceneComp.tsx",
` observer.disconnect()\n media.removeEventListener('change', handleChange)`,
` observer.disconnect()\n clearTimeout(fitAfterResizeTimer)\n media.removeEventListener('change', handleChange)`
);
replaceSource(
"src/routes/Onboarding/utils.tsx",
` <p className="m-0 text-center text-xs italic text-chalkboard-70 dark:text-chalkboard-30">

View File

@ -0,0 +1,32 @@
import { CustomIcon } from '@src/components/CustomIcon'
import Tooltip from '@src/components/Tooltip'
import { useSingletons } from '@src/lib/boot'
import { reportRejection } from '@src/lib/trap'
import { engineStreamZoomToFit } from '@src/lib/utils'
export const HICAD_CAMERA_FIT_PADDING = 0.35
export function FitAllButton() {
const { kclManager } = useSingletons()
return (
<button
type="button"
data-testid="hicad-fit-all-model"
aria-label="Fit all model"
onClick={() => {
engineStreamZoomToFit({
engineCommandManager: kclManager.engineCommandManager,
padding: HICAD_CAMERA_FIT_PADDING,
}).catch(reportRejection)
}}
className="group/fit relative pointer-events-auto grid h-8 w-8 shrink-0 place-items-center rounded-sm border border-chalkboard-20 bg-chalkboard-10/90 p-0 text-chalkboard-80 shadow-sm backdrop-blur-sm hover:border-primary hover:text-primary dark:border-chalkboard-80 dark:bg-chalkboard-100/90 dark:text-chalkboard-20 dark:hover:border-primary dark:hover:text-primary"
>
<CustomIcon name="scale" className="h-4 w-4" />
<span className="sr-only">Fit all model</span>
<Tooltip position="top-right" hoverOnly={true}>
Fit all model
</Tooltip>
</button>
)
}

View File

@ -35,6 +35,7 @@ const translations = new Map<string, string>([
['Export part', '导出零件'],
['Extrude', '拉伸'],
['Feature Tree', '特征树'],
['Fit all model', '显示全部模型'],
['Fillet', '圆角'],
['Flip Surface', '翻转曲面'],
['Front plane', '前视基准面'],
@ -102,6 +103,7 @@ const translations = new Map<string, string>([
'HiCAD AI 可能出错。我们会发送选区上下文以提高准确性,请始终核对结果。',
],
['Zoom to fit', '缩放至合适大小'],
['Reset view', '重置视图'],
['loading', '加载中'],
['zoo.dev', 'HiCAD 云端'],
])