scatter icon indicating copy to clipboard operation
scatter copied to clipboard

Creating Scatter node and modifiers with code only

Open skalimoi opened this issue 1 year ago • 1 comments

Hey there. I want to use ProtonScatter for procedurally generated worlds on runtime, so using the editor tool is a no-go. After reading the code a bit, I tried my hand at creating both a base node and modifiers in a script:

# class preloading
const ProtonScatter := preload("res://addons/proton_scatter/src/scatter.gd")
const ClusterizeModifier := preload("res://addons/proton_scatter/src/modifiers/clusterize.gd")
const ProjectModifier := preload("res://addons/proton_scatter/src/modifiers/project_on_geometry.gd")
const RelaxModifier := preload("res://addons/proton_scatter/src/modifiers/relax.gd")
const RandomizeTransformModifier := preload("res://addons/proton_scatter/src/modifiers/randomize_transforms.gd")
const CreateInsideRandomModifier := preload("res://addons/proton_scatter/src/modifiers/create_inside_random.gd")
const ProtonScatterItem := preload("res://addons/proton_scatter/src/scatter_item.gd")
const ProtonScatterShape := preload("res://addons/proton_scatter/src/scatter_shape.gd")

func ready:
    # create base node and stack
    var node: ProtonScatter = ProtonScatter.new()
    var stack = node.ProtonScatterModifierStack.new()

    # create modifier
    var clusterize_modifier := ClusterizeModifier.new()
    var project_modifier:= ProjectModifier.new()
    var relax_modifier := RelaxModifier.new()
    var randomize_modifier := RandomizeTransformModifier.new()
    var create_inside_modifier := CreateInsideRandomModifier.new()

    # add modifiers to stack in same order as editor - supposing that clusterize is the last modifier
    stack.add(create_inside_modifier)
    stack.add(randomize_modifier)
    stack.add(relax_modifier)
    stack.add(project_modifier)
    stack.add(clusterize_modifier)

    # replicate tree structure - shape and item
    var item_node := ProtonScatterItem.new()
    var shape_node := ProtonScatterShape.new()
    node.add_child(item_node)
    node.add_child(shape_node)
    
    # assign stack
    node.modifier_stack = stack

Bear in mind I excluded most parameters when creating new modifiers as the script would get too long for this post.

So my question is: am I doing it right? I'm not getting the same results than when using the node in the editor - the game gets stuck or doesn't apply the transformations right. There is no documentation about this so I feel like I'm beating around the bush.

Thanks

skalimoi avatar Oct 04 '23 10:10 skalimoi

I've been working on a procedural generation project with a similar need. I'm not sure if this works for your use case, but I have found success with this strategy:

  • Create a scene that contains a ProtonScatter node. Configure it in-editor.
  • Generate your terrain as normal at runtime.
  • Call $ProtonScatter.rebuild.call_deferred() for Scatter to pick up any changes.

A hacky example can be found here, using Godot 4.1.3. I've found that this doesn't work for me when I place the 3D scene in a Viewport, but I still need to look into why.

scatter_runtime_demo

willcliffy avatar Nov 27 '23 05:11 willcliffy