use godot::{ classes::{FastNoiseLite, Resource}, obj::{Base, Gd}, prelude::{Export, GodotClass, GodotConvert, Var}, }; use crate::runtime::types::IntoRuntime; use fastnoise_lite::FastNoiseLite as RustNoise; #[derive(GodotConvert, Var, Export, Debug, Clone, Copy, PartialEq)] #[godot(via = i64)] pub enum WorldGeneratorType { Noise2D, Noise3D, Graph, Flat, } impl Default for WorldGeneratorType { fn default() -> Self { WorldGeneratorType::Noise2D } } #[derive(GodotClass, Debug)] #[class(init, base=Resource)] pub struct WorldGeneratorResource { #[base] base: Base, #[export] pub noise2d: Option>, } impl WorldGeneratorResource { fn convert_noise_type( ty: godot::classes::fast_noise_lite::NoiseType, ) -> fastnoise_lite::NoiseType { use fastnoise_lite::NoiseType as R; use godot::classes::fast_noise_lite::NoiseType as G; match ty { G::SIMPLEX => R::OpenSimplex2, G::SIMPLEX_SMOOTH => R::OpenSimplex2S, G::PERLIN => R::Perlin, G::VALUE => R::Value, G::VALUE_CUBIC => R::ValueCubic, G::CELLULAR => R::Cellular, _ => R::OpenSimplex2S, // reasonable default } } fn convert_fractal_type( ft: godot::classes::fast_noise_lite::FractalType, dft: godot::classes::fast_noise_lite::DomainWarpFractalType, ) -> fastnoise_lite::FractalType { use fastnoise_lite::FractalType as R; use godot::classes::fast_noise_lite::DomainWarpFractalType as D; use godot::classes::fast_noise_lite::FractalType as G; // Priority: domain-warp fractals first let domain_fractal = match dft { D::PROGRESSIVE => Some(R::DomainWarpProgressive), D::INDEPENDENT => Some(R::DomainWarpIndependent), D::NONE => None, _ => None, }; if let Some(df) = domain_fractal { return df; } // Then normal fractals match ft { G::NONE => R::None, G::FBM => R::FBm, G::RIDGED => R::Ridged, G::PING_PONG => R::PingPong, _ => R::None, } } fn convert_cellular_distance_function( fnc: godot::classes::fast_noise_lite::CellularDistanceFunction, ) -> fastnoise_lite::CellularDistanceFunction { use fastnoise_lite::CellularDistanceFunction as R; use godot::classes::fast_noise_lite::CellularDistanceFunction as G; match fnc { G::EUCLIDEAN => R::Euclidean, G::EUCLIDEAN_SQUARED => R::EuclideanSq, G::MANHATTAN => R::Manhattan, G::HYBRID => R::Hybrid, _ => R::Euclidean, } } fn convert_cellular_return_type( ret: godot::classes::fast_noise_lite::CellularReturnType, ) -> fastnoise_lite::CellularReturnType { use fastnoise_lite::CellularReturnType as R; use godot::classes::fast_noise_lite::CellularReturnType as G; match ret { G::CELL_VALUE => R::CellValue, G::DISTANCE => R::Distance, G::DISTANCE2 => R::Distance2, G::DISTANCE2_ADD => R::Distance2Add, G::DISTANCE2_SUB => R::Distance2Sub, G::DISTANCE2_MUL => R::Distance2Mul, G::DISTANCE2_DIV => R::Distance2Div, _ => R::CellValue, } } fn convert_domain_warp_type( warp: godot::classes::fast_noise_lite::DomainWarpType, ) -> fastnoise_lite::DomainWarpType { use fastnoise_lite::DomainWarpType as R; use godot::classes::fast_noise_lite::DomainWarpType as G; match warp { G::SIMPLEX => R::OpenSimplex2, G::SIMPLEX_REDUCED => R::OpenSimplex2Reduced, G::BASIC_GRID => R::BasicGrid, _ => R::OpenSimplex2, } } } impl IntoRuntime for WorldGeneratorResource { fn into_runtime(&self) -> RustNoise { match &self.noise2d { Some(noise) => { let mut rn = RustNoise::new(); rn.set_seed(Some(noise.get_seed())); rn.set_frequency(Some(noise.get_frequency())); rn.set_noise_type(Some(Self::convert_noise_type(noise.get_noise_type()))); rn.set_fractal_type(Some(Self::convert_fractal_type( noise.get_fractal_type(), noise.get_domain_warp_fractal_type(), ))); rn.set_cellular_distance_function(Some(Self::convert_cellular_distance_function( noise.get_cellular_distance_function(), ))); rn.set_cellular_return_type(Some(Self::convert_cellular_return_type( noise.get_cellular_return_type(), ))); rn.set_domain_warp_type(Some(Self::convert_domain_warp_type( noise.get_domain_warp_type(), ))); return rn; } None => return RustNoise::new(), } } }