Source code for pyvcad_rendering.render

import sys
import wx
import os
import json
import inspect
from pathlib import Path

from .render_frame import RenderFrame

# Path to persistent state file in user home directory
STATE_FILE = Path.home() / ".pyvcad_render_state.json"

def _get_caller_id():
    """Identify the script invoking the render function."""
    try:
        # Step back through stack: 0=here, 1=renderWrapper, 2=caller
        # We look for the first frame outside of this module
        for frame_info in inspect.stack():
            filename = frame_info.filename
            # Ignore calls from within the library itself
            if "pyvcad_rendering" in filename:
                continue
            return os.path.abspath(filename)
    except Exception:
        pass
    return "unknown"

def render(vcad_object, materials=None):
    """Open the interactive 3D viewer for ``vcad_object`` (wx main loop)."""
    caller_id = _get_caller_id()

    # Load state
    state = {}
    if STATE_FILE.exists():
        try:
            with open(STATE_FILE, 'r') as f:
                state = json.load(f)
        except Exception:
            state = {} # Corrupt file, reset

    last_caller = state.get("last_caller", None)
    settings_to_use = {}

    # If the caller matches the last run, reuse settings
    if last_caller == caller_id and "last_settings" in state:
        settings_to_use = state["last_settings"]
    else:
        # New design context -> reset settings (empty dict uses defaults in RenderFrame)
        settings_to_use = {}
        # Update state with new caller immediately so if they crash/close, we track it
        state["last_caller"] = caller_id
        # Clear old settings in file to avoid confusion
        state["last_settings"] = {}
        try:
            with open(STATE_FILE, 'w') as f:
                json.dump(state, f, indent=4)
        except:
            pass

    app = wx.App(False)
    # Pass state file path so Frame can save on close
    app.frame = RenderFrame(vcad_object, state_file=str(STATE_FILE), initial_settings=settings_to_use, materials=materials)
    app.MainLoop()

[docs] def Render(vcad_object, materials=None): """Alias for :func:`render`.""" render(vcad_object, materials)
def render_image(vcad_object, filepath, settings=None, width=1920, height=1080, materials=None): """Render a single frame off-screen and save to ``filepath`` (no GUI).""" # settings can include scale_bar_palette: "auto" or a named palette override. from .headless_renderer import HeadlessRenderer renderer = HeadlessRenderer(width=width, height=height) renderer.render_and_save(vcad_object, filepath, settings=settings, materials=materials)
[docs] def Render_Image(vcad_object, filepath, settings=None, width=1920, height=1080, materials=None): """Alias for :func:`render_image`.""" render_image(vcad_object, filepath, settings, width, height, materials=materials)
def render_turntable_animation(vcad_object, output_dir, duration=3.0, fps=30, distance_multiplier=1.5, elevation_angle_deg=30.0, settings=None, width=1920, height=1080, output_format="gif", keep_frames=False, materials=None): """Orbit the camera around the scene and write an animation under ``output_dir`` (no GUI).""" # settings can include scale_bar_palette: "auto" or a named palette override. from .headless_renderer import HeadlessRenderer renderer = HeadlessRenderer(width=width, height=height) renderer.render_turntable_animation(vcad_object, output_dir, duration=duration, fps=fps, distance_multiplier=distance_multiplier, elevation_angle_deg=elevation_angle_deg, settings=settings, output_format=output_format, keep_frames=keep_frames, materials=materials)
[docs] def Render_Turntable_Animation(vcad_object, output_dir, duration=3.0, fps=30, distance_multiplier=1.5, elevation_angle_deg=30.0, settings=None, width=1920, height=1080, output_format="gif", keep_frames=False, materials=None): """Alias for :func:`render_turntable_animation`.""" render_turntable_animation(vcad_object, output_dir, duration, fps, distance_multiplier, elevation_angle_deg, settings, width, height, output_format, keep_frames, materials=materials)
def render_sweep_animation(vcad_object, output_dir, axis="z", duration=3.0, fps=30, loop=False, pause_seconds=0.5, settings=None, width=1920, height=1080, output_format="gif", keep_frames=False, materials=None): """Animate a clipping sweep along ``axis`` and write frames or a GIF under ``output_dir`` (no GUI).""" from .headless_renderer import HeadlessRenderer renderer = HeadlessRenderer(width=width, height=height) renderer.render_sweep_animation(vcad_object, output_dir, axis=axis, duration=duration, fps=fps, loop=loop, pause_seconds=pause_seconds, settings=settings, output_format=output_format, keep_frames=keep_frames, materials=materials)
[docs] def Render_Sweep_Animation(vcad_object, output_dir, axis="z", duration=3.0, fps=30, loop=False, pause_seconds=0.5, settings=None, width=1920, height=1080, output_format="gif", keep_frames=False, materials=None): """Alias for :func:`render_sweep_animation`.""" render_sweep_animation(vcad_object, output_dir, axis, duration, fps, loop, pause_seconds, settings, width, height, output_format, keep_frames, materials=materials)
__all__ = ["render", "Render", "render_image", "Render_Image", "render_turntable_animation", "Render_Turntable_Animation", "render_sweep_animation", "Render_Sweep_Animation"]