CoolFace
Apppublic

Reverb/open3dforge

sourceHugging Facemitupdated 4mo agoView on Hugging Face
0likes
ui_helpers.py124 linesDownload Raw Back to src
1"""2UI helpers โ€” shared functions across Gradio tabs.3 4Keeps `app.py` focused on layout, not formatting logic.5"""6 7from __future__ import annotations8 9from . import quota, workspace10 11 12def get_status_bar() -> str:13    """Build the global status bar shown at the bottom of every tab.14 15    Markdown-formatted single line with quota + workspace info.16    """17    state = workspace.get_state()18    parts = [19        quota.format_status(),20        f"๐Ÿ“ Workspace: {workspace.current_size_mb():.1f} MB",21        f"๐Ÿ“ฆ Exports: {workspace.export_count()}",22    ]23    if state.model_used:24        parts.append(f"๐Ÿ”ง Last: {state.model_used}")25    return " ยท ".join(parts)26 27 28def get_asset_summary() -> str:29    """Multi-line summary of what's currently in `workspace/current/`.30 31    Used in the viewer panel to show pipeline progress.32    """33    state = workspace.get_state()34    lines = [f"**Asset:** `{state.asset_name}`"]35 36    if state.face_count:37        lines.append(f"- Faces: {state.face_count:,}")38        lines.append(f"- Vertices: {state.vertex_count:,}")39 40    stages = []41    if state.high_poly_glb:42        stages.append("โœ“ Generated")43    if state.cleaned_glb:44        stages.append("โœ“ Cleaned")45    if state.low_poly_glb:46        stages.append("โœ“ Decimated")47    if state.unwrapped_glb:48        stages.append("โœ“ UV unwrapped")49    if state.normal_dx_png or state.normal_gl_png:50        stages.append("โœ“ Normal baked")51    if state.albedo_png:52        stages.append("โœ“ Albedo baked")53    if state.orm_png or (state.roughness_png and state.metallic_png):54        stages.append("โœ“ PBR maps")55    if state.lod_glbs:56        stages.append(f"โœ“ LODs ({len(state.lod_glbs)})")57    if state.collision_glb:58        stages.append("โœ“ Collision")59    if state.rigged_glb or state.rigged_fbx:60        stages.append("โœ“ Rigged")61 62    if stages:63        lines.append("")64        lines.append("**Progress:**")65        for s in stages:66            lines.append(f"- {s}")67    else:68        lines.append("")69        lines.append("*No asset loaded yet. Start at the Generate tab.*")70 71    return "\n".join(lines)72 73 74def get_viewer_model_path() -> str | None:75    """Pick the best GLB to show in the 3D viewer.76 77    Reads the filesystem directly so it works across the ZeroGPU subprocess78    boundary (the in-memory state written inside @spaces.GPU is invisible to79    the parent Gradio process).80    """81    from .workspace import CURRENT82    # Order: most processed โ†’ least processed83    candidates = [84        CURRENT / "rigged.glb",85        CURRENT / "scaled.glb",86        CURRENT / "pivoted.glb",87        CURRENT / "lods" / "LOD0.glb",88        CURRENT / "unwrapped.glb",89        CURRENT / "low_poly.glb",90        CURRENT / "cleaned.glb",91        CURRENT / "repaired.glb",92        CURRENT / "raw_gen.glb",93        CURRENT / "high_poly.glb",94    ]95    for path in candidates:96        if path.exists():97            return str(path)98    return None99 100 101def quota_warning(operation: str) -> str:102    """Generate a warning if an operation would exceed the daily quota.103 104    Returns an empty string if the operation fits comfortably.105    """106    estimated = quota.estimate(operation)107    state = quota.get_state()108    remaining = state.remaining_seconds()109 110    if estimated > remaining:111        overage = estimated - remaining112        cost = overage * quota.OVERAGE_RATE_PER_SECOND113        return (114            f"โš ๏ธ **Quota warning:** This will use ~{estimated}s but you only "115            f"have {remaining:.0f}s left today. "116            f"Overage cost: ~${cost:.2f}"117        )118    elif estimated > remaining * 0.5:119        return (120            f"โ„น๏ธ Estimated GPU time: ~{estimated}s "121            f"({remaining:.0f}s remaining today)"122        )123    return ""124