Bevy Plugins

The Foresight Development Kit is built on the Bevy Engine. Instead of papering over its internals, we lean into Bevy’s modularity, meaning that every plugin you build is, at its heart, a Bevy Plugin. This architectural decision gives you unrestricted access to underlying engine features, allowing you to build everything from simple UI tweaks to entirely new rendering pipelines.

Extending the Engine

When you implement a Bevy plugin within the SDK, you are working with the framework’s core building blocks. You can define Systems to handle frame-by-frame logic, manage global Resources, or attach Components to entities in the 3D scene.

This level of access is what allows the Foresight Development Kit to be so extensible. If the high-level SDK primitives don’t quite fit your needs, you can always drop down to Bevy code, because application logic and the underlying runtime are one and the same.

use fdk::libs::prelude::*;

pub struct MyCustomPlugin;

impl Plugin for MyCustomPlugin {
    fn build(&self, app: &mut App) {
        app.insert_resource(MyGlobalConfig::default())
           .add_event::<MyCustomEvent>()
           .add_systems(Update, my_update_system);
    }
}

fn my_update_system(config: Res<MyGlobalConfig>) {
    // This system runs alongside the core SDK systems
}

Deep Customization

Because you are working with native Bevy plugins, the entire framework is your playground:

  • Custom Rendering: You can implement specialized rendering logic for domain-specific data types that aren’t covered by the standard point cloud or mesh representations.
  • Render Graph Modification: If your application needs custom post-processing, compute shaders, or specialized multi-pass rendering, you can extend Bevy’s render graph directly.
  • Execution Timing: By adding systems to core schedules like PreUpdate or PostUpdate, you can ensure your logic runs at the exact moment required relative to the SDK’s own internal systems.

When to use Bevy vs. SDK Primitives

A common question for new developers is when to use a raw Bevy system versus an SDK-specific primitive like a Tool, Object, or Statement.

While Bevy provides the engine, the SDK provides the infrastructure. By building with SDK primitives, you gain access to a suite of enterprise-grade features that would otherwise require significant custom implementation:

  • Cloud Versioning & Collaboration: Objects created via the SDK are automatically integrated into the versioned object model. This means multi-user synchronization, branching, and atomic commits work out of the box.
  • Massive Data Streaming: SDK representations (like Point Clouds and Block Models) are powered by Dagger and Volumesight. They stream incrementally from the cloud, allowing your tools to handle terabytes of data with minimal local memory overhead.
  • Integrated Undo-Redo: When you execute logic via SDK Statements, the system automatically tracks changes. Users get full undo-redo support for your custom workflows without you writing a single line of state-management code.
  • Cross-Platform Scripting: Features built with SDK primitives can often be exposed to the Runtime Extensions (WASM) system, allowing end-users to automate your tools using scripts.

The Golden Rule: Use Bevy Plugins for low-level systems like custom rendering, hardware integration, or real-time simulation logic.

Use SDK Primitives for user-facing features such as creating objects, modifying project state, and defining high-level workflows.

For example, a real-time physics solver is best implemented as a Bevy Plugin. However, the UI to control it, the parameters stored in the project, and the final “baked” results should be handled via SDK primitives. This ensures they are automatically saved, versioned, and synchronized.