rj-action-library/Runtime/Rendering/Assets/Foliage/FoliageRenderer.cs

188 lines
3.9 KiB
C#
Raw Normal View History

2025-07-17 11:50:37 +00:00
using System.Collections;
using System.Collections.Generic;
using Godot;
using System;
using System.Threading.Tasks;
using System.Linq;
namespace Rokojori
{
/** <summary for="class FoliageRenderer">
<title>
A node to render foliage.
</title>
<description>
The GrassPatch has various settings to create a different styles of grass.
It allows to change the shapes of the blades, their number and distribution, their triangle count,
rotation and scale, LOD levels and much more.
</description>
</summary>
*/
[Tool]
[GlobalClass, Icon("res://addons/rokojori_action_library/Icons/Scatterer.svg") ]
2025-07-18 12:06:09 +00:00
public partial class FoliageRenderer:Node3D
2025-07-17 11:50:37 +00:00
{
2025-08-31 06:05:39 +00:00
[ExportToolButton( "Update Layers" )]
public Callable updateLayersButton => Callable.From( ()=> updateLayers = true ) ;
2025-07-17 11:50:37 +00:00
[Export]
2025-07-18 12:06:09 +00:00
public FoliageData[] foliage = [];
2025-07-17 11:50:37 +00:00
2025-07-19 06:22:56 +00:00
2025-08-31 06:05:39 +00:00
[ExportGroup("Quality")]
2025-07-18 14:45:23 +00:00
[Export( PropertyHint.Range, "0, 200" )]
public float quality = 100;
[Export]
public FoliageQualitySettings[] qualitySettingsAll;
2025-08-31 06:05:39 +00:00
[ExportGroup("Shared")]
[Export]
public Camera3D camera;
[Export]
public Texture2D noise;
[Export]
public int renderPriorityOffset = 0;
[ExportGroup("Obstacles")]
2025-07-19 06:22:56 +00:00
[Export]
public Node3D[] obstacles = [];
[Export]
public float[] obstacleSizes = [];
Vector4[] obstaclesData = new Vector4[4];
public Vector4 GetObstacleData( int index )
{
return obstaclesData[ index ];
}
2025-07-17 11:50:37 +00:00
List<FoliageRenderLayer> renderLayers = [];
[Export]
public bool processLayers = true;
public bool updateLayers = true;
2025-08-31 06:05:39 +00:00
2025-07-17 11:50:37 +00:00
Camera3D _assignedCamera;
2025-08-31 06:05:39 +00:00
2025-07-17 11:50:37 +00:00
public Camera3D GetAssignedCamera()
{
return _assignedCamera;
}
2025-08-31 06:05:39 +00:00
public int numFoliageLayers
{
get
{
var numLayers = 0;
foliage.ForEach( fd => numLayers += fd.numLayers );
return numLayers;
}
}
2025-07-17 11:50:37 +00:00
public override void _Process( double delta )
{
_assignedCamera = null;
2025-07-18 12:06:09 +00:00
if ( ! processLayers || foliage == null || foliage.Length == 0 )
2025-07-17 11:50:37 +00:00
{
return;
}
2025-07-18 12:06:09 +00:00
2025-08-31 06:05:39 +00:00
if ( updateLayers || numFoliageLayers != renderLayers.Count )
2025-07-17 11:50:37 +00:00
{
updateLayers = false;
this.DestroyChildren();
2025-08-31 06:05:39 +00:00
renderLayers = new List<FoliageRenderLayer>();
foliage.ForEach(
( fd )=>
{
renderLayers.Add( FoliageRenderLayer.Create( this, fd ) );
for ( int i = 0; fd.subLayers != null && i < fd.subLayers.Length; i++ )
{
if ( fd.subLayers[ i ] == null )
{
continue;
}
renderLayers.Add( FoliageRenderLayer.Create( this, fd, i ) );
}
}
);
this.LogInfo( "Initialize:", renderLayers.Count );
2025-07-17 11:50:37 +00:00
renderLayers.ForEach( r => r.data.Initialize( r ) );
2025-08-31 06:05:39 +00:00
2025-07-17 11:50:37 +00:00
}
2025-07-19 06:22:56 +00:00
if ( obstaclesData.Length != 4 )
{
obstaclesData = new Vector4[ 4];
}
for ( int i = 0; i < obstaclesData.Length; i++ )
{
var position = obstacles == null || i >= obstacles.Length ? Vector3.Zero : obstacles[ i ].GlobalPosition;
var size = obstacleSizes == null || i >= obstacleSizes.Length ? 0 : obstacleSizes[ i ];
obstaclesData[ i ] = new Vector4( position.X, position.Y, position.Z, size );
}
2025-07-17 11:50:37 +00:00
if ( Engine.IsEditorHint() )
{
_assignedCamera = EditorInterface.Singleton.GetEditorViewport3D().GetCamera3D();
}
else
{
_assignedCamera = camera;
}
if ( _assignedCamera == null )
{
return;
}
// this.LogInfo( "Processing", renderLayers.Count );
2025-07-18 12:06:09 +00:00
renderLayers.ForEach( r =>
{
if ( r == null )
{
return;
}
r.Update( delta );
}
);
2025-07-17 11:50:37 +00:00
}
}
}