Lightfielder Viewport | Python Scripting API
The Viewport app embeds CPython 3.11 or 3.12 through the LuaPython framework.
All Viewport functionality is available by importing the lf module:
import lf
lf.new_scene()
lf.open_scene("/path/to/file.jsonc")
The lf module is registered automatically when the LuaPython engine initialises
and is available in both the __main__ scope and via import lf.
Convention
Functions return None on success and raise RuntimeError on failure.
Functions that return data (like lf.get_selected, lf.list_layouts) return
a Python object (list or dict) parsed from JSON.
Primitive and light type names are lowercase:
lf.create_primitive("cube") # not "Cube"
lf.create_light("directional") # not "Directional"
lf.set_camera_mode("orbit") # not "Orbit"
lf.set_shading("wireframe") # not "Wireframe"
Display toggles accept a boolean (True / False).
Scene / File Operations
lf.new_scene()
try:
lf.open_scene("/Users/me/scenes/my_scene.jsonc")
except RuntimeError as e:
print(f"Failed: {e}")
lf.save_scene()
lf.save_scene_as("/Users/me/scenes/copy.jsonc")
lf.revert_scene()
lf.import_file("/Users/me/models/car.obj")
Creating Objects
# Scene objects
lf.create_camera()
lf.create_locator()
lf.create_group()
lf.create_reference()
lf.create_audio()
lf.create_note()
# Primitives (lowercase)
lf.create_primitive("cube")
lf.create_primitive("cone")
lf.create_primitive("sphere")
lf.create_primitive("cylinder")
lf.create_primitive("pyramid")
lf.create_primitive("torus")
# Lights (lowercase)
lf.create_light("ambient")
lf.create_light("area")
lf.create_light("directional")
lf.create_light("dome")
lf.create_light("point")
lf.create_light("spot")
lf.create_light("sphere")
lf.create_light("tube")
Selection
lf.select_all()
lf.deselect_all()
lf.select_by_name("Cube") # partial name match
lf.select_by_id("obj_5") # exact id match
selected = lf.get_selected() # returns list of dicts
for obj in selected:
print(f"{obj['name']} at {obj['position']}")
Example return from get_selected():
[
{
"id": "obj_3",
"name": "Cube",
"position": [0.0, 0.0, 0.0],
"rotation": [0.0, 0.0, 0.0],
"scale": [1.0, 1.0, 1.0],
"type": "mesh",
}
]
Edit Commands
lf.undo()
lf.redo()
lf.cut()
lf.copy()
lf.paste()
lf.delete_selected()
lf.duplicate_selected()
lf.group_selected()
lf.ungroup_selected()
Transform
# Set transform: id, position, rotation, scale (each as list of 3 floats)
lf.set_transform("obj_3", [0, 0, 0], [0, 0, 0], [2, 2, 2])
# Get transform returns a dict
t = lf.get_transform("obj_3")
print(t["position"]) # [0.0, 0.0, 0.0]
# Reparent: child_id, parent_id
lf.set_parent("obj_3", "obj_1")
# Detach from parent (empty string)
lf.set_parent("obj_3", "")
# Rename object
lf.rename_object("obj_3", "MyCube")
Viewport Control
lf.frame_all()
lf.go_home()
lf.set_camera_mode("orbit") # "orbit" | "fps"
lf.set_shading("shaded") # "shaded" | "boundingBox" | "points" | "wireframe" | "none"
lf.set_interaction("selection") # "selection" | "transform"
Display Toggles
All take a bool:
lf.show_grid(True)
lf.show_vertices(False)
lf.show_normals(False)
lf.show_edges(True)
lf.show_xray(False)
lf.show_hud(True)
lf.show_fps(False)
lf.show_details(False)
lf.show_distance(False)
lf.show_render(False)
lf.show_selected(False)
lf.show_camera_view(False)
lf.show_polygons(False)
lf.show_camera_locators(False)
lf.show_light_locators(False)
lf.show_locator_icons(True)
lf.show_skybox(False)
Auxiliary Windows
lf.open_outliner() # Opens Outliner window (F6 equivalent)
lf.open_attributes() # Opens Attributes window (F7 equivalent)
lf.open_history_stack() # Opens History Stack (F5 equivalent)
lf.close_outliner()
lf.close_attributes()
lf.close_history_stack()
Window Layouts
lf.save_layout("my_layout")
lf.load_layout("my_layout")
layouts = lf.list_layouts() # returns list of strings
print(layouts) # ["layout1", "layout2"]
OS Tabs
lf.new_tab() # Open new scene in OS tab
lf.close_tab() # Close current tab
Scripts & Examples
lf.run_script("/path/to/script.py")
lf.run_script("/path/to/script.lua")
scripts = lf.list_scripts() # list of filenames
lf.open_scripts_folder()
examples = lf.list_examples() # list of example names
lf.open_example("My Example")
lf.open_examples_folder()
History Stack
lf.clear_undo()
lf.save_undo("/Users/me/undo_snapshot.jsonc")
lf.load_undo("/Users/me/undo_snapshot.jsonc")
Complete Example
import lf
# Create a new scene
lf.new_scene()
# Add lighting and geometry
lf.create_light("directional")
lf.create_primitive("cube")
lf.create_primitive("sphere")
lf.create_camera()
# Select and inspect
lf.select_by_name("Cube")
info = lf.get_selected()
print("Selected:", info)
# Transform
lf.set_transform("obj_3", [2, 0, 0], [0, 0, 0], [1, 1, 1])
lf.rename_object("obj_3", "MyCube")
# Duplicate
lf.deselect_all()
lf.select_by_name("MyCube")
lf.duplicate_selected()
# Viewport
lf.frame_all()
lf.set_shading("wireframe")
lf.show_grid(False)
# Windows
lf.open_outliner()
lf.open_attributes()
# Save
lf.save_scene_as("/Users/me/example_scene.jsonc")
Tips
- Run
.pyscripts from Viewport's Scripts menu or vialf.run_script(). - The scripting engine is synchronous so long scripts will block the UI.
- Import
lfat the top of any Python script for full Viewport control. - All list/dict return values (from
get_selected,get_transform, etc.) are native Python objects so no JSON parsing needed.