using System.Collections; using System.Collections.Generic; using Godot; using System; namespace Rokojori { [Tool] [GlobalClass] public partial class GeneratorScatterer:Scatterer { [Export] public bool setDiscarded = true; [Export] public PackedScene packedScene; [Export] public Node3D container; [Export] public bool useGeneratorEntryFromChildren = true; [Export] public float childGeneratorNoiseScale = 1; [Export] public Vector3 childGeneratorNoiseOffset = Vector3.Zero; protected List childGenerators = new List(); protected List childGeneratorWeights = new List(); public void CreateWeights() { if ( ! useGeneratorEntryFromChildren ) { return; } childGenerators = Nodes.GetDirectChildren( this ); childGeneratorWeights = Lists.Map( childGenerators, c => c.probability ); var sum = 0f; childGeneratorWeights.ForEach( w => sum += w ); childGeneratorWeights = Lists.Map( childGeneratorWeights, c => c /= sum ); } public void AssginSceneAndContainer( ScatterPoint p ) { if ( ! useGeneratorEntryFromChildren ) { p.scene = packedScene; p.parent = container; } else { var value = Noise.Perlin( ( p.position + childGeneratorNoiseOffset ) * childGeneratorNoiseScale ); var index = _FindElementIndexWithWeights( childGeneratorWeights, value ); var gs = childGenerators[ index ]; p.scene = gs.GetPackedScene() != null ? gs.GetPackedScene() : packedScene; p.parent = gs.container != null ? gs.container : container; p.instanced = gs.useInstancing; } } int _FindElementIndexWithWeights( List weights, float value ) { var limit = 0f; for ( int i = 0; i < weights.Count; i++ ) { var before = limit; limit += weights[ i ]; if ( before <= value && value < limit ) { return i; } } return weights.Count - 1; } } }