Skip to content

Commit

Permalink
Curve Modifiers can now be enabled and disabled
Browse files Browse the repository at this point in the history
  • Loading branch information
cmbasnett committed Aug 23, 2024
1 parent e101ca5 commit 835b3a5
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 103 deletions.
1 change: 1 addition & 0 deletions bdk_addon/property_group_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

def add_curve_modifier_properties(cls):
# Add the curve modifier properties to the type annotation of the given class.
cls.__annotations__['use_curve_modifiers'] = BoolProperty(name='Use Curve Modifiers', default=False)
cls.__annotations__['is_curve_reversed'] = BoolProperty(name='Reverse Curve', default=False) # TODO: Rename to curve_is_reversed
cls.__annotations__['curve_trim_mode'] = EnumProperty(name='Trim Mode', items=(('NONE', 'None', '', 0), ('FACTOR', 'Factor', '', 1),('LENGTH', 'Distance', '', 2),), default='NONE')
cls.__annotations__['curve_trim_factor_start'] = FloatProperty(name='Trim Factor Start', default=0.0, min=0.0, max=1.0, subtype='FACTOR')
Expand Down
47 changes: 29 additions & 18 deletions bdk_addon/terrain/doodad/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -604,32 +604,43 @@ def add_distance_to_doodad_layer_nodes(node_tree: NodeTree, layer, layer_type: s

match terrain_doodad.object.type:
case 'CURVE':
curve_modifier_node = node_tree.nodes.new(type='GeometryNodeGroup')
curve_modifier_node.node_tree = ensure_curve_modifier_node_tree()
def add_curve_modifier_nodes(node_tree: NodeTree, layer, layer_type, curve_socket: NodeSocket) -> NodeSocket:
switch_node = node_tree.nodes.new(type='GeometryNodeSwitch')
switch_node.input_type = 'GEOMETRY'

add_doodad_layer_driver(switch_node.inputs['Switch'], layer, layer_type, 'use_curve_modifiers')

modifier_node = node_tree.nodes.new(type='GeometryNodeGroup')
modifier_node.node_tree = ensure_curve_modifier_node_tree()

def add_curve_modifier_driver(input_name: str, data_path: str):
add_doodad_layer_driver(modifier_node.inputs[input_name], layer, layer_type, data_path)

# Drivers
add_curve_modifier_driver('Is Curve Reversed', 'is_curve_reversed')
add_curve_modifier_driver('Trim Mode', 'curve_trim_mode')
add_curve_modifier_driver('Trim Factor Start', 'curve_trim_factor_start')
add_curve_modifier_driver('Trim Factor End', 'curve_trim_factor_end')
add_curve_modifier_driver('Trim Length Start', 'curve_trim_length_start')
add_curve_modifier_driver('Trim Length End', 'curve_trim_length_end')
add_curve_modifier_driver('Normal Offset', 'curve_normal_offset')

# Links
node_tree.links.new(curve_socket, modifier_node.inputs['Curve'])
node_tree.links.new(curve_socket, switch_node.inputs['False'])
node_tree.links.new(modifier_node.outputs['Curve'], switch_node.inputs['True'])

return switch_node.outputs['Output']

distance_to_curve_node = node_tree.nodes.new(type='GeometryNodeGroup')
distance_to_curve_node.node_tree = ensure_distance_to_curve_node_group()

def add_curve_modifier_driver(input_name: str, data_path: str):
add_doodad_layer_driver(curve_modifier_node.inputs[input_name], layer, layer_type, data_path)
curve_socket = add_curve_modifier_nodes(node_tree, layer, layer_type, terrain_doodad_object_info_node.outputs['Geometry'])

# Drivers
add_curve_modifier_driver('Is Curve Reversed', 'is_curve_reversed')
add_curve_modifier_driver('Trim Mode', 'curve_trim_mode')
add_curve_modifier_driver('Trim Factor Start', 'curve_trim_factor_start')
add_curve_modifier_driver('Trim Factor End', 'curve_trim_factor_end')
add_curve_modifier_driver('Trim Length Start', 'curve_trim_length_start')
add_curve_modifier_driver('Trim Length End', 'curve_trim_length_end')
add_curve_modifier_driver('Normal Offset', 'curve_normal_offset')

# Links
node_tree.links.new(terrain_doodad_object_info_node.outputs['Geometry'],
curve_modifier_node.inputs['Curve'])
node_tree.links.new(curve_modifier_node.outputs['Curve'], distance_to_curve_node.inputs['Curve'])
node_tree.links.new(curve_socket, distance_to_curve_node.inputs['Curve'])

return distance_to_curve_node.outputs['Distance']
case 'MESH':
# TODO: set up a switch for points vs. faces
distance_to_mesh_node_group = ensure_distance_to_mesh_node_group()

# Add a new node group node.
Expand Down
80 changes: 35 additions & 45 deletions bdk_addon/terrain/doodad/scatter/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -1437,36 +1437,31 @@ def add_scatter_layer_driver(struct: bpy_struct, data_path: str, index: int = -1

spacing_length_socket = spacing_mode_switch_node.outputs['Output']

curve_modifier_group_node = node_tree.nodes.new(type='GeometryNodeGroup')
curve_modifier_group_node.node_tree = ensure_curve_modifier_node_tree()

add_scatter_layer_driver(curve_modifier_group_node.inputs['Is Curve Reversed'],
'is_curve_reversed')
add_scatter_layer_driver(curve_modifier_group_node.inputs['Trim Mode'], 'curve_trim_mode')
add_scatter_layer_driver(curve_modifier_group_node.inputs['Trim Factor Start'],
'curve_trim_factor_start')
add_scatter_layer_driver(curve_modifier_group_node.inputs['Trim Factor End'],
'curve_trim_factor_end')
add_scatter_layer_driver(curve_modifier_group_node.inputs['Trim Length Start'],
'curve_trim_length_start')
add_scatter_layer_driver(curve_modifier_group_node.inputs['Trim Length End'],
'curve_trim_length_end')
add_scatter_layer_driver(curve_modifier_group_node.inputs['Normal Offset'],
'curve_normal_offset')

curve_to_points_group_node = node_tree.nodes.new(type='GeometryNodeGroup')
curve_to_points_group_node.node_tree = ensure_scatter_layer_curve_to_points_node_tree()

add_scatter_layer_driver(curve_to_points_group_node.inputs['Normal Offset Max'],
'curve_normal_offset_max')
add_scatter_layer_driver(curve_to_points_group_node.inputs['Normal Offset Seed'],
'curve_normal_offset_seed')
add_scatter_layer_driver(curve_to_points_group_node.inputs['Tangent Offset Max'],
'curve_tangent_offset_max')
add_scatter_layer_driver(curve_to_points_group_node.inputs['Tangent Offset Seed'],
'curve_tangent_offset_seed')
add_scatter_layer_driver(curve_to_points_group_node.inputs['Global Seed'], 'global_seed')
add_scatter_layer_driver(curve_to_points_group_node.inputs['Fence Mode'], 'fence_mode')
curve_switch_node = node_tree.nodes.new(type='GeometryNodeSwitch')
curve_switch_node.input_type = 'GEOMETRY'

add_scatter_layer_driver(curve_switch_node.inputs['Switch'], 'use_curve_modifiers')

curve_modifier_node = node_tree.nodes.new(type='GeometryNodeGroup')
curve_modifier_node.node_tree = ensure_curve_modifier_node_tree()

add_scatter_layer_driver(curve_modifier_node.inputs['Is Curve Reversed'], 'is_curve_reversed')
add_scatter_layer_driver(curve_modifier_node.inputs['Trim Mode'], 'curve_trim_mode')
add_scatter_layer_driver(curve_modifier_node.inputs['Trim Factor Start'], 'curve_trim_factor_start')
add_scatter_layer_driver(curve_modifier_node.inputs['Trim Factor End'], 'curve_trim_factor_end')
add_scatter_layer_driver(curve_modifier_node.inputs['Trim Length Start'], 'curve_trim_length_start')
add_scatter_layer_driver(curve_modifier_node.inputs['Trim Length End'], 'curve_trim_length_end')
add_scatter_layer_driver(curve_modifier_node.inputs['Normal Offset'], 'curve_normal_offset')

curve_to_points_node = node_tree.nodes.new(type='GeometryNodeGroup')
curve_to_points_node.node_tree = ensure_scatter_layer_curve_to_points_node_tree()

add_scatter_layer_driver(curve_to_points_node.inputs['Normal Offset Max'], 'curve_normal_offset_max')
add_scatter_layer_driver(curve_to_points_node.inputs['Normal Offset Seed'], 'curve_normal_offset_seed')
add_scatter_layer_driver(curve_to_points_node.inputs['Tangent Offset Max'], 'curve_tangent_offset_max')
add_scatter_layer_driver(curve_to_points_node.inputs['Tangent Offset Seed'], 'curve_tangent_offset_seed')
add_scatter_layer_driver(curve_to_points_node.inputs['Global Seed'], 'global_seed')
add_scatter_layer_driver(curve_to_points_node.inputs['Fence Mode'], 'fence_mode')

shrinkwrap_curve_to_terrain_node = node_tree.nodes.new(type='GeometryNodeGroup')
shrinkwrap_curve_to_terrain_node.node_tree = ensure_shrinkwrap_curve_to_terrain_node_tree()
Expand All @@ -1479,27 +1474,22 @@ def add_scatter_layer_driver(struct: bpy_struct, data_path: str, index: int = -1
terrain_info_object_node = node_tree.nodes.new(type='GeometryNodeObjectInfo')
terrain_info_object_node.inputs['Object'].default_value = terrain_info.terrain_info_object

node_tree.links.new(terrain_doodad_object_info_node.outputs['Geometry'],
shrinkwrap_curve_to_terrain_node.inputs['Curve'])
node_tree.links.new(terrain_info_object_node.outputs['Geometry'],
shrinkwrap_curve_to_terrain_node.inputs['Terrain Geometry'])
node_tree.links.new(terrain_doodad_object_info_node.outputs['Geometry'], shrinkwrap_curve_to_terrain_node.inputs['Curve'])
node_tree.links.new(terrain_info_object_node.outputs['Geometry'], shrinkwrap_curve_to_terrain_node.inputs['Terrain Geometry'])
node_tree.links.new(terrain_info_object_node.outputs['Transform'], shrinkwrap_curve_to_terrain_node.inputs['Terrain Transform'])

node_tree.links.new(shrinkwrap_curve_to_terrain_node.outputs['Curve'],
shrinkwrap_curve_to_terrain_switch_node.inputs['True'])
node_tree.links.new(terrain_doodad_object_info_node.outputs['Geometry'],
shrinkwrap_curve_to_terrain_switch_node.inputs['False'])
node_tree.links.new(shrinkwrap_curve_to_terrain_node.outputs['Curve'], shrinkwrap_curve_to_terrain_switch_node.inputs['True'])
node_tree.links.new(terrain_doodad_object_info_node.outputs['Geometry'], shrinkwrap_curve_to_terrain_switch_node.inputs['False'])

node_tree.links.new(shrinkwrap_curve_to_terrain_switch_node.outputs['Output'],
curve_modifier_group_node.inputs['Curve'])
node_tree.links.new(curve_modifier_group_node.outputs['Curve'],
curve_to_points_group_node.inputs['Curve'])
node_tree.links.new(shrinkwrap_curve_to_terrain_switch_node.outputs['Output'], curve_modifier_node.inputs['Curve'])
node_tree.links.new(shrinkwrap_curve_to_terrain_switch_node.outputs['Output'], curve_switch_node.inputs['False'])
node_tree.links.new(curve_modifier_node.outputs['Curve'], curve_switch_node.inputs['True'])
node_tree.links.new(curve_switch_node.outputs['Output'], curve_to_points_node.inputs['Curve'])

if spacing_length_socket is not None:
node_tree.links.new(spacing_length_socket,
curve_to_points_group_node.inputs['Spacing Length'])
node_tree.links.new(spacing_length_socket, curve_to_points_node.inputs['Spacing Length'])

points_socket = curve_to_points_group_node.outputs['Points']
points_socket = curve_to_points_node.outputs['Points']
case 'EMPTY':
# TODO: we're gonna certainly want more options here (e.g., random distance/angle from the
# center)
Expand Down
87 changes: 47 additions & 40 deletions bdk_addon/terrain/doodad/ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -567,28 +567,32 @@ def draw(self, context: 'Context'):
flow.prop(scatter_layer, 'fence_mode')
flow.separator()

# Curve settings
draw_curve_modifier_settings(flow, scatter_layer, curve_data=terrain_doodad.object.data)

flow.separator()
flow.prop(scatter_layer, 'curve_spacing_method')

match scatter_layer.curve_spacing_method:
case'RELATIVE':
flow.prop(scatter_layer, 'curve_spacing_relative_axis', text='Axis')
flow.prop(scatter_layer, 'curve_spacing_relative_factor', text='Factor')
case 'ABSOLUTE':
flow.prop(scatter_layer, 'curve_spacing_absolute', text='Distance')

flow.separator()

flow.prop(scatter_layer, 'curve_normal_offset_max', text='Normal Offset Max')
flow.prop(scatter_layer, 'curve_normal_offset_seed', text='Seed')

flow.separator()

flow.prop(scatter_layer, 'curve_tangent_offset_max', text='Tangent Offset Max')
flow.prop(scatter_layer, 'curve_tangent_offset_seed', text='Seed')
# Curve Modifiers
draw_curve_modifier_settings(flow, scatter_layer)

# Spacing
spacing_header, spacing_panel = flow.panel('Spacing', default_closed=True)
spacing_header.label(text='Spacing')
if spacing_panel:
col = spacing_panel.column(align=True)
col.prop(scatter_layer, 'curve_spacing_method')
match scatter_layer.curve_spacing_method:
case'RELATIVE':
col.prop(scatter_layer, 'curve_spacing_relative_axis', text='Axis')
col.prop(scatter_layer, 'curve_spacing_relative_factor', text='Factor')
case 'ABSOLUTE':
col.prop(scatter_layer, 'curve_spacing_absolute', text='Distance')

# Offsets
offsets_header, offsets_panel = flow.panel('Offsets', default_closed=True)
offsets_header.label(text='Offsets')
if offsets_panel:
col = offsets_panel.column(align=True)
col.prop(scatter_layer, 'curve_normal_offset_max', text='Normal Offset Max')
col.prop(scatter_layer, 'curve_normal_offset_seed', text='Seed')
col.separator()
col.prop(scatter_layer, 'curve_tangent_offset_max', text='Tangent Offset Max')
col.prop(scatter_layer, 'curve_tangent_offset_seed', text='Seed')


def get_selected_terrain_doodad_scatter_layer_object(context: Context):
Expand Down Expand Up @@ -867,24 +871,27 @@ def draw(self, context):
flow.prop(scatter_layer, 'actor_group', text='Group')


def draw_curve_modifier_settings(layout: UILayout, data, curve_data: Curve = None):
layout.prop(data, 'is_curve_reversed')
layout.prop(data, 'curve_normal_offset')

layout.separator()

layout.prop(data, 'curve_trim_mode')

if data.curve_trim_mode == 'FACTOR':
col = layout.column(align=True)
col.prop(data, 'curve_trim_factor_start', text='Trim Start')
col.prop(data, 'curve_trim_factor_end', text='End')
if data.curve_trim_factor_start >= data.curve_trim_factor_end:
layout.label(text='Trim start should be less than trim end', icon='ERROR')
elif data.curve_trim_mode == 'LENGTH':
col = layout.column(align=True)
col.prop(data, 'curve_trim_length_start', text='Trim Start')
col.prop(data, 'curve_trim_length_end', text='End')
def draw_curve_modifier_settings(layout: UILayout, data):
curve_modifier_header, curve_modifier_panel = layout.panel('Curve Modifiers', default_closed=True)
curve_modifier_header.use_property_split = False
curve_modifier_header.prop(data, 'use_curve_modifiers', text='Curve Modifiers')
if curve_modifier_panel:
curve_modifier_panel.prop(data, 'is_curve_reversed')
curve_modifier_panel.prop(data, 'curve_normal_offset')
curve_modifier_panel.separator()
curve_modifier_panel.prop(data, 'curve_trim_mode')

match data.curve_trim_mode:
case 'FACTOR':
col = curve_modifier_panel.column(align=True)
col.prop(data, 'curve_trim_factor_start', text='Trim Start')
col.prop(data, 'curve_trim_factor_end', text='End')
if data.curve_trim_factor_start >= data.curve_trim_factor_end:
curve_modifier_panel.label(text='Trim start should be less than trim end', icon='ERROR')
case 'LENGTH':
col = curve_modifier_panel.column(align=True)
col.prop(data, 'curve_trim_length_start', text='Trim Start')
col.prop(data, 'curve_trim_length_end', text='End')


class BDK_PT_terrain_doodad_scatter_layer_settings(Panel):
Expand Down

0 comments on commit 835b3a5

Please sign in to comment.