diff --git a/.github/workflows/site.yml b/.github/workflows/site.yml new file mode 100644 index 0000000..241bf9e --- /dev/null +++ b/.github/workflows/site.yml @@ -0,0 +1,43 @@ +# Deploy the static marketing site (site/) to GitHub Pages at +# render.preshow.link — same mechanism as UV Studio's uv.preshow.link. +# +# The deploy is OPT-IN — it only runs when the repo variable +# DEPLOY_PAGES == 'true'. To enable it (needs a public repo OR a plan with +# private Pages, e.g. Pro): +# repo Settings → Pages → Source: "GitHub Actions" +# gh variable set DEPLOY_PAGES --body true +# Then add a DNS CNAME record: render.preshow.link → hayhamlt.github.io +# The custom domain is baked in via the CNAME file below, so the site is +# served at root — no subpath rewrites needed. +name: Site + +on: + push: + branches: [main] + paths: ['site/**', '.github/workflows/site.yml'] + workflow_dispatch: + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: pages + cancel-in-progress: true + +jobs: + deploy: + if: ${{ vars.DEPLOY_PAGES == 'true' }} + runs-on: ubuntu-latest + environment: + name: github-pages + url: ${{ steps.deploy.outputs.page_url }} + steps: + - uses: actions/checkout@v4 + - run: echo 'render.preshow.link' > site/CNAME + - uses: actions/upload-pages-artifact@v3 + with: + path: site + - id: deploy + uses: actions/deploy-pages@v4 diff --git a/README.md b/README.md index 1d5db12..0c57701 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,12 @@ -# Render Mapper Pro +# PrevizRender (formerly Render Mapper Pro) A standalone desktop app that maps videos onto 3D‑scene materials and renders them headlessly — built for LED‑wall / screen‑content workflows where one scene drives many video surfaces. +PrevizRender is one of three sibling tools built by [hamLT](https://motion.hamlt.com) and powered by [Toy Robot Media](https://toyrobotmedia.com): **[Preshow.link](https://www.preshow.link)** plans and previzes the show, **[UV Studio](https://uv.preshow.link)** maps artwork onto the venue's screens, and **PrevizRender** renders the comps locally. Product site: **[render.preshow.link](https://render.preshow.link)** (deployed from [`site/`](site/) via GitHub Pages, same as UV Studio's). (Installer and bundle artifacts keep the `RenderMapperPro` name so auto-updates and install paths stay valid.) + It supports **two render backends**, chosen automatically by scene type: **Blender** (`.blend`, `.fbx`, `.usd`, …) and **Cinema 4D + Redshift** (`.c4d`). It runs the renderer in the background, so a renderer crash can never take down the app, and ships bundled static `ffmpeg`/`ffprobe` so audio muxing and clip probing work out of the box. -![Render Mapper Pro](docs/screenshots/render-mapper-pro.png) +![PrevizRender](docs/screenshots/previzrender.png) ## Download diff --git a/app_qt.py b/app_qt.py index 57134d6..9bb2de9 100644 --- a/app_qt.py +++ b/app_qt.py @@ -302,7 +302,7 @@ def __init__(self) -> None: self._c4dpy_path = _find_c4dpy() # Cinema 4D headless Python, if installed self._deadline_repo_path = "" self._deadline_command_path = "" - self._deadline_job_name_template = "Render Mapper Pro Job - {scene_name}" + self._deadline_job_name_template = f"{APP_NAME} Job - {{scene_name}}" self._deadline_comment = "" self._discovered_materials: list[str] = [] self._discovered_cameras: list[str] = [] @@ -728,7 +728,7 @@ def _guide_sections() -> list[tuple[str, str]]: return [ ("Getting Started", """

Welcome

-

Render Mapper Pro maps your videos onto a 3D scene's +

PrevizRender maps your videos onto a 3D scene's materials and renders them — on your machine or a render farm. Each tab above covers one part of the app; here's the whole flow first.

