### Search and Install Plugins from Registry Source: https://lichtfeld.io/docs/guide Search for plugins by keyword, install a specific plugin by ID, check for updates, or update a plugin. ```python import lichtfeld as lf results = lf.plugins.search("neural rendering") lf.plugins.install_from_registry("plugin_id") lf.plugins.check_updates() lf.plugins.update("my_plugin") ``` -------------------------------- ### Install Plugin from GitHub Source: https://lichtfeld.io/docs/guide Install a plugin directly from a GitHub repository using its owner and repo name or a full URL. ```python import lichtfeld as lf lf.plugins.install("owner/repo") lf.plugins.install("https://github.com/owner/repo") ``` -------------------------------- ### Custom Training Callback Example Source: https://lichtfeld.io/docs/guide An example of a custom plugin that automatically saves checkpoints at specified intervals during training. ```python import lichtfeld as lf from lfs_plugins.ui.state import AppState class AutoSavePlugin: """Automatically save checkpoints every N iterations.""" def __init__(self, interval=5000): self.interval = interval self.last_save = 0 def on_post_step(self): ctx = lf.context() if ctx.iteration - self.last_save >= self.interval: lf.save_checkpoint() self.last_save = ctx.iteration lf.log.info(f"Auto-saved at iteration {ctx.iteration}") _auto_save = None def on_load(): global _auto_save _auto_save = AutoSavePlugin(interval=5000) lf.on_post_step(_auto_save.on_post_step) lf.log.info("Auto-save plugin loaded") def on_unload(): global _auto_save _auto_save = None ``` -------------------------------- ### Plugin Entrypoint __init__.py Source: https://lichtfeld.io/docs/guide Example `__init__.py` file for a LichtFeld plugin, defining `on_load` and `on_unload` functions for class registration and unregistration. ```python import lichtfeld as lf from .panels.main_panel import MainPanel _classes = [MainPanel] def on_load(): for cls in _classes: lf.register_class(cls) lf.log.info("my_plugin loaded") def on_unload(): for cls in reversed(_classes): lf.unregister_class(cls) lf.log.info("my_plugin unloaded") ``` -------------------------------- ### Capability Registry Initialization Source: https://lichtfeld.io/docs/api-reference Get the singleton instance of the CapabilityRegistry to manage and invoke capabilities. ```python from lfs_plugins.capabilities import CapabilityRegistry, CapabilitySchema, Capability from lfs_plugins.context import PluginContext, SceneContext, ViewContext, CapabilityBroker registry = CapabilityRegistry.instance() ``` -------------------------------- ### Plugin pyproject.toml Configuration Source: https://lichtfeld.io/docs/guide Example `pyproject.toml` file for a LichtFeld plugin, including project metadata and tool-specific settings. ```toml [project] name = "my_plugin" version = "0.1.0" description = "What this plugin does" authors = [{name = "Your Name"}] dependencies = [] [tool.lichtfeld] hot_reload = true plugin_api = ">=1,<2" lichtfeld_version = ">=0.4.2" required_features = [] ``` -------------------------------- ### Define Material Settings with Properties Source: https://lichtfeld.io/docs/guide Example of creating a PropertyGroup subclass for material settings, utilizing various property types like FloatVectorProperty and StringProperty. Demonstrates singleton access and modification of properties. ```python from lfs_plugins.props import PropertyGroup, FloatProperty, StringProperty class MaterialSettings(PropertyGroup): color = FloatVectorProperty(default=(1, 1, 1), size=3, subtype="COLOR") roughness = FloatProperty(default=0.5, min=0.0, max=1.0) name = StringProperty(default="Untitled", maxlen=64) # Singleton access settings = MaterialSettings.get_instance() settings.roughness = 0.8 print(settings.roughness) # 0.8 (validated and clamped) ``` -------------------------------- ### PluginManager Methods Source: https://lichtfeld.io/docs/api-reference Provides methods for discovering, loading, unloading, installing, uninstalling, updating, and searching for plugins. It also allows checking for updates and retrieving plugin states and errors. ```APIDOC ## PluginManager ### `plugins_dir` - **Description**: Property that returns the path to the plugin directory (`~/.lichtfeld/plugins/`). - **Returns**: `Path` ### `discover()` - **Description**: Scans the plugin directory for available plugins. - **Returns**: `list[PluginInfo]` ### `load(name, on_progress=None)` - **Description**: Loads a specific plugin by its name. An optional progress callback can be provided. - **Returns**: `bool` ### `unload(name)` - **Description**: Unloads a specific plugin by its name. - **Returns**: `bool` ### `reload(name)` - **Description**: Hot-reloads a specific plugin by its name. - **Returns**: `bool` ### `load_all()` - **Description**: Loads all user-enabled plugins. - **Returns**: `dict[str, bool]` ### `install(url, on_progress=None, auto_load=True)` - **Description**: Installs a plugin from a Git URL. An optional progress callback and auto-load flag can be provided. - **Returns**: `str` (the name of the installed plugin) ### `uninstall(name)` - **Description**: Uninstalls a plugin by its name. - **Returns**: `bool` ### `update(name, on_progress=None)` - **Description**: Updates a specific plugin by its name. An optional progress callback can be provided. - **Returns**: `bool` ### `search(query, compatible_only=True)` - **Description**: Searches the plugin registry for plugins matching the query. Compatibility can be filtered. - **Returns**: `list[RegistryPluginInfo]` ### `check_updates()` - **Description**: Checks for available updates for installed plugins. - **Returns**: `dict[str, tuple]` ### `get_state(name)` - **Description**: Retrieves the current state of a specific plugin. - **Returns**: `Optional[PluginState]` ### `get_error(name)` - **Description**: Retrieves the error message associated with a specific plugin, if any. - **Returns**: `Optional[str]` ### `get_traceback(name)` - **Description**: Retrieves the error traceback for a specific plugin, if any. - **Returns**: `Optional[str]` ``` -------------------------------- ### Get PluginManager Instance Source: https://lichtfeld.io/docs/api-reference Obtain the singleton instance of the PluginManager. ```python mgr = PluginManager.instance() ``` -------------------------------- ### Open Image File Dialog Source: https://lichtfeld.io/docs/api-reference Opens a dialog to select an image file. Specify a starting directory if needed. ```python lf.ui.open_image_dialog(start_dir='') ``` -------------------------------- ### Add Shell and Retained Behavior to a Panel Source: https://lichtfeld.io/docs/guide This example demonstrates adding shell and retained behavior to a panel by defining inline RCSS, setting `height_mode`, and implementing the `on_update` method for periodic updates. The `draw` method still handles content rendering. ```python import lichtfeld as lf class StatusBarPanel(lf.ui.Panel): id = "my_plugin.status" label = "Build Up 2" space = lf.ui.PanelSpace.STATUS_BAR height_mode = lf.ui.PanelHeightMode.CONTENT update_interval_ms = 120 style = "" body.status-bar-panel { padding: 0 12dp; } #im-root .im-label { color: #f3c96d; font-weight: bold; } " def __init__(self): self._progress = 0.2 def draw(self, ui): ui.label("STATUS") ui.progress_bar(self._progress, f"{int(self._progress * 100)}%") def on_update(self, doc): del doc self._progress = (self._progress + 0.02) % 1.0 return True ``` -------------------------------- ### Open Mesh File Dialog Source: https://lichtfeld.io/docs/api-reference Opens a dialog to select a mesh file. A starting directory can be specified. ```python lf.ui.open_mesh_file_dialog(start_dir='') ``` -------------------------------- ### Create a Modal Operator (Interactive Tool) Source: https://lichtfeld.io/docs/guide Implement an operator that runs in a modal state, allowing for interactive user input. This example creates a tool to measure distance by clicking two points. ```python import lichtfeld as lf from lfs_plugins.types import Operator, Event class MeasureTool(Operator): label = "Measure Distance" description = "Click two points to measure distance" # Only set UNDO when the operator actually implements undo()/redo() # or when all mutations go through history-aware scene APIs. options = set() def __init__(self): super().__init__() self.start_pos = None def invoke(self, context, event: Event) -> set: self.start_pos = None lf.log.info("Click first point...") return {"RUNNING_MODAL"} def modal(self, context, event: Event) -> set: if event.type == "ESC": lf.log.info("Measurement cancelled") return {"CANCELLED"} if event.type == "LEFTMOUSE" and event.value == "PRESS": pos = (event.mouse_x, event.mouse_y) if self.start_pos is None: self.start_pos = pos lf.log.info("Click second point...") return {"RUNNING_MODAL"} else: dx = pos[0] - self.start_pos[0] dy = pos[1] - self.start_pos[1] dist = (dx * dx + dy * dy) ** 0.5 lf.log.info(f"Distance: {dist:.2f} pixels") return {"FINISHED"} return {"RUNNING_MODAL"} def cancel(self, context): self.start_pos = None ``` -------------------------------- ### Open Folder Dialog Source: https://lichtfeld.io/docs/api-reference Opens a dialog to select a folder. A custom title and starting directory can be provided. ```python lf.ui.open_folder_dialog(title='Select Folder', start_dir='') ``` -------------------------------- ### Open PLY File Dialog Source: https://lichtfeld.io/docs/api-reference Opens a dialog to select a PLY file. A starting directory can be specified. ```python lf.ui.open_ply_file_dialog(start_dir='') ``` -------------------------------- ### Get Panel Information Source: https://lichtfeld.io/docs/api-reference Fetches detailed information about a specific UI panel by its ID. Returns None if the panel is not found. ```python lf.ui.get_panel(panel_id) ``` -------------------------------- ### Get UI Hook Points Source: https://lichtfeld.io/docs/api-reference Retrieves a list of all available UI hook point keys. Use this to avoid hard-coding hook points. ```python lf.ui.get_hook_points() ``` -------------------------------- ### Get Available Languages Source: https://lichtfeld.io/docs/api-reference Returns a list of available language codes and their display names for the UI. ```python lf.ui.get_languages() ``` -------------------------------- ### Training Control Functions Source: https://lichtfeld.io/docs/api-reference Functions to manage the training process, including initialization, starting, pausing, resuming, stopping, resetting, and saving checkpoints. ```APIDOC ## Training Control ### `prepare_training_from_scene()` **Description**: Initialize trainer from scene cameras and point cloud. ### Returns - `None` ### `start_training()` **Description**: Start training. ### Returns - `None` ### `pause_training()` **Description**: Pause the training process. ### Returns - `None` ### `resume_training()` **Description**: Resume the training process. ### Returns - `None` ### `stop_training()` **Description**: Stop the training process. ### Returns - `None` ### `reset_training()` **Description**: Reset training to iteration 0. ### Returns - `None` ### `save_checkpoint()` **Description**: Save the current training checkpoint. ### Returns - `None` ### `switch_to_edit_mode()` **Description**: Enter edit mode for the training. ### Returns - `None` ### `has_trainer()` **Description**: Check if a trainer is loaded. ### Returns - `bool` ### `trainer_state()` **Description**: Get the current state of the trainer. ### Returns - `str` ### `finish_reason()` **Description**: Get the reason why training ended. ### Returns - `str or None` ### `trainer_error()` **Description**: Get any error message from the trainer. ### Returns - `str or None` ### `context()` **Description**: Get a snapshot of the training context. ### Returns - `Context` ### `optimization_params()` **Description**: Get the current optimization parameters. ### Returns - `OptimizationParams` ### `dataset_params()` **Description**: Get the current dataset parameters. ### Returns - `DatasetParams` ### `loss_buffer()` **Description**: Get the history of training losses. ### Returns - `list[float]` ### `load_checkpoint_for_training(checkpoint_path, dataset_path, output_path)` **Description**: Load a checkpoint for training. ### Parameters - `checkpoint_path` (str) - Required - Path to the checkpoint file. - `dataset_path` (str) - Required - Path to the dataset. - `output_path` (str) - Required - Path for output. ### Returns - `None` ``` -------------------------------- ### Get Main Panel Tab Summaries Source: https://lichtfeld.io/docs/api-reference Retrieves typed summaries for all tabs within the main UI panel. ```python lf.ui.get_main_panel_tabs() ``` -------------------------------- ### Get App Context Source: https://lichtfeld.io/docs/api-reference Fetches the current application context, which may contain information about the running application state. ```python lf.ui.context() ``` -------------------------------- ### Training Control Functions Source: https://lichtfeld.io/docs/guide Functions to manage the training process, including starting, pausing, resuming, stopping, resetting, and saving checkpoints. ```python import lichtfeld as lf lf.start_training() lf.pause_training() lf.resume_training() lf.stop_training() lf.reset_training() lf.save_checkpoint() ``` -------------------------------- ### Get and Set Node Transformation Matrix Source: https://lichtfeld.io/docs/guide Shows how to retrieve and set the transformation matrix for a scene node. The matrix is represented as a 16-float column-major matrix. ```python import lichtfeld as lf # Get/set as 16-float column-major matrix matrix = lf.get_node_transform("My Splat") lf.set_node_transform("My Splat", matrix) ``` -------------------------------- ### Add, Query, and Modify Scene Nodes Source: https://lichtfeld.io/docs/guide Provides examples for managing nodes within the scene graph, including adding new groups and splats, querying existing nodes, and performing operations like renaming, reparenting, removing, and duplicating nodes. ```python scene = lf.get_scene() # Add nodes group_id = scene.add_group("My Group") splat_id = scene.add_splat( "My Splat", means=lf.Tensor.zeros([100, 3], device="cuda"), sh0=lf.Tensor.zeros([100, 1, 3], device="cuda"), shN=lf.Tensor.zeros([100, 0, 3], device="cuda"), scaling=lf.Tensor.zeros([100, 3], device="cuda"), rotation=lf.Tensor.zeros([100, 4], device="cuda"), opacity=lf.Tensor.zeros([100, 1], device="cuda"), ) # Query nodes nodes = scene.get_nodes() node = scene.get_node("My Splat") visible = scene.get_visible_nodes() # Modify scene.rename_node("My Splat", "Renamed Splat") scene.reparent(splat_id, group_id) scene.remove_node("Renamed Splat", keep_children=False) new_name = scene.duplicate_node("My Group") ``` -------------------------------- ### Create Plugin with CLI Source: https://lichtfeld.io/docs/guide Commands to create, check, and list plugins using the LichtFeld Studio CLI. ```bash LichtFeld-Studio plugin create my_plugin LichtFeld-Studio plugin check my_plugin LichtFeld-Studio plugin list ``` -------------------------------- ### Get Scene Object and Scene Status Source: https://lichtfeld.io/docs/guide Demonstrates how to retrieve the current scene object and check if a scene is loaded using the lichtfeld module. Accesses the total Gaussian count if a scene is available. ```python import lichtfeld as lf scene = lf.get_scene() # Get scene object (None if no scene loaded) if lf.has_scene(): print(f"Total gaussians: {scene.total_gaussian_count}") ``` -------------------------------- ### Create Range Tensor Source: https://lichtfeld.io/docs/api-reference Creates a tensor with values ranging from start to end with a specified step. Requires start, end, step, device, and data type. ```python t.arange(start, end, step, device, dtype) ``` -------------------------------- ### Show Help Source: https://lichtfeld.io/docs/api-reference Displays the help information for the Lichtfeld library. ```python lf.help() ``` -------------------------------- ### Create Linear Space Tensor Source: https://lichtfeld.io/docs/api-reference Creates a tensor with values linearly spaced between start and end. Requires start, end, number of steps, device, and data type. ```python t.linspace(start, end, steps, device, dtype) ``` -------------------------------- ### Register and Invoke Capabilities Source: https://lichtfeld.io/docs/guide Demonstrates how to register a capability with a schema and invoke it. Requires `lfs_plugins.capabilities` and `lfs_plugins.context`. ```python from lfs_plugins.capabilities import CapabilityRegistry, CapabilitySchema from lfs_plugins.context import PluginContext registry = CapabilityRegistry.instance() # Register a capability def my_handler(args: dict, ctx: PluginContext) -> dict: threshold = args.get("threshold", 0.5) if ctx.scene: # Do something with the scene pass return {"success": True, "count": 42} registry.register( name="my_plugin.analyze", handler=my_handler, description="Analyze gaussians by threshold", schema=CapabilitySchema( properties={"threshold": {"type": "number", "default": 0.5}}, required=[], ), plugin_name="my_plugin", requires_gui=True, ) # Invoke a capability result = registry.invoke("my_plugin.analyze", {"threshold": 0.3}) # result = {"success": True, "count": 42} # Query registry.has("my_plugin.analyze") # True caps = registry.list_all() # List[Capability] # Unregister registry.unregister("my_plugin.analyze") registry.unregister_all_for_plugin("my_plugin") ``` -------------------------------- ### Get Tensor Shape Source: https://lichtfeld.io/docs/api-reference Returns the dimensions of the tensor as a tuple. ```python tensor.shape ``` -------------------------------- ### Transform Operations Source: https://lichtfeld.io/docs/api-reference Functions for getting and setting node transformations. ```APIDOC ## Transform Operations ### Description Functions for getting and setting node transformations, including decomposition and composition. ### Functions - **`get_node_transform(name)`**: Get the transform matrix of a node. Returns `list[float]` (16 floats, column-major). - **`set_node_transform(name, matrix)`**: Set the transform matrix for a node. Returns `None`. - **`decompose_transform(matrix)`**: Decompose a 4x4 matrix into its components. Returns `dict`. - **`compose_transform(translation, euler_deg, scale)`**: Build a 4x4 transform matrix from translation, Euler angles (degrees), and scale. Returns `list[float]`. ### `decompose_transform` Return Keys - **`translation`** (`list[float]`): Position `[x, y, z]`. - **`rotation_quat`** (`list[float]`): Quaternion rotation `[x, y, z, w]`. - **`rotation_euler`** (`list[float]`): Euler angles in radians `[rx, ry, rz]`. - **`rotation_euler_deg`** (`list[float]`): Euler angles in degrees `[rx, ry, rz]`. - **`scale`** (`list[float]`): Scale factors `[sx, sy, sz]`. ``` -------------------------------- ### Create Plugin with Python Source: https://lichtfeld.io/docs/guide Python code to scaffold a new plugin package and print its path. ```python import lichtfeld as lf path = lf.plugins.create("my_plugin") print(path) ``` -------------------------------- ### Registering Training Lifecycle Hooks Source: https://lichtfeld.io/docs/guide Shows how to use decorators to register callbacks for various stages of the training process. Requires `lichtfeld`. ```python import lichtfeld as lf @lf.on_training_start def on_start(): lf.log.info("Training started") @lf.on_iteration_start def on_iter(): pass @lf.on_pre_optimizer_step def on_pre_opt(): pass @lf.on_post_step def on_post(): ctx = lf.context() if ctx.iteration % 1000 == 0: lf.log.info(f"Iteration {ctx.iteration}, loss: {ctx.loss:.6f}") @lf.on_training_end def on_end(): lf.log.info(f"Training finished: {lf.finish_reason()}") ``` -------------------------------- ### Simple Immediate-Mode Panel Source: https://lichtfeld.io/docs/guide A basic LichtFeld Studio panel implemented using only the `draw(ui)` method for immediate-mode UI rendering. State is managed on the class instance. ```python import lichtfeld as lf class HelloPanel(lf.ui.Panel): id = "hello_world.main_panel" label = "Hello World" space = lf.ui.PanelSpace.MAIN_PANEL_TAB order = 200 def __init__(self): self._clicks = 0 def draw(self, ui): ui.heading("Hello from my plugin") ui.text_disabled("This panel uses only draw(ui).") if ui.button_styled(f"Greet ({self._clicks})", "primary"): self._clicks += 1 lf.log.info("Hello, LichtFeld!") ``` -------------------------------- ### Get Tensor Device Source: https://lichtfeld.io/docs/api-reference Returns the device the tensor is on ('cpu' or 'cuda'). ```python tensor.device ``` -------------------------------- ### Direct Icon Loading with Lichtfeld Source: https://lichtfeld.io/docs/api-reference Demonstrates direct loading and freeing of icons using the lichtfeld library. Icons are cached by C++ for performance. ```python import lichtfeld as lf texture_id = lf.load_icon(name) lf.free_icon(texture_id) ``` -------------------------------- ### Position / Size Source: https://lichtfeld.io/docs/api-reference Methods for getting and calculating position and size information. ```APIDOC ## Position / Size ### `get_cursor_pos()` **Description**: Gets the cursor position. **Returns**: `tuple` ### `get_cursor_screen_pos()` **Description**: Gets the cursor screen position. **Returns**: `tuple` ### `get_window_pos()` **Description**: Gets the window position. **Returns**: `tuple` ### `get_window_width()` **Description**: Gets the window width. **Returns**: `float` ### `get_text_line_height()` **Description**: Gets the text line height. **Returns**: `float` ### `get_content_region_avail()` **Description**: Gets the available content area. **Returns**: `tuple` ### `get_viewport_pos()` **Description**: Gets the viewport position. **Returns**: `tuple` ### `get_viewport_size()` **Description**: Gets the viewport size. **Returns**: `tuple` ### `get_dpi_scale()` **Description**: Gets the DPI scale factor. **Returns**: `float` ### `calc_text_size(text)` **Description**: Calculates the dimensions of given text. **Returns**: `tuple` ``` -------------------------------- ### Create a New Plugin Source: https://lichtfeld.io/docs/guide Use the LichtFeld Python API to create the minimal source package for a new plugin. ```python import lichtfeld as lf path = lf.plugins.create("my_new_plugin") ``` -------------------------------- ### Get Size of Tensor Dimension Source: https://lichtfeld.io/docs/api-reference Returns the size of a specific dimension of the tensor. ```python tensor.size(dim) ``` -------------------------------- ### Get Tensor Number of Elements Source: https://lichtfeld.io/docs/api-reference Returns the total number of elements in the tensor. ```python tensor.numel ``` -------------------------------- ### Get Pivot Mode Source: https://lichtfeld.io/docs/api-reference Retrieves the current pivot mode as an enum index. ```python lf.ui.get_pivot_mode() / set_pivot_mode(mode) ``` -------------------------------- ### Get Transform Space Source: https://lichtfeld.io/docs/api-reference Retrieves the current transform space as an enum index. ```python lf.ui.get_transform_space() ``` -------------------------------- ### Create a Responsive Grid Layout Source: https://lichtfeld.io/docs/api-reference Use `ui.grid_flow()` to create a responsive grid. The number of columns can be specified, and the grid will adapt. Each cell can contain its own layout. ```python with ui.grid_flow(columns=3) as grid: for item in items: with grid.box() as cell: cell.label(item.name) cell.button("Select") ``` -------------------------------- ### Get Active Tool Source: https://lichtfeld.io/docs/api-reference Retrieves the ID of the currently active tool in the UI. ```python lf.ui.get_active_tool() ``` -------------------------------- ### Discover and Manage Lichtfeld Plugins Source: https://lichtfeld.io/docs/guide Use these commands to scan for, load, unload, reload, uninstall, and list loaded Lichtfeld plugins. Ensure the 'lichtfeld' library is imported. ```python import lichtfeld as lf lf.plugins.discover() # Scan for installed plugins lf.plugins.load("my_plugin") # Load a specific plugin lf.plugins.unload("my_plugin") # Unload lf.plugins.reload("my_plugin") # Reload (hot reload) lf.plugins.uninstall("my_plugin") # Remove lf.plugins.list_loaded() # Show loaded plugins ``` -------------------------------- ### Get Tensor Data Type Source: https://lichtfeld.io/docs/api-reference Returns the data type of the tensor elements as a string. ```python tensor.dtype ``` -------------------------------- ### Basic Signal Usage Source: https://lichtfeld.io/docs/guide Demonstrates the creation and basic usage of a Signal, including setting and reading its value, and subscribing to changes. Subscriptions can be manually unsubscribed or owner-tracked. ```python from lfs_plugins.ui.signals import Signal, ComputedSignal, ThrottledSignal, Batch # Basic signal count = Signal(0, name="count") count.value = 5 # Notifies subscribers current = count.value # Read current value current = count.peek() # Read without tracking # Subscribe unsub = count.subscribe(lambda v: print(f"Count: {v}")) unsub() # Stop receiving updates # Owner-tracked subscription (auto-cleanup on plugin unload) unsub = count.subscribe_as("my_plugin", lambda v: print(v)) ``` -------------------------------- ### Get Tensor Number of Dimensions Source: https://lichtfeld.io/docs/api-reference Returns the number of dimensions (rank) of the tensor as an integer. ```python tensor.ndim ``` -------------------------------- ### Get Current FPS Source: https://lichtfeld.io/docs/api-reference Returns the current frames per second (FPS) of the application. ```python lf.ui.get_fps() ``` -------------------------------- ### Get Active Submode Source: https://lichtfeld.io/docs/api-reference Returns the ID of the currently active submode for the active tool. ```python lf.ui.get_active_submode() ``` -------------------------------- ### Import Lichtfeld for Plugin API Source: https://lichtfeld.io/docs/api-reference Import the lichtfeld library to access the convenience plugin API. ```python import lichtfeld as lf ``` -------------------------------- ### Get Current Language Source: https://lichtfeld.io/docs/api-reference Retrieves the language code of the currently active UI language. ```python lf.ui.get_current_language() ``` -------------------------------- ### Manage Node Selection Source: https://lichtfeld.io/docs/guide Demonstrates various methods for selecting and deselecting nodes in the scene, including selecting single nodes, multiple nodes, adding to the current selection, and retrieving selected node names. Also covers Gaussian-level selection using masks. ```python import lichtfeld as lf lf.select_node("My Splat") lf.select_nodes(["Splat A", "Splat B"]) lf.add_to_selection("Another Splat") names = lf.get_selected_node_names() lf.deselect_all() has_sel = lf.has_selection() # Gaussian-level selection (mask-based) scene = lf.get_scene() mask = lf.Tensor.zeros([scene.total_gaussian_count], dtype="bool", device="cuda") mask[0:100] = True scene.set_selection_mask(mask) scene.clear_selection() ``` -------------------------------- ### Get Git Commit Hash Source: https://lichtfeld.io/docs/api-reference Retrieves the Git commit hash for the current build of the application. ```python lf.ui.get_git_commit() ``` -------------------------------- ### Initialize Tensor API Source: https://lichtfeld.io/docs/api-reference Imports the Lichtfeld library and assigns the Tensor class to a shorthand alias 't'. ```python import lichtfeld as lf t = lf.Tensor ``` -------------------------------- ### Get Active Theme Name Source: https://lichtfeld.io/docs/api-reference Retrieves the name of the currently active theme ('dark' or 'light'). ```python lf.ui.get_theme() ``` -------------------------------- ### Signal Initialization Source: https://lichtfeld.io/docs/api-reference Initialize a Signal with an initial value and an optional name. Signals track their own value changes. ```python Signal(initial_value: T, name: str = "") ``` -------------------------------- ### Manage Panel Properties via API Source: https://lichtfeld.io/docs/guide Control panel visibility, labels, order, and space using the `lf.ui` API. This allows for dynamic management of panels after they have been registered. ```python import lichtfeld as lf lf.ui.set_panel_enabled("my_plugin.panel", False) lf.ui.is_panel_enabled("my_plugin.panel") lf.ui.get_panel("my_plugin.panel") lf.ui.set_panel_label("my_plugin.panel", "New Name") lf.ui.set_panel_order("my_plugin.panel", 50) lf.ui.set_panel_space("my_plugin.panel", lf.ui.PanelSpace.FLOATING) lf.ui.set_panel_parent("my_plugin.panel", "lfs.rendering") lf.ui.get_panel_names(lf.ui.PanelSpace.MAIN_PANEL_TAB) ``` -------------------------------- ### PointerProperty Source: https://lichtfeld.io/docs/api-reference Represents a property that points to another PropertyGroup. Allows getting or creating the referenced instance. ```APIDOC ## PointerProperty ### Description Represents a property that points to another PropertyGroup. Allows getting or creating the referenced instance. ### Methods - **get_instance()**: `PropertyGroup` - Get or create referenced object. ``` -------------------------------- ### File/Path Source: https://lichtfeld.io/docs/api-reference Provides a function for picking files or folders. ```APIDOC ## File/Path ### `path_input(label, value, folder_mode=True, dialog_title='')` #### Description Creates a file or folder picker input. #### Parameters * **label** (string) - Required - The label for the input. * **value** (str) - Required - The initial path value. * **folder_mode** (bool) - Optional - If True, allows folder selection; otherwise, file selection. Defaults to True. * **dialog_title** (str) - Optional - The title of the dialog window, defaults to ''. #### Returns * `(bool, str)` - A tuple containing (changed, new_path). `changed` is true if the path was modified. ``` -------------------------------- ### Define Training Settings with Diverse Properties Source: https://lichtfeld.io/docs/guide Illustrates the definition of a PropertyGroup subclass for training configurations, showcasing a wide range of property types including FloatProperty, IntProperty, BoolProperty, StringProperty, EnumProperty, FloatVectorProperty, and TensorProperty. ```python from lfs_plugins.props import ( PropertyGroup, FloatProperty, IntProperty, BoolProperty, StringProperty, EnumProperty, FloatVectorProperty, TensorProperty, ) class TrainingSettings(PropertyGroup): learning_rate = FloatProperty( default=0.001, min=0.0001, max=0.1, name="Learning Rate", description="Base learning rate for optimization", ) max_iterations = IntProperty(default=30000, min=1000, max=100000) use_ssim = BoolProperty(default=True, name="Use SSIM Loss") output_path = StringProperty(default="output", subtype="DIR_PATH") strategy = EnumProperty(items=[ ("mcmc", "MCMC", "Markov Chain Monte Carlo strategy"), ("default", "Default", "Default densification strategy"), ]) background_color = FloatVectorProperty( default=(0.0, 0.0, 0.0), size=3, subtype="COLOR" ) custom_mask = TensorProperty(shape=(-1,), dtype="bool", device="cuda") ``` -------------------------------- ### Open Checkpoint File Dialog Source: https://lichtfeld.io/docs/api-reference Opens a dialog to select a checkpoint file. ```python lf.ui.open_checkpoint_file_dialog() ``` -------------------------------- ### Get Current Theme Source: https://lichtfeld.io/docs/api-reference Retrieves the currently active theme object. This can be used to inspect theme properties. ```python lf.ui.theme() ``` -------------------------------- ### AppState Signals for Scene Source: https://lichtfeld.io/docs/guide Lists pre-defined signals for managing scene state, such as whether a scene is loaded, its generation status, and its file path. ```python # Scene AppState.has_scene # Signal[bool] AppState.scene_generation # Signal[int] - increments on scene change AppState.scene_path # Signal[str] ``` -------------------------------- ### PluginContext Creation Source: https://lichtfeld.io/docs/api-reference Build a PluginContext from the registry, optionally including view information. This context provides access to scene, view, and capabilities. ```python @dataclass class PluginContext: scene: Optional[SceneContext] view: Optional[ViewContext] capabilities: CapabilityBroker @classmethod def build(cls, registry, include_view=True) -> 'PluginContext': ... # Classmethod. Build from state ``` -------------------------------- ### Define a Custom Tool with Submodes and Pivot Modes Source: https://lichtfeld.io/docs/guide Create a tool definition that includes custom submodes (e.g., opacity, color, scale) and pivot modes (e.g., center, cursor). ```python from pathlib import Path from lfs_plugins.tool_defs.definition import ToolDef, SubmodeDef, PivotModeDef from lfs_plugins.tools import ToolRegistry paint_tool = ToolDef( id="my_plugin.paint", label="Paint", icon="paint", group="paint", order=100, description="Paint gaussian attributes", submodes=( SubmodeDef("opacity", "Opacity", "opacity"), SubmodeDef("color", "Color", "color"), SubmodeDef("scale", "Scale", "scale"), ), pivot_modes=( PivotModeDef("center", "Selection Center", "circle-dot"), PivotModeDef("cursor", "3D Cursor", "crosshair"), ), poll=lambda ctx: ctx.has_scene, plugin_name="my_plugin", plugin_path=str(Path(__file__).parent), ) ToolRegistry.register_tool(paint_tool) ``` -------------------------------- ### Get Panel IDs Source: https://lichtfeld.io/docs/api-reference Retrieves a list of panel IDs for a specified UI space, defaulting to floating panels. ```python lf.ui.get_panel_names(space=lf.ui.PanelSpace.FLOATING) ``` -------------------------------- ### Reactive Training Monitor Panel Source: https://lichtfeld.io/docs/guide A UI panel that displays real-time training statistics and a loss history plot. It subscribes to loss changes and updates its display accordingly. Requires `lichtfeld` and `lfs_plugins.ui`. ```python import lichtfeld as lf from lfs_plugins.ui.state import AppState from lfs_plugins.ui.signals import Signal class TrainingMonitor(lf.ui.Panel): label = "Training Monitor" space = lf.ui.PanelSpace.MAIN_PANEL_TAB order = 50 def __init__(self): self.best_loss = Signal(float("inf"), name="best_loss") self.loss_history = [] AppState.loss.subscribe_as("my_plugin", self._on_loss_change) def _on_loss_change(self, loss: float): if loss > 0: self.loss_history.append(loss) if loss < self.best_loss.value: self.best_loss.value = loss @classmethod def poll(cls, context) -> bool: return AppState.has_trainer.value def draw(self, ui): ui.heading("Training Monitor") state = AppState.trainer_state.value ui.label(f"State: {state}") ui.label(f"Iteration: {AppState.iteration.value}") ui.label(f"Loss: {AppState.loss.value:.6f}") ui.label(f"Best Loss: {self.best_loss.value:.6f}") ui.label(f"PSNR: {AppState.psnr.value:.2f}") ui.label(f"Gaussians: {AppState.num_gaussians.value:,}") progress = AppState.training_progress.value ui.progress_bar(progress, f"{progress * 100:.1f}%") if self.loss_history: ui.plot_lines( "Loss##monitor", self.loss_history[-200:], 0.0, max(self.loss_history[-200:]), (0, 80), ) ``` -------------------------------- ### Create a Boxed Container Layout Source: https://lichtfeld.io/docs/api-reference Use `ui.box()` to create a bordered container. This is useful for visually separating sections of your UI. Content within the box will have a border. ```python with ui.box() as box: box.heading("Settings") box.prop(self, "opacity") ``` -------------------------------- ### VS Code Debugpy Attach Configuration Source: https://lichtfeld.io/docs/guide VS Code launch configuration to attach the debugger to a running LichtFeld plugin process. ```json { "name": "Attach to LichtFeld Plugin", "type": "debugpy", "request": "attach", "connect": {"host": "localhost", "port": 5678} } ``` -------------------------------- ### Get Undo Stack Source: https://lichtfeld.io/docs/api-reference Retrieves the current undo/redo history as a structured dictionary. This can be useful for debugging or visualizing the history. ```python lf.undo.stack() -> dict ``` -------------------------------- ### Create an Execute-Only Operator Source: https://lichtfeld.io/docs/guide Define an operator that performs a specific action when executed. This example resets the opacity of all gaussians in the scene. ```python import lichtfeld as lf from lfs_plugins.types import Operator from lfs_plugins.props import FloatProperty class ResetOpacity(Operator): label = "Reset Opacity" description = "Set opacity of all gaussians to a given value" target_opacity: float = FloatProperty(default=1.0, min=0.0, max=1.0) @classmethod def poll(cls, context) -> bool: return lf.has_scene() def execute(self, context) -> set: scene = lf.get_scene() model = scene.combined_model() n = model.num_points mask = lf.Tensor.ones([n, 1], device="cuda") scaled = mask * self.target_opacity # Apply to opacity (working in logit space requires inverse sigmoid) lf.log.info(f"Reset {n} gaussians to opacity {self.target_opacity}") return {"FINISHED"} ``` -------------------------------- ### IntProperty Definition Source: https://lichtfeld.io/docs/api-reference Define an IntProperty with optional parameters for default value, min/max range, step, name, description, and update callback. ```python IntProperty( default: int = 0, min: int = -2**31, max: int = 2**31 - 1, step: int = 1, name: str = "", description: str = "", update: Callable = None, ) ``` -------------------------------- ### Scene Shortcuts Source: https://lichtfeld.io/docs/api-reference Module-level shortcuts for common scene operations. ```APIDOC ## Scene Shortcuts ### Description Module-level shortcuts for common scene operations, equivalent to `Scene` object methods. ### Functions - **`set_node_visibility(name, visible)`**: Toggle node visibility. Returns `None`. - **`remove_node(name, keep_children=False)`**: Remove a node. Optionally keep its children. Returns `None`. - **`reparent_node(name, new_parent)`**: Reparent a node to a new parent. Returns `None`. - **`rename_node(old_name, new_name)`**: Rename a node. Returns `None`. - **`add_group(name, parent="")`**: Add a group node. Returns `None`. - **`get_num_gaussians()`**: Get the total count of gaussians in the scene. Returns `int`. ``` -------------------------------- ### AppState Signals for Training Source: https://lichtfeld.io/docs/guide Provides a list of pre-defined signals related to the training process, including training status, iteration count, loss, and PSNR. ```python from lfs_plugins.ui.state import AppState # Training AppState.is_training # Signal[bool] AppState.trainer_state # Signal[str] - "idle", "ready", "running", "paused", "stopping" AppState.has_trainer # Signal[bool] AppState.iteration # Signal[int] AppState.max_iterations # Signal[int] AppState.loss # Signal[float] AppState.psnr # Signal[float] AppState.num_gaussians # Signal[int] ``` -------------------------------- ### Save Configuration File Source: https://lichtfeld.io/docs/api-reference Saves the current configuration to a specified file path. ```python lf.save_config_file(path: str) ``` -------------------------------- ### EnumProperty Definition Source: https://lichtfeld.io/docs/api-reference Define an EnumProperty with items, default value, name, description, and update callback. ```python EnumProperty( items: list[tuple[str, str, str]] = [], # (identifier, label, description) default: str = None, # First item if None name: str = "", description: str = "", update: Callable = None, ) ``` -------------------------------- ### Scene Access Source: https://lichtfeld.io/docs/guide Provides functions to get the current scene object and check if a scene is loaded. It also exposes the total count of Gaussian splats in the scene. ```APIDOC ## Scene Access ### Description Provides functions to get the current scene object and check if a scene is loaded. It also exposes the total count of Gaussian splats in the scene. ### Functions - **`lf.get_scene()`** - Returns the current scene object. Returns `None` if no scene is loaded. - **`lf.has_scene()`** - Returns `True` if a scene is loaded, `False` otherwise. ### Scene Object Attributes - **`scene.total_gaussian_count`** (int) - The total number of Gaussian splats in the scene. ### Request Example ```python import lichtfeld as lf scene = lf.get_scene() if lf.has_scene(): print(f"Total gaussians: {scene.total_gaussian_count}") ``` ``` -------------------------------- ### Styling Source: https://lichtfeld.io/docs/api-reference Methods for managing style variables and colors. ```APIDOC ## Styling ### `push_style_var(var, value)` **Description**: Pushes a float style variable. **Returns**: `None` ### `push_style_var_vec2(var, value)` **Description**: Pushes a vec2 style variable. **Returns**: `None` ### `pop_style_var(count=1)` **Description**: Pops style variables. **Returns**: `None` ### `push_style_color(col, color)` **Description**: Pushes a color override. **Returns**: `None` ### `pop_style_color(count=1)` **Description**: Pops color overrides. **Returns**: `None` ### `push_item_width(width)` / `pop_item_width()` **Description**: Manages the item width stack. **Returns**: `None` ### `begin_disabled(disabled=True)` / `end_disabled()` **Description**: Disables a widget region. For composable disabled regions, prefer `SubLayout.enabled`. **Returns**: `None` ``` -------------------------------- ### Tensor API - Creation Source: https://lichtfeld.io/docs/api-reference Functions for creating and initializing tensors with various properties. ```APIDOC ## Tensor API - Creation ### Description Provides functions for creating and initializing tensors. Tensors are fundamental data structures for numerical computation. ### Functions - `t.zeros(shape, device='cuda', dtype='float32')`: Creates a tensor filled with zeros. - `t.ones(shape, device, dtype)`: Creates a tensor filled with ones. - `t.full(shape, value, device, dtype)`: Creates a tensor filled with a constant value. - `t.eye(n, device, dtype)`: Creates an identity matrix. - `t.arange(start, end, step, device, dtype)`: Creates a tensor with values in a specified range. - `t.linspace(start, end, steps, device, dtype)`: Creates a tensor with linearly spaced values. - `t.rand(shape, device, dtype)`: Creates a tensor with random values uniformly distributed between 0 and 1. - `t.randn(shape, device, dtype)`: Creates a tensor with random values from a standard normal distribution. - `t.empty(shape, device, dtype)`: Creates an uninitialized tensor. - `t.randint(low, high, shape, device)`: Creates a tensor with random integers. - `t.from_numpy(arr, copy=True)`: Creates a tensor from a NumPy array. - `t.cat(tensors, dim=0)`: Concatenates a sequence of tensors along a given dimension. - `t.stack(tensors, dim=0)`: Stacks a sequence of tensors along a new dimension. - `t.where(condition, x, y)`: Selects elements from `x` or `y` based on a `condition` tensor. ``` -------------------------------- ### Transforms Source: https://lichtfeld.io/docs/guide Provides functionality to get and set the transformation matrix of nodes, as well as decompose a matrix into its translation, rotation (Euler angles), and scale components, and compose these components back into a matrix. ```APIDOC ## Transforms ### Description Provides functionality to get and set the transformation matrix of nodes, as well as decompose a matrix into its translation, rotation (Euler angles), and scale components, and compose these components back into a matrix. ### Functions - **`lf.get_node_transform(name: str)`** - Returns the 16-float column-major transformation matrix for the specified node. - **`lf.set_node_transform(name: str, matrix: Tensor)`** - Sets the transformation matrix for the specified node. - **`lf.decompose_transform(matrix: Tensor)`** - Decomposes a transformation matrix into its components. - Returns a dictionary with keys: `"translation"`, `"euler"`, `"scale"`. - **`lf.compose_transform(translation: list[float], euler_deg: list[float], scale: list[float])`** - Composes a transformation matrix from translation, Euler angles (in degrees), and scale components. - Returns the composed transformation matrix. ### Request Example ```python import lichtfeld as lf # Get/set as 16-float column-major matrix matrix = lf.get_node_transform("My Splat") lf.set_node_transform("My Splat", matrix) # Decompose/compose components = lf.decompose_transform(matrix) # components = {"translation": [x,y,z], "euler": [rx,ry,rz], "scale": [sx,sy,sz]} new_matrix = lf.compose_transform( translation=[1.0, 2.0, 3.0], euler_deg=[0.0, 45.0, 0.0], scale=[1.0, 1.0, 1.0], ) ``` ``` -------------------------------- ### PluginContext for Capability Handlers Source: https://lichtfeld.io/docs/guide Illustrates accessing scene, view, and other capabilities within a `PluginContext`. Requires `lfs_plugins.context`. ```python from lfs_plugins.context import PluginContext, SceneContext, ViewContext def handler(args: dict, ctx: PluginContext) -> dict: # Scene access if ctx.scene: ctx.scene.scene # PyScene object ctx.scene.set_selection_mask(mask) # Viewport access if ctx.view: ctx.view.image # [H, W, 3] tensor ctx.view.screen_positions # [N, 2] tensor or None ctx.view.width, ctx.view.height ctx.view.fov ctx.view.rotation # [3, 3] tensor ctx.view.translation # [3] tensor # Invoke other capabilities if ctx.capabilities.has("other_plugin.feature"): result = ctx.capabilities.invoke("other_plugin.feature", {"key": "value"}) return {"success": True} ``` -------------------------------- ### UI Layout API: Heading Text Source: https://lichtfeld.io/docs/api-reference Render text as a prominent heading. ```python heading(text) ``` -------------------------------- ### ThrottledSignal Initialization Source: https://lichtfeld.io/docs/api-reference Initialize a ThrottledSignal to control the rate of notifications. Useful for high-frequency updates. ```python ThrottledSignal(initial_value: T, max_rate_hz: float = 60.0, name: str = "") ``` -------------------------------- ### Set UI Theme Source: https://lichtfeld.io/docs/api-reference Switches the application's theme to either 'dark' or 'light'. ```python lf.ui.set_theme(name) ``` -------------------------------- ### Enable debugpy in Plugin Source: https://lichtfeld.io/docs/guide Add this code to your plugin's `on_load()` function to enable VS Code debugging by listening on a specific port. ```python def on_load(): try: import debugpy debugpy.listen(5678) lf.log.info("debugpy listening on port 5678") except ImportError: pass ```