HungryProton / scatter

Godot engine addon to randomly fill an area with props or other scenes
MIT License
2.08k stars 94 forks source link

Creating Scatter node and modifiers with code only #166

Open skalimoi opened 1 year ago

skalimoi commented 1 year ago

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

willcliffy commented 10 months ago

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:

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