rj-action-library/Runtime/Procedural/Scatter/Generators/GeneratorScatterer.cs

88 lines
2.0 KiB
C#

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<GeneratorEntry> childGenerators = new List<GeneratorEntry>();
protected List<float> childGeneratorWeights = new List<float>();
public void CreateWeights()
{
if ( ! useGeneratorEntryFromChildren )
{
return;
}
childGenerators = Nodes.GetDirectChildren<GeneratorEntry>( 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.packedScene != null ? gs.packedScene : packedScene;
p.parent = gs.container != null ? gs.container : container;
}
}
int _FindElementIndexWithWeights( List<float> 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;
}
}
}