@@ -1341,13 +1341,23 @@ def centered(w): name = centered(QLabel(APP_NAME)) name.setStyleSheet(f"color:{pal.text}; font-size:19px; font-weight:700; margin-top:8px;") - ver = centered(QLabel(f"Version {APP_VERSION}")) + ver = centered(QLabel(f"Version {APP_VERSION} · formerly Render Mapper Pro")) ver.setStyleSheet(f"color:{pal.text_muted}; font-size:12px;") desc = centered(QLabel("Automated video-texture mapping and headless\n" "rendering — Blender, Cinema 4D and three.js.")) desc.setStyleSheet(f"color:{pal.text_muted}; font-size:12px; margin-top:8px;") desc.setWordWrap(True) + family = centered(QLabel( + 'Sibling apps: ' + f'Preshow.link for show previz · ' + f'UV Studio for screen UVs')) + family.setStyleSheet(f"color:{pal.text_muted}; font-size:12px; margin-top:4px;") + family.setOpenExternalLinks(True) + family.setTextInteractionFlags(Qt.TextInteractionFlag.TextBrowserInteraction) + sep = QFrame() sep.setFrameShape(QFrame.Shape.HLine) sep.setStyleSheet(f"color:{pal.border}; margin:14px 40px;") @@ -2737,7 +2747,7 @@ def _job_engine(j: RenderJob) -> str: error( self, "App Component Missing", "The app's render component couldn't be found — the installation may be " - f"damaged. Reinstall Render Mapper Pro.\n\nDetails: {exc}") + f"damaged. Reinstall {APP_NAME}.\n\nDetails: {exc}") self._is_rendering = False return # Bundled ffmpeg path for the workers: C4D always muxes its movie with it, @@ -3456,8 +3466,8 @@ def _open_path(path: str) -> None: # ── Project save/open ──────────────────────────────────────────────── def _save_project(self) -> None: p, _ = QFileDialog.getSaveFileName( - self, "Save Project", str(Path.home() / f"render_mapper_project{PROJECT_EXT}"), - f"Render Mapper Project (*{PROJECT_EXT})") + self, "Save Project", str(Path.home() / f"previzrender_project{PROJECT_EXT}"), + f"PrevizRender Project (*{PROJECT_EXT})") if not p: return if not p.lower().endswith(PROJECT_EXT): @@ -3475,7 +3485,7 @@ def _save_project(self) -> None: def _open_project(self) -> None: p, _ = QFileDialog.getOpenFileName( self, "Open Project", str(Path.home()), - f"Render Mapper Project (*{PROJECT_EXT})") + f"PrevizRender Project (*{PROJECT_EXT})") if not p: return try: @@ -3584,7 +3594,7 @@ def _send_test() -> None: if not self._discord_webhook: self._show_toast("Enter a webhook URL first.", "warning") return - self._dispatch_discord("✅ Test notification from Render Mapper Pro") + self._dispatch_discord(f"✅ Test notification from {APP_NAME}") self._show_toast("Test sent — check Discord (and Live Logs for errors).", "info") test_btn.clicked.connect(_send_test) @@ -3981,9 +3991,9 @@ def _apply_profile_data(self, d: dict) -> None: self.deadline_panel.dl_chunk_spin.setValue(int(d.get("deadline_chunk_size", 1))) self.deadline_panel.dl_suspended_cb.setChecked(bool(d.get("deadline_suspended", False))) self.deadline_panel.dl_submit_scene_cb.setChecked(bool(d.get("deadline_submit_scene", True))) - self._deadline_job_name_template = str(d.get("deadline_job_name_template", "Render Mapper Pro Job - {scene_name}")) + self._deadline_job_name_template = str(d.get("deadline_job_name_template", f"{APP_NAME} Job - {{scene_name}}")) if self._deadline_job_name_template == "BlenderRender Job - {scene_name}": # migrate old app name - self._deadline_job_name_template = "Render Mapper Pro Job - {scene_name}" + self._deadline_job_name_template = f"{APP_NAME} Job - {{scene_name}}" self.deadline_panel.dl_name_template_edit.setText(self._deadline_job_name_template) self.deadline_panel.dl_machine_limit_spin.setValue(int(d.get("deadline_machine_limit", 0))) self.deadline_panel.dl_limits_edit.setText(str(d.get("deadline_limits", ""))) @@ -4185,7 +4195,7 @@ def note_missing(vp: str, vn: str) -> None: deadline_chunk_size=int(jd.get("deadline_chunk_size", 1)), deadline_suspended=bool(jd.get("deadline_suspended", False)), deadline_submit_scene=bool(jd.get("deadline_submit_scene", True)), - deadline_job_name_template=str(jd.get("deadline_job_name_template", "Render Mapper Pro Job - {scene_name}")), + deadline_job_name_template=str(jd.get("deadline_job_name_template", f"{APP_NAME} Job - {{scene_name}}")), deadline_machine_limit=int(jd.get("deadline_machine_limit", 0)), deadline_limits=str(jd.get("deadline_limits", "")), deadline_command_path=str(jd.get("deadline_command_path", "")), @@ -4672,7 +4682,7 @@ def run_qt_app() -> None: if probe.state() == QLocalSocket.LocalSocketState.ConnectedState: probe.waitForBytesWritten(250) probe.disconnectFromServer() - print("Render Mapper Pro is already running — focusing the existing window.", file=sys.stderr) + print(f"{APP_NAME} is already running — focusing the existing window.", file=sys.stderr) return # No live instance; clear any stale socket and become the server. QLocalServer.removeServer(SINGLE_INSTANCE_KEY) diff --git a/app_version.py b/app_version.py index 899eaa9..71aaa27 100644 --- a/app_version.py +++ b/app_version.py @@ -5,4 +5,8 @@ tag whose value doesn't match this string. """ __version__ = "1.8.34" -APP_NAME = "Render Mapper Pro" # display name; single source shared by the app + mixins +# Display name; single source shared by the app + mixins. "PrevizRender" is +# the product name (formerly "Render Mapper Pro"); installer/bundle artifact +# names in BlenderVideoMapper.spec and installer/windows.iss intentionally keep +# the old name so the auto-update chain and install paths stay valid. +APP_NAME = "PrevizRender" diff --git a/app_window/reporting_mixin.py b/app_window/reporting_mixin.py index 08b9bc4..294b353 100644 --- a/app_window/reporting_mixin.py +++ b/app_window/reporting_mixin.py @@ -9,6 +9,7 @@ from datetime import datetime from pathlib import Path +from app_version import APP_NAME from app_window.base import _WindowMembers from core.logging_setup import get_logger from core.metrics import estimate_energy_cost @@ -105,7 +106,7 @@ def _build_html_report(self) -> str: '.err{color:#ed4245;font-family:ui-monospace,monospace;font-size:12px;' 'white-space:pre-wrap;margin:6px 0}.brand{color:#e8833a;font-weight:700}' '' - '

