feat: add some docs

This commit is contained in:
dusk 2024-08-29 15:49:23 +03:00
parent 07405168e8
commit ac91b9a53e
Signed by: dusk
SSH Key Fingerprint: SHA256:Abmvag+juovVufZTxyWY8KcVgrznxvBjQpJesv071Aw
8 changed files with 48 additions and 17 deletions

View File

@ -3,8 +3,8 @@ extends EditorPlugin
func _enter_tree() -> void:
add_autoload_singleton("BoidsProcess_2D", "res://addons/boids/boids_process_2d.tscn")
add_autoload_singleton("ProcessBoids", "res://addons/boids/process_boids.tscn")
func _exit_tree() -> void:
remove_autoload_singleton("BoidsProcess_2D")
remove_autoload_singleton("ProcessBoids")

View File

@ -1,4 +1,3 @@
[gd_scene format=3 uid="uid://c84c62urmhxbm"]
[node name="BoidsProcess" type="BoidsProcess"]
process_2d = true

View File

@ -2,7 +2,7 @@ extends Node2D
func _ready() -> void:
for flock in get_children():
for i in 1000: spawnBoid(flock)
for i in 100: spawnBoid(flock)
func spawnBoid(flock: Flock2D) -> void:
var boid: Boid2D = preload("../example_boid.tscn").instantiate()

View File

