Files
fps_project_1/addons/dreadpon.spatial_gardener/toolshed/toolshed_brush.gd

297 lines
10 KiB
GDScript

@tool
extends "../utility/input_field_resource/input_field_resource.gd"
#-------------------------------------------------------------------------------
# All the data that reflects a brush behavior
#-------------------------------------------------------------------------------
const Globals = preload("../utility/globals.gd")
enum BrushType {PAINT, ERASE, SINGLE, REAPPLY}
enum OverlapMode {VOLUME, PROJECTION}
var behavior_brush_type:int = BrushType.PAINT
var shape_volume_size:float = 1.0
var shape_projection_size:float = 1.0
var behavior_strength:float = 1.0
var behavior_passthrough: bool = false
var behavior_overlap_mode: int = OverlapMode.VOLUME
var behavior_no_settings_text: String = 'This brush has no additional settings'
#-------------------------------------------------------------------------------
# Initialization
#-------------------------------------------------------------------------------
func _init(__behavior_brush_type:int = BrushType.PAINT, __behavior_strength:float = 1.0, __shape_volume_size:float = 1.0,
__shape_projection_size:float = 1.0, __behavior_passthrough: bool = false, __behavior_overlap_mode: int = OverlapMode.VOLUME):
input_field_blacklist = ['behavior/behavior_brush_type']
super()
set_meta("class", "Toolshed_Brush")
resource_name = "Toolshed_Brush"
behavior_brush_type = __behavior_brush_type
behavior_strength = __behavior_strength
shape_volume_size = __shape_volume_size
shape_projection_size = __shape_projection_size
behavior_passthrough = __behavior_passthrough
behavior_overlap_mode = __behavior_overlap_mode
func _create_input_field(_base_control:Control, _resource_previewer, prop:String) -> UI_InputField:
var input_field:UI_InputField = null
match prop:
"shape/shape_volume_size":
var max_value = FunLib.get_setting_safe("dreadpons_spatial_gardener/input_and_ui/brush_volume_size_slider_max_value", 100.0)
var settings := {"min": 0.0, "max": max_value, "step": 0.01, "allow_greater": true, "allow_lesser": false,}
input_field = UI_IF_RealSlider.new(shape_volume_size, "Volume Size", prop, settings)
"shape/shape_projection_size":
var max_value = FunLib.get_setting_safe("dreadpons_spatial_gardener/input_and_ui/brush_projection_size_slider_max_value", 1000.0)
var settings := {"min": 1.0, "max": max_value, "step": 1.0, "allow_greater": true, "allow_lesser": false,}
input_field = UI_IF_RealSlider.new(shape_projection_size, "Projection Size", prop, settings)
"behavior/behavior_strength":
var settings := {"min": 0.0, "max": 1.0, "step": 0.01, "allow_greater": false, "allow_lesser": false,}
input_field = UI_IF_RealSlider.new(behavior_strength, "Strength", prop, settings)
"behavior/behavior_passthrough":
input_field = UI_IF_Bool.new(behavior_passthrough, "Passthrough", prop)
"behavior/behavior_overlap_mode":
var settings := {"enum_list": FunLib.capitalize_string_array(OverlapMode.keys())}
input_field = UI_IF_Enum.new(behavior_overlap_mode, "Overlap Mode", prop, settings)
"behavior/behavior_no_settings_text":
var settings := {"label_visibility": false}
input_field = UI_IF_PlainText.new(behavior_no_settings_text, "No Settings Text", prop, settings)
return input_field
#-------------------------------------------------------------------------------
# Property export
#-------------------------------------------------------------------------------
func _modify_prop(prop:String, val):
match prop:
"behavior/behavior_strength":
val = clamp(val, 0.0, 1.0)
"behavior/behavior_overlap_mode":
match behavior_brush_type:
BrushType.PAINT, BrushType.SINGLE:
val = OverlapMode.VOLUME
"shape/shape_volume_size":
match behavior_brush_type:
BrushType.SINGLE:
val = 1.0
return val
func _set(prop, val):
var return_val = true
val = _modify_prop(prop, val)
match prop:
"behavior/behavior_brush_type":
behavior_brush_type = val
_emit_property_list_changed_notify()
"shape/shape_volume_size":
shape_volume_size = val
"shape/shape_projection_size":
shape_projection_size = val
"behavior/behavior_strength":
behavior_strength = val
"behavior/behavior_passthrough":
behavior_passthrough = val
"behavior/behavior_overlap_mode":
behavior_overlap_mode = val
_emit_property_list_changed_notify()
"behavior/behavior_no_settings_text":
behavior_no_settings_text = val
_:
return_val = false
if return_val:
emit_changed()
return return_val
func _get(prop):
match prop:
"behavior/behavior_brush_type":
return behavior_brush_type
"shape/shape_volume_size":
return shape_volume_size
"shape/shape_projection_size":
return shape_projection_size
"behavior/behavior_strength":
return behavior_strength
"behavior/behavior_passthrough":
return behavior_passthrough
"behavior/behavior_overlap_mode":
return behavior_overlap_mode
"behavior/behavior_no_settings_text":
return behavior_no_settings_text
return null
func _filter_prop_dictionary(prop_dict: Dictionary) -> Dictionary:
var props_to_hide := ["behavior/behavior_brush_type"]
match behavior_overlap_mode:
OverlapMode.VOLUME:
match behavior_brush_type:
BrushType.PAINT:
props_to_hide.append_array([
"shape/shape_projection_size",
"behavior/behavior_passthrough",
"behavior/behavior_overlap_mode",
"behavior/behavior_no_settings_text"
])
BrushType.ERASE:
props_to_hide.append_array([
"shape/shape_projection_size",
"behavior/behavior_passthrough",
"behavior/behavior_no_settings_text"
])
BrushType.SINGLE:
props_to_hide.append_array([
"shape/shape_volume_size",
"shape/shape_projection_size",
"behavior/behavior_strength",
"behavior/behavior_passthrough",
"behavior/behavior_overlap_mode",
])
BrushType.REAPPLY:
props_to_hide.append_array([
"shape/shape_projection_size",
"behavior/behavior_passthrough",
"behavior/behavior_no_settings_text"
])
OverlapMode.PROJECTION:
match behavior_brush_type:
BrushType.ERASE:
props_to_hide.append_array([
"shape/shape_volume_size",
"behavior/behavior_strength",
"behavior/behavior_no_settings_text"
])
BrushType.REAPPLY:
props_to_hide.append_array([
"shape/shape_volume_size",
"behavior/behavior_strength",
"behavior/behavior_no_settings_text"
])
for prop in props_to_hide:
prop_dict[prop].usage = PROPERTY_USAGE_NO_EDITOR
return prop_dict
func _get_prop_dictionary():
return {
"behavior/behavior_brush_type" : {
"name": "behavior/behavior_brush_type",
"type": TYPE_INT,
"usage": PROPERTY_USAGE_DEFAULT,
"hint": PROPERTY_HINT_ENUM,
"hint_string": "Paint,Erase,Single,Reapply"
},
"shape/shape_volume_size" : {
"name": "shape/shape_volume_size",
"type": TYPE_FLOAT,
"usage": PROPERTY_USAGE_DEFAULT,
"hint": PROPERTY_HINT_RANGE,
"hint_string": "0.0,100.0,0.01,or_greater"
},
"shape/shape_projection_size" : {
"name": "shape/shape_projection_size",
"type": TYPE_FLOAT,
"usage": PROPERTY_USAGE_DEFAULT,
"hint": PROPERTY_HINT_RANGE,
"hint_string": "1.0,1000.0,1.0,or_greater"
},
"behavior/behavior_strength" : {
"name": "behavior/behavior_strength",
"type": TYPE_FLOAT,
"usage": PROPERTY_USAGE_DEFAULT,
"hint": PROPERTY_HINT_RANGE,
"hint_string": "0.0,1.0,0.01"
},
"behavior/behavior_passthrough" : {
"name": "behavior/behavior_passthrough",
"type": TYPE_BOOL,
"usage": PROPERTY_USAGE_DEFAULT,
"hint": PROPERTY_HINT_NONE,
},
"behavior/behavior_overlap_mode" : {
"name": "behavior/behavior_overlap_mode",
"type": TYPE_INT,
"usage": PROPERTY_USAGE_DEFAULT,
"hint": PROPERTY_HINT_ENUM,
"hint_string": "Volume,Projection"
},
"behavior/behavior_no_settings_text" : {
"name": "behavior/behavior_no_settings_text",
"type": TYPE_STRING,
"usage": PROPERTY_USAGE_DEFAULT,
"hint": PROPERTY_HINT_NONE,
},
}
func get_prop_tooltip(prop:String) -> String:
match prop:
"behavior/behavior_brush_type":
return "The brush type enum, that defines it's behavior (paint, erase, etc.)"
"shape/shape_volume_size":
return "The diameter of this brush, in world units\n" \
+ "\n" \
+ "Can be edited by dragging in the editor viewport while holding\n" \
+ "[brush_prop_edit_button]\n" \
+ Globals.AS_IN_SETTINGS_STRING
"shape/shape_projection_size":
return "The diameter of this brush, in screen pixels\n" \
+ "\n" \
+ "Can be edited by dragging in the editor viewport while holding\n" \
+ "[brush_prop_edit_button]\n" \
+ Globals.AS_IN_SETTINGS_STRING
"behavior/behavior_strength":
return "The plant density multiplier of this brush\n" \
+ "\n" \
+ "Can be edited by dragging in the editor viewport while holding\n" \
+ "[brush_prop_edit_modifier] + [brush_prop_edit_button]\n" \
+ Globals.AS_IN_SETTINGS_STRING
"behavior/behavior_passthrough":
return "The flag, that defines whether this brush can affect plants hidden behind terrain\n" \
+ "Only active physics bodies masked by 'Gardening Collision Mask' can occlude plants\n" \
+ "In simpler terms: whatever surface volume-brush sticks to, will block a projection-brush as well\n" \
+ "\n" \
+ "Enabling Passthrough will allow this brush to ignore any collision whatsoever\n" \
+ "It also gives better performance when painting since it disables additional collision checks\n"
"behavior/behavior_overlap_mode":
return "The overlap mode enum, that defines how brush finds which plants to affect\n" \
+ "Volume brush exists in 3D world and affects whichever plants it overlaps\n" \
+ "Projection brush exists in screen-space and affects all plants that are visually inside it's area\n" \
+ "\n" \
+ "For normal painting use a Volumetric brush\n" \
+ "If you have plants stuck in mid-air (say, you moved the ground beneath them),\n" \
+ "Use a Projection brush to remove them (Volumetric brush simply won't reach them)\n" \
+ "\n" \
+ "Can be edited by pressing\n" \
+ "[brush_overlap_mode_button]\n" \
+ Globals.AS_IN_SETTINGS_STRING
return ""