Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
d20cbea
Add terrain layer functionality and curve layer implementation
lokejonatan Nov 9, 2025
4841ef9
Implement layer stamping functionality and enhance layer management i…
lokejonatan Nov 9, 2025
39af6fb
Add layer stamping functionality and finalize stamp layers in Terrain…
lokejonatan Nov 10, 2025
e363272
Enhance layer management by adding layer creation and selection funct…
lokejonatan Nov 10, 2025
953b24e
Refactor layer management by removing stamp-to-layer functionality an…
lokejonatan Nov 10, 2025
96c5204
Initialize layer payloads with default dimensions and coverage in Ter…
lokejonatan Nov 10, 2025
663f7bc
Refactor pixel blending logic in Terrain3DLayer to simplify color adj…
lokejonatan Nov 10, 2025
65e09e5
Add layer management methods for height, control, and color layers in…
lokejonatan Nov 10, 2025
842198c
Fix parameter order in _on_layer_selected function for consistency
lokejonatan Nov 11, 2025
d209b87
Add layer management functions for coverage and movement in Terrain3D…
lokejonatan Nov 11, 2025
6c1cd7f
Add LayerDemo script for managing demo layers in Terrain3D
lokejonatan Nov 11, 2025
afb4e3e
Add Terrain3DStampAnchor class for managing stamp layers in Terrain3D
lokejonatan Nov 11, 2025
f4d55b2
Add Terrain3DCurveLayerPath class for managing curve layers in Terrain3D
lokejonatan Nov 13, 2025
6ec477a
Add region size validation and height map handling in set_layer_cover…
lokejonatan Nov 13, 2025
c0c493e
Enhance payload management in Terrain3DLayer and Terrain3DCurveLayer …
lokejonatan Nov 13, 2025
1ecd878
Refactor intensity handling in Terrain3DLayer and adjust depth proper…
lokejonatan Nov 16, 2025
f1e02e7
Adjust depth property range in Terrain3DCurveLayerPath and remove red…
lokejonatan Nov 16, 2025
13082ee
Update documentation and refactor Terrain3DCurveLayer for improved he…
lokejonatan Nov 17, 2025
692b964
Add falloff_curve support to Terrain3DCurveLayerPath and Terrain3DLayer
lokejonatan Nov 17, 2025
0c092f2
Refactor region point mapping and curve sampling in Terrain3DCurveLay…
lokejonatan Nov 17, 2025
b222d0f
Connect height_maps_changed signal to refresh collision on height cha…
lokejonatan Nov 17, 2025
258027e
Add global stamp layer functionality and improve payload handling in …
lokejonatan Nov 21, 2025
93b9606
Add split_layer_payload_global_data method to Terrain3DData for enhan…
lokejonatan Nov 22, 2025
16b245a
Enhance layer management by introducing global layer collection and u…
lokejonatan Nov 22, 2025
2308e4a
Implement layer group management with allocation and retrieval functi…
lokejonatan Nov 23, 2025
a4295fa
Refactor layer handling to support group management and enhance layer…
lokejonatan Nov 23, 2025
4d1de17
Refactor layer assignment logic by removing stamp anchor selection me…
lokejonatan Nov 23, 2025
c849a03
Implement group management for Terrain3DStampAnchor with anchor ID ha…
lokejonatan Nov 24, 2025
7366738
Enhance collision handling and layer management by introducing a refr…
lokejonatan Nov 24, 2025
e34995f
Add user-editable property to Terrain3DLayer and enhance height range…
lokejonatan Nov 28, 2025
9725e40
Implement Terrain3DStampProjector class for managing baked Terrain3D …
lokejonatan Nov 28, 2025
1b36c1a
Refactor Terrain3D collision handling by removing obsolete refresh me…
lokejonatan Nov 30, 2025
5d04d56
Comment out texture asset connection logic in Terrain3D initialization
lokejonatan Dec 15, 2025
c24f2e4
Add documentation for non-destructive layer system architecture in Te…
lokejonatan Jan 3, 2026
712db90
Add external layer management for procedural tools in Terrain3D
lokejonatan Jan 10, 2026
e9d615c
Add external tool workflow for non-destructive layer management in Te…
lokejonatan Jan 11, 2026
ed6b797
Add force base fallback logic to layer painting in Terrain3DEditor
lokejonatan Jan 11, 2026
424a5ae
Add layer locking filter functionality to layer management UI
lokejonatan Jan 14, 2026
eec068d
Update C# bindings
lokejonatan Jan 11, 2026
3313b72
Removed the in-editor procedural helper nodes (StampAnchor / CurveLay…
lokejonatan Jan 18, 2026
35f91be
Update documentation for non-destructive layers to reflect new extern…
lokejonatan Jan 18, 2026
16f2371
Remove Terrain3DCurveLayer and related functionality from Terrain3D
lokejonatan Jan 18, 2026
9e6ade5
Add functional header inclusion in constants.h
lokejonatan Jan 2, 2026
3fed42c
Update C# bindings
lokejonatan Jan 18, 2026
452ceff
Remove LayerDemo script
lokejonatan Jan 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
591 changes: 591 additions & 0 deletions doc/docs/non_destructive_layers_architecture.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion doc/docs/tips_technical.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ This list are for items that don't already have dedicated pages in the documenta
| GPU Sculpting| [Pending](https://github.com/TokisanGames/Terrain3D/issues/174). Currently painting occurs on the CPU in C++. It's reasonably fast, but we have a soft limit of 200 on the brush size, as larger sizes lag.
| Holes | Holes work for both visual and collision.
| Jolt | [Godot-Jolt](https://github.com/godot-jolt/godot-jolt) was merged into Godot. Terrain3D works with both Godot and Jolt physics. Collision is generated where regions are defined.
| Non-destructive layers | Used for things like river beds, roads or paths that follow a curve and tweak the terrain. It's [possible](https://github.com/TokisanGames/Terrain3D/issues/129) in the future.
| Non-destructive layers | Supported via `Terrain3DData.set_map_layer()` (with optional `release_map_layer()` cleanup) so external generators can push fully baked textures into the layer stack without touching the base maps. Use deterministic `external_id` values per `(region, map_type)` to update an existing layer instead of spawning duplicates.
| Object placement | The [instancer](instancer.md) supports placing foliage. Placing objects that shouldn't be in a MultiMeshInstance node is [out of scope](https://github.com/TokisanGames/Terrain3D/issues/47). See 3rd party tools below.
| Streaming | There is no streaming built in to Godot. Region Streaming is [in progress](https://github.com/TokisanGames/Terrain3D/pull/675).
| Roads | Look at [Godot Road Generator](https://github.com/TheDuckCow/godot-road-generator/).
Expand Down
82 changes: 69 additions & 13 deletions project/addons/terrain_3d/csharp/Terrain3D.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

namespace TokisanGames;

[Tool]
public partial class Terrain3D : Node3D
{

Expand All @@ -28,10 +29,9 @@ protected Terrain3D() { }
/// <returns>The existing or a new instance of the <see cref="Terrain3D"/> wrapper script attached to the supplied <paramref name="godotObject"/>.</returns>
public new static Terrain3D Bind(GodotObject godotObject)
{
#if DEBUG
if (!IsInstanceValid(godotObject))
throw new InvalidOperationException("The supplied GodotObject instance is not valid.");
#endif
return null;

if (godotObject is Terrain3D wrapperScriptInstance)
return wrapperScriptInstance;

Expand Down Expand Up @@ -150,15 +150,20 @@ public event AssetsChangedSignalHandler AssetsChangedSignal
public new static readonly StringName CollisionMode = "collision_mode";
public new static readonly StringName CollisionShapeSize = "collision_shape_size";
public new static readonly StringName CollisionRadius = "collision_radius";
public new static readonly StringName CollisionTarget = "collision_target";
public new static readonly StringName CollisionLayer = "collision_layer";
public new static readonly StringName CollisionMask = "collision_mask";
public new static readonly StringName CollisionPriority = "collision_priority";
public new static readonly StringName PhysicsMaterial = "physics_material";
public new static readonly StringName CollisionTarget = "collision_target";
public new static readonly StringName ClipmapTarget = "clipmap_target";
public new static readonly StringName MeshLods = "mesh_lods";
public new static readonly StringName MeshSize = "mesh_size";
public new static readonly StringName VertexSpacing = "vertex_spacing";
public new static readonly StringName ClipmapTarget = "clipmap_target";
public new static readonly StringName TessellationLevel = "tessellation_level";
public new static readonly StringName DisplacementScale = "displacement_scale";
public new static readonly StringName DisplacementSharpness = "displacement_sharpness";
public new static readonly StringName BufferShaderOverrideEnabled = "buffer_shader_override_enabled";
public new static readonly StringName BufferShaderOverride = "buffer_shader_override";
public new static readonly StringName RenderLayers = "render_layers";
public new static readonly StringName MouseLayer = "mouse_layer";
public new static readonly StringName CastShadows = "cast_shadows";
Expand All @@ -182,9 +187,12 @@ public event AssetsChangedSignalHandler AssetsChangedSignal
public new static readonly StringName ShowControlScale = "show_control_scale";
public new static readonly StringName ShowColormap = "show_colormap";
public new static readonly StringName ShowRoughmap = "show_roughmap";
public new static readonly StringName ShowDisplacementBuffer = "show_displacement_buffer";
public new static readonly StringName ShowTextureAlbedo = "show_texture_albedo";
public new static readonly StringName ShowTextureHeight = "show_texture_height";
public new static readonly StringName ShowTextureNormal = "show_texture_normal";
public new static readonly StringName ShowTextureRough = "show_texture_rough";
public new static readonly StringName ShowTextureAo = "show_texture_ao";
}

public new string Version
Expand Down Expand Up @@ -279,6 +287,12 @@ public event AssetsChangedSignalHandler AssetsChangedSignal
set => Set(GDExtensionPropertyName.CollisionRadius, value);
}

public new Node3D CollisionTarget
{
get => Get(GDExtensionPropertyName.CollisionTarget).As<Node3D>();
set => Set(GDExtensionPropertyName.CollisionTarget, value);
}

public new long CollisionLayer
{
get => Get(GDExtensionPropertyName.CollisionLayer).As<long>();
Expand All @@ -303,10 +317,10 @@ public event AssetsChangedSignalHandler AssetsChangedSignal
set => Set(GDExtensionPropertyName.PhysicsMaterial, value);
}

public new Node3D CollisionTarget
public new Node3D ClipmapTarget
{
get => Get(GDExtensionPropertyName.CollisionTarget).As<Node3D>();
set => Set(GDExtensionPropertyName.CollisionTarget, value);
get => Get(GDExtensionPropertyName.ClipmapTarget).As<Node3D>();
set => Set(GDExtensionPropertyName.ClipmapTarget, value);
}

public new long MeshLods
Expand All @@ -327,10 +341,34 @@ public event AssetsChangedSignalHandler AssetsChangedSignal
set => Set(GDExtensionPropertyName.VertexSpacing, value);
}

public new Node3D ClipmapTarget
public new long TessellationLevel
{
get => Get(GDExtensionPropertyName.ClipmapTarget).As<Node3D>();
set => Set(GDExtensionPropertyName.ClipmapTarget, value);
get => Get(GDExtensionPropertyName.TessellationLevel).As<long>();
set => Set(GDExtensionPropertyName.TessellationLevel, value);
}

public new double DisplacementScale
{
get => Get(GDExtensionPropertyName.DisplacementScale).As<double>();
set => Set(GDExtensionPropertyName.DisplacementScale, value);
}

public new double DisplacementSharpness
{
get => Get(GDExtensionPropertyName.DisplacementSharpness).As<double>();
set => Set(GDExtensionPropertyName.DisplacementSharpness, value);
}

public new bool BufferShaderOverrideEnabled
{
get => Get(GDExtensionPropertyName.BufferShaderOverrideEnabled).As<bool>();
set => Set(GDExtensionPropertyName.BufferShaderOverrideEnabled, value);
}

public new Shader BufferShaderOverride
{
get => Get(GDExtensionPropertyName.BufferShaderOverride).As<Shader>();
set => Set(GDExtensionPropertyName.BufferShaderOverride, value);
}

public new long RenderLayers
Expand All @@ -345,9 +383,9 @@ public event AssetsChangedSignalHandler AssetsChangedSignal
set => Set(GDExtensionPropertyName.MouseLayer, value);
}

public new Variant CastShadows
public new long CastShadows
{
get => Get(GDExtensionPropertyName.CastShadows).As<Variant>();
get => Get(GDExtensionPropertyName.CastShadows).As<long>();
set => Set(GDExtensionPropertyName.CastShadows, value);
}

Expand Down Expand Up @@ -471,6 +509,18 @@ public event AssetsChangedSignalHandler AssetsChangedSignal
set => Set(GDExtensionPropertyName.ShowRoughmap, value);
}

public new bool ShowDisplacementBuffer
{
get => Get(GDExtensionPropertyName.ShowDisplacementBuffer).As<bool>();
set => Set(GDExtensionPropertyName.ShowDisplacementBuffer, value);
}

public new bool ShowTextureAlbedo
{
get => Get(GDExtensionPropertyName.ShowTextureAlbedo).As<bool>();
set => Set(GDExtensionPropertyName.ShowTextureAlbedo, value);
}

public new bool ShowTextureHeight
{
get => Get(GDExtensionPropertyName.ShowTextureHeight).As<bool>();
Expand All @@ -489,6 +539,12 @@ public event AssetsChangedSignalHandler AssetsChangedSignal
set => Set(GDExtensionPropertyName.ShowTextureRough, value);
}

public new bool ShowTextureAo
{
get => Get(GDExtensionPropertyName.ShowTextureAo).As<bool>();
set => Set(GDExtensionPropertyName.ShowTextureAo, value);
}

public new static class GDExtensionMethodName
{
public new static readonly StringName SetEditor = "set_editor";
Expand Down
14 changes: 11 additions & 3 deletions project/addons/terrain_3d/csharp/Terrain3DAssets.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

namespace TokisanGames;

[Tool]
public partial class Terrain3DAssets : Resource
{

Expand All @@ -28,10 +29,9 @@ protected Terrain3DAssets() { }
/// <returns>The existing or a new instance of the <see cref="Terrain3DAssets"/> wrapper script attached to the supplied <paramref name="godotObject"/>.</returns>
public new static Terrain3DAssets Bind(GodotObject godotObject)
{
#if DEBUG
if (!IsInstanceValid(godotObject))
throw new InvalidOperationException("The supplied GodotObject instance is not valid.");
#endif
return null;

if (godotObject is Terrain3DAssets wrapperScriptInstance)
return wrapperScriptInstance;

Expand Down Expand Up @@ -148,10 +148,12 @@ public event TexturesChangedSignalHandler TexturesChangedSignal
public new static readonly StringName GetTextureColors = "get_texture_colors";
public new static readonly StringName GetTextureNormalDepths = "get_texture_normal_depths";
public new static readonly StringName GetTextureAoStrengths = "get_texture_ao_strengths";
public new static readonly StringName GetTextureAoLightAffects = "get_texture_ao_light_affects";
public new static readonly StringName GetTextureRoughnessMods = "get_texture_roughness_mods";
public new static readonly StringName GetTextureUvScales = "get_texture_uv_scales";
public new static readonly StringName GetTextureVerticalProjections = "get_texture_vertical_projections";
public new static readonly StringName GetTextureDetiles = "get_texture_detiles";
public new static readonly StringName GetTextureDisplacements = "get_texture_displacements";
public new static readonly StringName ClearTextures = "clear_textures";
public new static readonly StringName UpdateTextureList = "update_texture_list";
public new static readonly StringName SetMeshAsset = "set_mesh_asset";
Expand Down Expand Up @@ -186,6 +188,9 @@ public event TexturesChangedSignalHandler TexturesChangedSignal
public new float[] GetTextureAoStrengths() =>
Call(GDExtensionMethodName.GetTextureAoStrengths, []).As<float[]>();

public new float[] GetTextureAoLightAffects() =>
Call(GDExtensionMethodName.GetTextureAoLightAffects, []).As<float[]>();

public new float[] GetTextureRoughnessMods() =>
Call(GDExtensionMethodName.GetTextureRoughnessMods, []).As<float[]>();

Expand All @@ -198,6 +203,9 @@ public event TexturesChangedSignalHandler TexturesChangedSignal
public new Vector2[] GetTextureDetiles() =>
Call(GDExtensionMethodName.GetTextureDetiles, []).As<Vector2[]>();

public new Vector2[] GetTextureDisplacements() =>
Call(GDExtensionMethodName.GetTextureDisplacements, []).As<Vector2[]>();

public new void ClearTextures(bool update = false) =>
Call(GDExtensionMethodName.ClearTextures, [update]);

Expand Down
6 changes: 3 additions & 3 deletions project/addons/terrain_3d/csharp/Terrain3DCollision.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

namespace TokisanGames;

[Tool]
public partial class Terrain3DCollision : GodotObject
{

Expand All @@ -28,10 +29,9 @@ protected Terrain3DCollision() { }
/// <returns>The existing or a new instance of the <see cref="Terrain3DCollision"/> wrapper script attached to the supplied <paramref name="godotObject"/>.</returns>
public new static Terrain3DCollision Bind(GodotObject godotObject)
{
#if DEBUG
if (!IsInstanceValid(godotObject))
throw new InvalidOperationException("The supplied GodotObject instance is not valid.");
#endif
return null;

if (godotObject is Terrain3DCollision wrapperScriptInstance)
return wrapperScriptInstance;

Expand Down
Loading