Render Mapper Pro — Render Report

' + f'

{APP_NAME} — Render Report

' f'
{stamp} · Scene: {scene}
' '' '' diff --git a/core/logging_setup.py b/core/logging_setup.py index 7a1295a..8219f12 100644 --- a/core/logging_setup.py +++ b/core/logging_setup.py @@ -63,7 +63,7 @@ def setup_logging(log_path: Path | str | None = None, level: int = logging.INFO, logger.propagate = False logger.info("%s", "=" * 60) - logger.info("Render Mapper Pro %s — session start", version or "?") + logger.info("PrevizRender %s — session start", version or "?") return logger diff --git a/docs/screenshots/previzrender.png b/docs/screenshots/previzrender.png new file mode 100644 index 0000000..e045d7b Binary files /dev/null and b/docs/screenshots/previzrender.png differ diff --git a/docs/screenshots/render-mapper-pro.png b/docs/screenshots/render-mapper-pro.png deleted file mode 100644 index 8e60ad7..0000000 Binary files a/docs/screenshots/render-mapper-pro.png and /dev/null differ diff --git a/site/img/app.png b/site/img/app.png new file mode 100644 index 0000000..e045d7b Binary files /dev/null and b/site/img/app.png differ diff --git a/site/img/toy-robot-media-logo.png b/site/img/toy-robot-media-logo.png new file mode 100644 index 0000000..9b7821b Binary files /dev/null and b/site/img/toy-robot-media-logo.png differ diff --git a/site/index.html b/site/index.html new file mode 100644 index 0000000..e69e4a8 --- /dev/null +++ b/site/index.html @@ -0,0 +1,506 @@ + + + + + +PrevizRender — render the comps, before load-in. + + + + + + + + + + + + + + + + + + + + + +
+
+ Free · macOS (Apple Silicon) & Windows +

Render the comps, before load-in.

+

Map videos onto 3D-scene materials and render headlessly — Blender or Cinema 4D + Redshift, on your own machine. One scene, many screens, no farm required.

+ +
Formerly Render Mapper Pro. Auto-updates on launch — see the latest release →
+ +
+
+
PrevizRender
+ PrevizRender — scene, clips, and render queue with a live preview +
+
+ +
+ Renders with Blender · Cinema 4D + Redshift · ships bundled ffmpeg +
+
+
+ + +
+
+
+ Four steps, start to finish +

From a scene and clips to finished frames

+

No render setup, no scripting. Scan the scene, link clips to materials, queue it.

+
+
+
+
1

Add a scene

+

Drag a .blend / .c4d / .glb (or .fbx, .usd, …) onto the Scene box, then Scan — materials, cameras, and render settings load automatically.

+
+
+
2

Add clips

+

Drag your videos into the list and pick a camera. Resolution, fps, and frame ranges auto-fill from the scene.

+
+
+
3

Link them

+

Auto-map matches clips to materials by name — or link any pair by hand. Every screen gets its content.

+
+
+
4

Queue & render

+

Hit Start and watch the live preview. The renderer runs headless in the background — a crash can never take down the app.

+
+
+
+
+ + +
+
+
+ A closer look +

A render pipeline in one window

+

Click a feature to read what it does.

+
+
+
+ + + + + +
+
+
+
PrevizRender
+ PrevizRender feature +
+

The right backend is chosen automatically by scene type — Blender for .blend / .fbx / .usd and friends, Cinema 4D + Redshift for .c4d. Same workflow either way.

+
+
+
+
+ + +
+
+
+ Backends +

Your scenes, your renderers

+

PrevizRender drives the renderer you already use — headlessly, in the background.

+
+
+
+

Bl Blender

+

.blend, .fbx, .obj, .glb, .usd, .abc and more. No Blender on the machine? The app offers a managed runtime download — one click, with a progress bar.

+ Nothing else to install +
+
+

C4 Cinema 4D + Redshift

+

.c4d scenes render through your own C4D + Redshift install — the app pulls the Redshift sampling settings straight from the scene.

+ Uses your licensed install +
+
+
+
+ + +
+
+
+ Part of the family +

Plan it. Map it. Render it.

+

Three sibling tools by hamLT, powered by Toy Robot Media — one for each stage of getting content onto real-world screens.

+
+ +
+
+ + +
+
+
+

Get PrevizRender

+

Free. Installer or portable zip — updates arrive automatically.

+
+
+ +
macOS (Apple Silicon)
+
Checking latest version…
+ Download for Mac +
+
+ +
Windows (x64)
+
Checking latest version…
+ Download for Windows +
+
+
Prefer no install? Portable zips for both platforms are on the Releases page →
+
+
+
+ + + + + + diff --git a/site/previzrender-logo.svg b/site/previzrender-logo.svg new file mode 100644 index 0000000..5529754 --- /dev/null +++ b/site/previzrender-logo.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + +
JobStatusFramesDurationAvg/frameEst. Cost