@ -7,6 +7,8 @@ use crate::{BoidProperties, Flock2D};
#[class(init, base=Node2D)]
pub struct Boid2D {
#[export]
/// The properties of this boid.
/// Note: this cannot be changed in runtime, aside from removing and readding the node.
properties: Gd<BoidProperties>,
props: BoidProperties,
vel: Vec2,
@ -18,18 +20,21 @@ pub struct Boid2D {
impl Boid2D {
#[func]
#[inline(always)]
/// Get the current velocity of this boid.
fn get_velocity(&self) -> Vector2 {
Vector2::new(self.vel.x, self.vel.y)
}
#[func]
#[inline(always)]
/// Get the ID of this boid.
pub fn get_id(&self) -> i64 {
self.base().instance_id().to_i64()
}
#[func]
#[inline(always)]
/// Get the flock ID of this boid.
pub fn get_flock_id(&self) -> i64 {
self.flock_id
}

View File

@ -5,20 +5,26 @@ use godot::prelude::*;
pub struct BoidProperties {
#[export]
#[init(val = 4.0)]
/// Max speed of this boid.
pub max_speed: f32,
#[export]
#[init(val = 1.0)]
/// Max force that will be applied to this boid at once.
pub max_force: f32,
#[export]
#[init(val = 1.5)]
/// How much to align with other boids.
pub alignment: f32,
#[export]
#[init(val = 1.0)]
/// How much to cohere to other boids.
pub cohesion: f32,
#[export]
#[init(val = 1.2)]
/// How much to seperate from other boids.
pub seperation: f32,
#[export]
#[init(val = 0.8)]
/// How much to follow a flock target (if there is one).
pub targeting: f32,
}

View File

@ -9,9 +9,12 @@ use super::Flock;
#[class(init, base=Node2D)]
pub struct Flock2D {
#[export]
/// Properties of this flock.
/// Note: this cannot be changed in runtime, aside from removing and readding the node.
properties: Gd<FlockProperties>,
props: FlockProperties,
#[export]
/// A target node for the flock to follow.
target: Option<Gd<Node2D>>,
pub boids: FxIndexMap<i64, Gd<Boid2D>>,
base: Base<Node2D>,

View File

@ -5,14 +5,14 @@ use godot::prelude::*;
pub struct FlockProperties {
#[export]
#[init(val = 625.0)]
/// squared
/// Distance (squared) to apply seperation force between boids in a flock.
pub goal_seperation: f32,
#[export]
#[init(val = 2500.0)]
/// squared
/// Distance (squared) to apply alignment force between boids in a flock.
pub goal_alignment: f32,
#[export]
#[init(val = 2500.0)]
/// squared
/// Distance (squared) to apply cohesion force between boids in a flock.
pub goal_cohesion: f32,
}

View File

@ -73,13 +73,20 @@ unsafe impl ExtensionLibrary for BoidsExtension {
#[derive(GodotClass)]
#[class(init, base=Node)]
/// Node that will make calls automatically to process 2D/3D boids, providing some configuration options.
/// It's best to use this as an autoload singleton.
pub struct BoidsProcess {
#[export]
#[init(val = true)]
/// Whether to process 2D boids or not.
process_2d: bool,
#[export]
#[init(val = true)]
/// Whether to process 3D boids or not.
process_3d: bool,
#[export]
#[init(val = 1)]
/// Process boids per N physics ticks.
process_per_tick: i64,
boids: Option<Gd<Boids>>,
engine: Option<Gd<Engine>>,
@ -117,6 +124,7 @@ impl INode for BoidsProcess {
#[derive(GodotClass)]
#[class(init, base=Object)]
/// Singleton that holds all boids and flocks and manages them.
struct Boids {
flocks2d: FxIndexMap<i64, Gd<Flock2D>>,
boids2d: FxIndexMap<i64, Gd<Boid2D>>,
@ -150,15 +158,25 @@ impl Boids {
impl Boids {
#[func]
#[inline(always)]
/// Process all 2D boids once.
/// NOTE: This function is not intended to be manually called. Prefer using `BoidsProcess` as an autoload singleton where possible.
fn process_boids_2d(&mut self) {
process_boids(&mut self.boids2d, &self.flocks2d)
}
#[func]
#[inline(always)]
fn get_total_boid_count(&self) -> i64 {
/// Gets the total 2D boid count.
fn get_total_boid_2d_count(&self) -> i64 {
self.boids2d.len() as i64
}
#[func]
#[inline(always)]
/// Gets the total 2D flock count.
fn get_total_flock_2d_count(&self) -> i64 {
self.flocks2d.len() as i64
}
}
#[inline(always)]
@ -202,8 +220,8 @@ where
}
#[cfg(feature = "stats")]
godot_print!(
"[Boids] preparing all calculations took {} ms",
time.elapsed().as_millis()
"[Boids] preparing all calculations took {} micros",
time.elapsed().as_micros()
);
#[cfg(feature = "stats")]
@ -211,7 +229,7 @@ where
let forces: Vec<(i64, Vec3)> = calc_funcs
.into_par_iter()
.fold(
|| Vec::<(i64, Vec3)>::with_capacity(total_boid_count / 10),
|| Vec::<(i64, Vec3)>::with_capacity(total_boid_count),
|mut acc, (boid_id, calc_fn)| {
let force = calc_fn();
acc.push((boid_id, force));
@ -219,7 +237,7 @@ where
},
)
.reduce(
|| Vec::<(i64, Vec3)>::with_capacity(total_boid_count / 10),
|| Vec::<(i64, Vec3)>::with_capacity(total_boid_count),
|mut left, mut right| {
left.append(&mut right);
left
@ -227,19 +245,19 @@ where
);
#[cfg(feature = "stats")]
godot_print!(
"[Boids] calculating all boids took {} ms",
time.elapsed().as_millis()
"[Boids] calculating all boids took {} micros",
time.elapsed().as_micros()
);
#[cfg(feature = "stats")]
let time = std::time::Instant::now();
for (boid_id, force) in forces {
let boid = boids.get_mut(&boid_id).unwrap();
let boid = unsafe { boids.get_mut(&boid_id).unwrap_unchecked() };
boid.bind_mut().apply_force(force);
}
#[cfg(feature = "stats")]
godot_print!(
"[Boids] applying forces took {} ms",
time.elapsed().as_millis()
"[Boids] applying forces took {} micros",
time.elapsed().as_micros()
);
}