From eb3dbf321aa06c69885789c53a3b5567e69c669e Mon Sep 17 00:00:00 2001 From: Andres Tobio <92232669+AndrewUru@users.noreply.github.com> Date: Wed, 4 Nov 2026 22:33:54 +0100 Subject: [PATCH 1/7] feat(windows): add desktop Gradio launcher with pywebview --- desktop.py | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 desktop.py diff --git a/desktop.py b/desktop.py new file mode 100644 index 0000000..5640398 --- /dev/null +++ b/desktop.py @@ -0,0 +1,58 @@ +"""Desktop entrypoint: local Gradio server displayed in a native window.""" +import os +import sys +import traceback +import webbrowser + +os.environ.setdefault("GRADIO_ANALYTICS_ENABLED", "False") + +from app import CSS, create_app +from imagen3d.storage import start_cleaner + + +def main(): + import gradio as gr + import uvicorn + + start_cleaner() + demo = create_app().queue(max_size=16) + uvicorn.Config(app=demo.app, log_level="warning").load() + try: + demo.launch( + server_name="127.0.0.1", + server_port=7860, + share=False, + inbrowser=False, + prevent_thread_lock=True, + max_file_size="15mb", + theme=gr.themes.Soft(primary_hue="cyan", neutral_hue="slate"), + css=CSS, + ) + url = demo.local_url or "http://127.0.0.1:7860" + try: + import webview + webview.create_window("3D Creator Studio", url, width=1360, height=900, + min_size=(850, 600)) + webview.start() + except Exception as exc: + print(f"No se pudo abrir la ventana nativa: {exc}", file=sys.stderr) + print(f"Abriendo la interfaz en el navegador: {url}") + webbrowser.open(url) + input("Pulsa Intro para detener el servidor... ") + finally: + demo.close() + + +if __name__ == "__main__": + try: + if "--check" in sys.argv: + import trimesh + instance = create_app() + assert instance is not None + print("OK: dependencias e interfaz cargadas.") + else: + main() + except Exception: + traceback.print_exc() + input("Error al arrancar. Pulsa Intro para salir... ") + sys.exit(1) From be41e4dd1c8bfc4ebf9e0339f23bafb09fc1dbcf Mon Sep 17 00:00:00 2001 From: Andres Tobio <92232669+AndrewUru@users.noreply.github.com> Date: Wed, 4 Nov 2026 22:33:58 +0100 Subject: [PATCH 2/7] build: pin Windows desktop packaging tools --- requirements-desktop.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 requirements-desktop.txt diff --git a/requirements-desktop.txt b/requirements-desktop.txt new file mode 100644 index 0000000..14d8696 --- /dev/null +++ b/requirements-desktop.txt @@ -0,0 +1,2 @@ +pyinstaller==6.16.0 +pywebview==6.1 From dece7eb6bd6b538b2ce088391e38de49546ef429 Mon Sep 17 00:00:00 2001 From: Andres Tobio <92232669+AndrewUru@users.noreply.github.com> Date: Wed, 4 Nov 2026 22:34:21 +0100 Subject: [PATCH 3/7] build(windows): add portable packaging automation --- scripts/build_windows.ps1 | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 scripts/build_windows.ps1 diff --git a/scripts/build_windows.ps1 b/scripts/build_windows.ps1 new file mode 100644 index 0000000..cc8a47e --- /dev/null +++ b/scripts/build_windows.ps1 @@ -0,0 +1,12 @@ +$ErrorActionPreference = "Stop" +Set-Location (Resolve-Path (Join-Path $PSScriptRoot "..")) +$python = Join-Path (Get-Location) ".venv\Scripts\python.exe" +if (-not (Test-Path $python)) { throw "Falta .venv. Ejecuta: py -3.12 -m venv .venv" } +& $python -m pip install -r requirements.txt -r requirements-desktop.txt +if ($LASTEXITCODE -ne 0) { throw "Fallo la instalacion" } +$flags = @("--noconfirm", "--clean", "--onedir", "--console", "--name", "3D-Creator", "--collect-all", "gradio", "--collect-all", "gradio_client", "--collect-all", "trimesh", "--collect-all", "shapely", "--collect-all", "cv2", "--collect-all", "manifold3d", "--collect-submodules", "webview", "--hidden-import=uvicorn.protocols.http.auto", "--hidden-import=uvicorn.lifespan.on", "desktop.py") +& $python -m PyInstaller @flags +if ($LASTEXITCODE -ne 0) { throw "Fallo la compilacion" } +& ".\dist\3D-Creator\3D-Creator.exe" --check +if ($LASTEXITCODE -ne 0) { throw "Fallo la comprobacion del ejecutable" } +Write-Host "Compilado: dist\3D-Creator\3D-Creator.exe" From 2d9c2cb36d2a07156765594966c4915b8248a9d6 Mon Sep 17 00:00:00 2001 From: Andres Tobio <92232669+AndrewUru@users.noreply.github.com> Date: Wed, 4 Nov 2026 22:34:23 +0100 Subject: [PATCH 4/7] build(windows): add portable packaging automation --- .github/workflows/windows-portable.yml | 45 ++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 .github/workflows/windows-portable.yml diff --git a/.github/workflows/windows-portable.yml b/.github/workflows/windows-portable.yml new file mode 100644 index 0000000..c616b27 --- /dev/null +++ b/.github/workflows/windows-portable.yml @@ -0,0 +1,45 @@ +name: Windows portable EXE + +on: + workflow_dispatch: + push: + branches: [main] + paths: + - "desktop.py" + - "app.py" + - "imagen3d/**" + - "requirements*.txt" + - "scripts/build_windows.ps1" + - ".github/workflows/windows-portable.yml" + +jobs: + windows-build: + runs-on: windows-latest + permissions: + contents: read + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.12" + architecture: x64 + cache: pip + cache-dependency-path: | + requirements.txt + requirements-desktop.txt + - name: Create Python environment + shell: pwsh + run: py -3.12 -m venv .venv + - name: Build portable app + shell: pwsh + run: ./scripts/build_windows.ps1 + - name: Archive portable folder + shell: pwsh + run: Compress-Archive -Path "dist/3D-Creator" -DestinationPath "3D-Creator-Windows-x64.zip" + - name: Upload executable bundle + uses: actions/upload-artifact@v4 + with: + name: 3D-Creator-Windows-x64 + path: 3D-Creator-Windows-x64.zip + if-no-files-found: error + retention-days: 14 From 4485ebd6e7171ca681edb13de429c16c536b94d2 Mon Sep 17 00:00:00 2001 From: Andres Tobio <92232669+AndrewUru@users.noreply.github.com> Date: Wed, 4 Nov 2026 22:34:39 +0100 Subject: [PATCH 5/7] docs: document portable EXE build, usage and AI limitations --- docs/WINDOWS.md | 52 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 docs/WINDOWS.md diff --git a/docs/WINDOWS.md b/docs/WINDOWS.md new file mode 100644 index 0000000..b902644 --- /dev/null +++ b/docs/WINDOWS.md @@ -0,0 +1,52 @@ +# Ejecutable portable de Windows + +Esta es una **versión preliminar** del empaquetado de 3D Creator Studio. +No se han cambiado los motores de generación ni el flujo Python habitual. + +## Descargar la compilación + +Abre la pestaña **Actions** de GitHub, selecciona **Windows portable EXE** +y ejecuta **Run workflow** sobre la rama `feat/windows-portable-exe`. +Cuando termine correctamente, descarga el artefacto +`3D-Creator-Windows-x64`. Extrae el ZIP y abre +`3D-Creator/3D-Creator.exe`. + +**Conserva toda la carpeta**, incluido `_internal`; el ejecutable no +funciona si se separa de sus dependencias. + +## Compilar en Windows 10/11 + +Requiere Python 3.12 de 64 bits para compilar: + +```powershell +py -3.12 -m venv .venv +.\scripts\build_windows.ps1 +``` + +El resultado queda en `dist/3D-Creator/3D-Creator.exe`. +El script comprueba que el EXE puede importar las dependencias y construir +la interfaz, pero se debe realizar además una prueba manual de la ventana, +el visor 3D y las exportaciones STL/GLB en Windows. + +## Comportamiento + +- Gradio escucha únicamente en `127.0.0.1:7860`, sin enlaces públicos. +- pywebview muestra la interfaz en una ventana propia usando WebView2. +- Si pywebview falla, intenta abrir el navegador predeterminado. +- Cerrar la ventana nativa detiene el servidor. Con el navegador alternativo, + pulsa Intro en la consola para terminar. +- La consola permanece visible durante esta fase para facilitar diagnósticos. +- Si el puerto 7860 está ocupado, cierra la otra instancia. +- Windows puede requerir WebView2 y mostrar avisos para EXE sin firma. + +## Limitaciones expresas + +Las modalidades que no necesitan IA local (extrusión de siluetas y relieve desde +mapa de alturas) son el objetivo de este primer empaquetado. **TripoSR y Depth +Anything V2 no están incluidos**. Requieren entornos Python y pesos externos +en rutas concretas, por lo que no se garantiza que funcionen dentro del ZIP. +Para esas dos modalidades, sigue usando la instalación Python del README. + +Esto no es todavía un instalador MSI, una aplicación firmada ni un sistema +de actualizaciones automáticas. Tampoco incorpora todavía el editor de mallas +interactivo; es un empaquetado de las funciones existentes. From 030e25a408d0efad9087252f82c5c33b81928209 Mon Sep 17 00:00:00 2001 From: Andres Tobio <92232669+AndrewUru@users.noreply.github.com> Date: Wed, 4 Nov 2026 22:34:52 +0100 Subject: [PATCH 6/7] build: ignore PyInstaller outputs --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 8e39757..b5fcc5c 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,6 @@ __pycache__/ *.pyc *.log artifacts/ +build/ +dist/ +*.spec From 5f2581d70f0b67b8d031b939e2775d63ae013941 Mon Sep 17 00:00:00 2001 From: Andres Tobio <92232669+AndrewUru@users.noreply.github.com> Date: Wed, 4 Nov 2026 22:35:21 +0100 Subject: [PATCH 7/7] ci: build Windows executable on pull requests for verification --- .github/workflows/windows-portable.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/windows-portable.yml b/.github/workflows/windows-portable.yml index c616b27..748a27d 100644 --- a/.github/workflows/windows-portable.yml +++ b/.github/workflows/windows-portable.yml @@ -2,6 +2,8 @@ name: Windows portable EXE on: workflow_dispatch: + pull_request: + branches: [main] push: branches: [main] paths: