Grassy knoll
This commit is contained in:
@@ -0,0 +1,880 @@
|
||||
# plugin.gd
|
||||
# This file is part of: SimpleGrassTextured
|
||||
# Copyright (c) 2023 IcterusGames
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
# a copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||
# permit persons to whom the Software is furnished to do so, subject to
|
||||
# the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
@tool
|
||||
extends EditorPlugin
|
||||
|
||||
const DEFAULT_POINTER_DEPTH := 10.0
|
||||
|
||||
enum EVENT_MOUSE {
|
||||
EVENT_NONE,
|
||||
EVENT_MOVE,
|
||||
EVENT_CLICK,
|
||||
}
|
||||
|
||||
enum TOOL {
|
||||
NONE,
|
||||
PENCIL,
|
||||
AIRBRUSH,
|
||||
ERASER
|
||||
}
|
||||
|
||||
enum TOOL_SHAPE {
|
||||
SPHERE,
|
||||
CYLINDER,
|
||||
CYLINDER_INF_H,
|
||||
BOX,
|
||||
BOX_INF_H
|
||||
}
|
||||
|
||||
var _raycast_3d : RayCast3D = null
|
||||
var _pointer_decal : Decal = null
|
||||
var _pointer_img_circle = load("res://addons/simplegrasstextured/images/pointer.png")
|
||||
var _pointer_img_rect = load("res://addons/simplegrasstextured/images/pointer_rect.png")
|
||||
var _pointer_depth: int = DEFAULT_POINTER_DEPTH
|
||||
var _pointer_rotate: bool = true
|
||||
var _grass_selected = null
|
||||
var _position_draw := Vector3.ZERO
|
||||
var _normal_draw := Vector3.ZERO
|
||||
var _object_draw : Object = null
|
||||
var _edit_density := 25
|
||||
var _edit_radius := 2.0
|
||||
var _edit_slope := Vector2(0, 45)
|
||||
var _edit_scale := Vector3.ONE
|
||||
var _edit_rotation := 0.0
|
||||
var _edit_rotation_rand := 1.0
|
||||
var _edit_tool: TOOL = TOOL.AIRBRUSH : set = _on_set_tool
|
||||
var _gui_toolbar = null
|
||||
var _gui_toolbar_up = null
|
||||
var _time_draw := 0
|
||||
var _draw_paused := true
|
||||
var _mouse_event := EVENT_MOUSE.EVENT_NONE
|
||||
var _project_ray_origin := Vector3.INF
|
||||
var _project_ray_normal := Vector3.INF
|
||||
var _inspector_plugin : EditorInspectorPlugin = null
|
||||
var _evaluate_draw_time: int = 100
|
||||
var _prev_config := ""
|
||||
var _custom_settings := [{
|
||||
"name": "SimpleGrassTextured/General/default_terrain_physics_layer",
|
||||
"type": TYPE_INT,
|
||||
"hint": PROPERTY_HINT_LAYERS_3D_PHYSICS,
|
||||
"hint_string": "",
|
||||
"default": pow(2, 32) - 1,
|
||||
"basic": true
|
||||
},{
|
||||
"name": "SimpleGrassTextured/General/evaluate_draw_time",
|
||||
"type": TYPE_INT,
|
||||
"hint": PROPERTY_HINT_ENUM,
|
||||
"hint_string": "Slow:150,Normal:100,Fast:50,Very fast:25",
|
||||
"default": 50,
|
||||
"basic": false
|
||||
},{
|
||||
"name": "SimpleGrassTextured/General/interactive_resolution",
|
||||
"type": TYPE_INT,
|
||||
"hint": PROPERTY_HINT_ENUM,
|
||||
"hint_string": "Low:256,High:512",
|
||||
"default": 512,
|
||||
"basic": false
|
||||
},{
|
||||
"name": "SimpleGrassTextured/General/interactive_resolution.android",
|
||||
"type": TYPE_INT,
|
||||
"hint": PROPERTY_HINT_ENUM,
|
||||
"hint_string": "Low:256,High:512",
|
||||
"default": 256,
|
||||
"basic": false
|
||||
},{
|
||||
"name": "SimpleGrassTextured/General/interactive_resolution.ios",
|
||||
"type": TYPE_INT,
|
||||
"hint": PROPERTY_HINT_ENUM,
|
||||
"hint_string": "Low:256,High:512",
|
||||
"default": 256,
|
||||
"basic": false
|
||||
},{
|
||||
"name": "SimpleGrassTextured/Shortcuts/airbrush_tool",
|
||||
"type": TYPE_OBJECT,
|
||||
"hint": PROPERTY_HINT_RESOURCE_TYPE,
|
||||
"hint_string": "Shortcut",
|
||||
"default": _create_shortcut(KEY_D),
|
||||
"basic": true
|
||||
},{
|
||||
"name": "SimpleGrassTextured/Shortcuts/pencil_tool",
|
||||
"type": TYPE_OBJECT,
|
||||
"hint": PROPERTY_HINT_RESOURCE_TYPE,
|
||||
"hint_string": "Shortcut",
|
||||
"default": _create_shortcut(KEY_B),
|
||||
"basic": true
|
||||
},{
|
||||
"name": "SimpleGrassTextured/Shortcuts/eraser_tool",
|
||||
"type": TYPE_OBJECT,
|
||||
"hint": PROPERTY_HINT_RESOURCE_TYPE,
|
||||
"hint_string": "Shortcut",
|
||||
"default": _create_shortcut(KEY_X),
|
||||
"basic": true
|
||||
},{
|
||||
"name": "SimpleGrassTextured/Shortcuts/radius_increment",
|
||||
"type": TYPE_OBJECT,
|
||||
"hint": PROPERTY_HINT_RESOURCE_TYPE,
|
||||
"hint_string": "Shortcut",
|
||||
"default": _create_shortcut(KEY_BRACKETRIGHT),
|
||||
"basic": true
|
||||
},{
|
||||
"name": "SimpleGrassTextured/Shortcuts/radius_decrement",
|
||||
"type": TYPE_OBJECT,
|
||||
"hint": PROPERTY_HINT_RESOURCE_TYPE,
|
||||
"hint_string": "Shortcut",
|
||||
"default": _create_shortcut(KEY_BRACKETLEFT),
|
||||
"basic": true
|
||||
},{
|
||||
"name": "SimpleGrassTextured/Shortcuts/density_increment",
|
||||
"type": TYPE_OBJECT,
|
||||
"hint": PROPERTY_HINT_RESOURCE_TYPE,
|
||||
"hint_string": "Shortcut",
|
||||
"default": _create_shortcut(KEY_EQUAL),
|
||||
"basic": true
|
||||
},{
|
||||
"name": "SimpleGrassTextured/Shortcuts/density_decrement",
|
||||
"type": TYPE_OBJECT,
|
||||
"hint": PROPERTY_HINT_RESOURCE_TYPE,
|
||||
"hint_string": "Shortcut",
|
||||
"default": _create_shortcut(KEY_MINUS),
|
||||
"basic": true
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
func _enter_tree() -> void:
|
||||
if not get_tree().has_user_signal(&"sgt_globals_params_changed"):
|
||||
get_tree().add_user_signal(&"sgt_globals_params_changed")
|
||||
_verify_global_shader_parameters()
|
||||
_enable_shaders(true)
|
||||
_init_default_project_settings()
|
||||
_prev_config = _custom_config_memorize()
|
||||
if ProjectSettings.has_signal(&"settings_changed"):
|
||||
ProjectSettings.connect(&"settings_changed", _on_project_settings_changed)
|
||||
# Must ensure the resource file of default_mesh.tres match the current Godot version
|
||||
var default_mesh = load("res://addons/simplegrasstextured/default_mesh.tres")
|
||||
if not default_mesh or not default_mesh.has_meta(&"GodotVersion") or default_mesh.get_meta(&"GodotVersion") != Engine.get_version_info()["string"]:
|
||||
push_warning("SimpleGrassTextured, updating file res://addons/simplegrasstextured/default_mesh.tres")
|
||||
default_mesh = null
|
||||
var mesh_builder = load("res://addons/simplegrasstextured/default_mesh_builder.gd").new()
|
||||
mesh_builder.rebuild_and_save_default_mesh()
|
||||
default_mesh = load("res://addons/simplegrasstextured/default_mesh.tres")
|
||||
if default_mesh:
|
||||
default_mesh.emit_changed()
|
||||
print("SimpleGrassTextured, file updated successfully res://addons/simplegrasstextured/default_mesh.tres")
|
||||
else:
|
||||
push_error("SimpleGrassTextured, error updating file res://addons/simplegrasstextured/default_mesh.tres")
|
||||
add_custom_type(
|
||||
"SimpleGrassTextured",
|
||||
"MultiMeshInstance3D",
|
||||
load("res://addons/simplegrasstextured/grass.gd"),
|
||||
load("res://addons/simplegrasstextured/sgt_icon.svg")
|
||||
)
|
||||
|
||||
_gui_toolbar = load("res://addons/simplegrasstextured/gui/toolbar.tscn").instantiate()
|
||||
_gui_toolbar.visible = false
|
||||
add_control_to_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_BOTTOM, _gui_toolbar)
|
||||
_gui_toolbar.set_plugin(self)
|
||||
|
||||
_gui_toolbar_up = load("res://addons/simplegrasstextured/gui/toolbar_up.tscn").instantiate()
|
||||
_gui_toolbar_up.visible = false
|
||||
add_control_to_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, _gui_toolbar_up)
|
||||
_gui_toolbar_up.set_plugin(self)
|
||||
|
||||
_inspector_plugin = load("res://addons/simplegrasstextured/sgt_inspector.gd").new()
|
||||
add_inspector_plugin(_inspector_plugin)
|
||||
|
||||
_raycast_3d = RayCast3D.new()
|
||||
_raycast_3d.collision_mask = pow(2, 32) - 1
|
||||
_raycast_3d.visible = false
|
||||
_pointer_decal = Decal.new()
|
||||
_pointer_decal.set_texture(Decal.TEXTURE_ALBEDO, _pointer_img_circle)
|
||||
_pointer_decal.visible = false
|
||||
_pointer_decal.extents = Vector3(_edit_radius, _pointer_depth, _edit_radius)
|
||||
_pointer_decal.upper_fade = 0
|
||||
_pointer_decal.lower_fade = 0
|
||||
add_child(_raycast_3d)
|
||||
add_child(_pointer_decal)
|
||||
|
||||
_gui_toolbar.slider_radius.value_changed.connect(_on_slider_radius_value_changed)
|
||||
_gui_toolbar.slider_density.value_changed.connect(_on_slider_density_value_changed)
|
||||
_gui_toolbar.button_airbrush.toggled.connect(_on_button_airbrush_toggled)
|
||||
_gui_toolbar.button_pencil.toggled.connect(_on_button_pencil_toggled)
|
||||
_gui_toolbar.button_eraser.toggled.connect(_on_button_eraser_toggled)
|
||||
_gui_toolbar.edit_slope_range.value_changed.connect(_on_edit_slope_range_changed)
|
||||
_gui_toolbar.edit_scale.value_changed.connect(_on_edit_scale_value_changed)
|
||||
_gui_toolbar.edit_rotation.value_changed.connect(_on_edit_rotation_value_changed)
|
||||
_gui_toolbar.edit_rotation_rand.value_changed.connect(_on_edit_rotation_rand_value_changed)
|
||||
_gui_toolbar.edit_distance.value_changed.connect(_on_edit_distance_value_changed)
|
||||
_edit_tool = TOOL.AIRBRUSH
|
||||
|
||||
|
||||
func _exit_tree() -> void:
|
||||
var current_config := _custom_config_memorize()
|
||||
if current_config != _prev_config:
|
||||
# Force save settings if some shortcut has been changed
|
||||
ProjectSettings.save()
|
||||
_grass_selected = null
|
||||
_raycast_3d.queue_free()
|
||||
_pointer_decal.queue_free()
|
||||
remove_custom_type("SimpleGrassTextured")
|
||||
remove_control_from_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_BOTTOM, _gui_toolbar)
|
||||
_gui_toolbar.queue_free()
|
||||
remove_control_from_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, _gui_toolbar_up)
|
||||
_gui_toolbar_up.queue_free()
|
||||
if _inspector_plugin != null:
|
||||
remove_inspector_plugin(_inspector_plugin)
|
||||
|
||||
|
||||
func _enable_plugin() -> void:
|
||||
_verify_global_shader_parameters()
|
||||
|
||||
|
||||
func _disable_plugin() -> void:
|
||||
_enable_shaders(false)
|
||||
remove_autoload_singleton("SimpleGrass")
|
||||
if ProjectSettings.has_setting("shader_globals/sgt_legacy_renderer"):
|
||||
ProjectSettings.set_setting("shader_globals/sgt_legacy_renderer", null)
|
||||
if ProjectSettings.has_setting("shader_globals/sgt_player_position"):
|
||||
ProjectSettings.set_setting("shader_globals/sgt_player_position", null)
|
||||
if ProjectSettings.has_setting("shader_globals/sgt_player_mov"):
|
||||
ProjectSettings.set_setting("shader_globals/sgt_player_mov", null)
|
||||
if ProjectSettings.has_setting("shader_globals/sgt_normal_displacement"):
|
||||
ProjectSettings.set_setting("shader_globals/sgt_normal_displacement", null)
|
||||
if ProjectSettings.has_setting("shader_globals/sgt_motion_texture"):
|
||||
ProjectSettings.set_setting("shader_globals/sgt_motion_texture", null)
|
||||
if ProjectSettings.has_setting("shader_globals/sgt_wind_direction"):
|
||||
ProjectSettings.set_setting("shader_globals/sgt_wind_direction", null)
|
||||
if ProjectSettings.has_setting("shader_globals/sgt_wind_movement"):
|
||||
ProjectSettings.set_setting("shader_globals/sgt_wind_movement", null)
|
||||
if ProjectSettings.has_setting("shader_globals/sgt_wind_strength"):
|
||||
ProjectSettings.set_setting("shader_globals/sgt_wind_strength", null)
|
||||
if ProjectSettings.has_setting("shader_globals/sgt_wind_turbulence"):
|
||||
ProjectSettings.set_setting("shader_globals/sgt_wind_turbulence", null)
|
||||
if ProjectSettings.has_setting("shader_globals/sgt_wind_pattern"):
|
||||
ProjectSettings.set_setting("shader_globals/sgt_wind_pattern", null)
|
||||
# Remove custom settings from Project Settings
|
||||
for entry in _custom_settings:
|
||||
if ProjectSettings.has_setting(entry["name"]):
|
||||
ProjectSettings.set_setting(entry["name"], null)
|
||||
# Fix editor crash when disable plugin while SimpleGrassTextured node is selected
|
||||
_grass_selected = null
|
||||
var editor = get_editor_interface()
|
||||
if editor != null:
|
||||
var scene_root = editor.get_edited_scene_root()
|
||||
if scene_root != null:
|
||||
editor.edit_node(scene_root)
|
||||
var selection = editor.get_selection()
|
||||
if selection != null:
|
||||
selection.clear()
|
||||
|
||||
|
||||
func _get_plugin_name() -> String:
|
||||
return "SimpleGrassTextured"
|
||||
|
||||
|
||||
func _handles(object) -> bool:
|
||||
if object != null and object.has_meta("SimpleGrassTextured") and object.visible:
|
||||
_grass_selected = object
|
||||
_update_gui()
|
||||
_update_pointer()
|
||||
return true
|
||||
_grass_selected = null
|
||||
return false
|
||||
|
||||
|
||||
func _edit(object) -> void:
|
||||
_grass_selected = object
|
||||
_update_gui()
|
||||
_update_pointer()
|
||||
|
||||
|
||||
func _make_visible(visible : bool) -> void:
|
||||
if visible:
|
||||
if _grass_selected != null:
|
||||
_update_gui()
|
||||
_gui_toolbar.visible = true
|
||||
_gui_toolbar_up.visible = true
|
||||
else:
|
||||
_gui_toolbar.visible = false
|
||||
_gui_toolbar_up.visible = false
|
||||
_pointer_decal.visible = false
|
||||
_grass_selected = null
|
||||
_gui_toolbar.set_current_grass(null)
|
||||
_gui_toolbar_up.set_current_grass(null)
|
||||
|
||||
|
||||
func _physics_process(_delta) -> void:
|
||||
if _mouse_event == EVENT_MOUSE.EVENT_CLICK:
|
||||
_raycast_3d.global_transform.origin = _project_ray_origin
|
||||
_raycast_3d.global_transform.basis.y = _project_ray_normal
|
||||
_raycast_3d.target_position = Vector3(0, 100000, 0)
|
||||
_raycast_3d.collision_mask = _grass_selected.collision_mask
|
||||
_raycast_3d.force_raycast_update()
|
||||
if _raycast_3d.is_colliding():
|
||||
_position_draw = _raycast_3d.get_collision_point()
|
||||
_normal_draw = _raycast_3d.get_collision_normal()
|
||||
_object_draw = _raycast_3d.get_collider()
|
||||
_eval_brush()
|
||||
_time_draw = Time.get_ticks_msec()
|
||||
_draw_paused = false
|
||||
else:
|
||||
_time_draw = 0
|
||||
_draw_paused = true
|
||||
_object_draw = null
|
||||
_mouse_event = EVENT_MOUSE.EVENT_NONE
|
||||
elif _mouse_event == EVENT_MOUSE.EVENT_MOVE:
|
||||
_raycast_3d.global_transform.origin = _project_ray_origin
|
||||
_raycast_3d.global_transform.basis.y = _project_ray_normal
|
||||
_raycast_3d.target_position = Vector3(0, 100000, 0)
|
||||
_raycast_3d.collision_mask = _grass_selected.collision_mask
|
||||
_raycast_3d.force_raycast_update()
|
||||
if ( not _raycast_3d.is_colliding()
|
||||
or ( _object_draw != null and _raycast_3d.get_collider() != _object_draw )):
|
||||
_pointer_decal.visible = false
|
||||
_draw_paused = true
|
||||
_mouse_event = EVENT_MOUSE.EVENT_NONE
|
||||
return
|
||||
else:
|
||||
_draw_paused = false
|
||||
_position_draw = _raycast_3d.get_collision_point()
|
||||
_normal_draw = _raycast_3d.get_collision_normal()
|
||||
if _pointer_rotate:
|
||||
var trans := Transform3D()
|
||||
if abs(_normal_draw.z) == 1:
|
||||
trans.basis.x = Vector3(1,0,0)
|
||||
trans.basis.y = Vector3(0,0,_normal_draw.z)
|
||||
trans.basis.z = Vector3(0,_normal_draw.z,0)
|
||||
else:
|
||||
trans.basis.y = _normal_draw
|
||||
trans.basis.x = _normal_draw.cross(trans.basis.z)
|
||||
trans.basis.z = trans.basis.x.cross(_normal_draw)
|
||||
trans.basis = trans.basis.orthonormalized()
|
||||
trans.origin = _position_draw
|
||||
_pointer_decal.global_transform = trans
|
||||
else:
|
||||
_pointer_decal.global_position = _position_draw
|
||||
_pointer_decal.rotation = Vector3.ZERO
|
||||
_pointer_decal.extents = Vector3(_edit_radius, _pointer_depth, _edit_radius)
|
||||
_pointer_decal.visible = _edit_tool != TOOL.NONE
|
||||
_mouse_event = EVENT_MOUSE.EVENT_NONE
|
||||
|
||||
if _time_draw > 0:
|
||||
if not _draw_paused:
|
||||
if Time.get_ticks_msec() - _time_draw >= _evaluate_draw_time:
|
||||
_time_draw = Time.get_ticks_msec()
|
||||
_eval_brush()
|
||||
|
||||
|
||||
func _forward_3d_gui_input(viewport_camera: Camera3D, event: InputEvent) -> int:
|
||||
if _grass_selected == null:
|
||||
return EditorPlugin.AFTER_GUI_INPUT_PASS
|
||||
if _grass_selected.multimesh != null:
|
||||
_gui_toolbar.label_stats.text = "Count: " + str(_grass_selected.multimesh.instance_count)
|
||||
if event is InputEventMouseButton:
|
||||
if event.button_index == MOUSE_BUTTON_LEFT:
|
||||
if _edit_tool == TOOL.NONE:
|
||||
return EditorPlugin.AFTER_GUI_INPUT_PASS
|
||||
if event.pressed:
|
||||
if _edit_tool == TOOL.AIRBRUSH:
|
||||
get_undo_redo().create_action(_grass_selected.name + " Airbrush tool")
|
||||
elif _edit_tool == TOOL.PENCIL:
|
||||
get_undo_redo().create_action(_grass_selected.name + " Pencil tool")
|
||||
elif _edit_tool == TOOL.ERASER:
|
||||
get_undo_redo().create_action(_grass_selected.name + " Eraser tool")
|
||||
else:
|
||||
get_undo_redo().create_action(_grass_selected.name)
|
||||
get_undo_redo().add_undo_property(_grass_selected, &"baked_height_map", _grass_selected.baked_height_map)
|
||||
get_undo_redo().add_undo_property(_grass_selected, &"multimesh", _grass_selected.multimesh)
|
||||
_project_ray_origin = viewport_camera.project_ray_origin(event.position)
|
||||
_project_ray_normal = viewport_camera.project_ray_normal(event.position)
|
||||
_mouse_event = EVENT_MOUSE.EVENT_CLICK
|
||||
else:
|
||||
get_undo_redo().add_do_property(_grass_selected, &"baked_height_map", _grass_selected.baked_height_map)
|
||||
get_undo_redo().add_do_property(_grass_selected, &"multimesh", _grass_selected.multimesh)
|
||||
get_undo_redo().commit_action()
|
||||
_time_draw = 0
|
||||
_object_draw = null
|
||||
_mouse_event = EVENT_MOUSE.EVENT_NONE
|
||||
return EditorPlugin.AFTER_GUI_INPUT_STOP
|
||||
if event is InputEventMouseMotion:
|
||||
if _mouse_event != EVENT_MOUSE.EVENT_CLICK:
|
||||
_project_ray_origin = viewport_camera.project_ray_origin(event.position)
|
||||
_project_ray_normal = viewport_camera.project_ray_normal(event.position)
|
||||
_mouse_event = EVENT_MOUSE.EVENT_MOVE
|
||||
return EditorPlugin.AFTER_GUI_INPUT_PASS
|
||||
|
||||
|
||||
func _verify_global_shader_parameters() -> void:
|
||||
if not ProjectSettings.has_setting("shader_globals/sgt_legacy_renderer"):
|
||||
ProjectSettings.set_setting("shader_globals/sgt_legacy_renderer", {
|
||||
"type": "int",
|
||||
"value": 0
|
||||
})
|
||||
if RenderingServer.global_shader_parameter_get("sgt_legacy_renderer") == null:
|
||||
var using_legacy_renderer = ProjectSettings.get_setting_with_override("rendering/renderer/rendering_method") == "gl_compatibility"
|
||||
RenderingServer.global_shader_parameter_add("sgt_legacy_renderer", RenderingServer.GLOBAL_VAR_TYPE_INT, 1 if using_legacy_renderer else 0)
|
||||
|
||||
if not ProjectSettings.has_setting("shader_globals/sgt_player_position"):
|
||||
ProjectSettings.set_setting("shader_globals/sgt_player_position", {
|
||||
"type": "vec3",
|
||||
"value": Vector3(1000000, 1000000, 1000000)
|
||||
})
|
||||
if RenderingServer.global_shader_parameter_get("sgt_player_position") == null:
|
||||
RenderingServer.global_shader_parameter_add("sgt_player_position", RenderingServer.GLOBAL_VAR_TYPE_VEC3, Vector3(1000000,1000000,1000000))
|
||||
if not ProjectSettings.has_setting("shader_globals/sgt_player_mov"):
|
||||
ProjectSettings.set_setting("shader_globals/sgt_player_mov", {
|
||||
"type": "vec3",
|
||||
"value": Vector3.ZERO
|
||||
})
|
||||
if RenderingServer.global_shader_parameter_get("sgt_player_mov") == null:
|
||||
RenderingServer.global_shader_parameter_add("sgt_player_mov", RenderingServer.GLOBAL_VAR_TYPE_VEC3, Vector3.ZERO)
|
||||
if not ProjectSettings.has_setting("shader_globals/sgt_normal_displacement"):
|
||||
ProjectSettings.set_setting("shader_globals/sgt_normal_displacement", {
|
||||
"type": "sampler2D",
|
||||
"value": "res://addons/simplegrasstextured/images/normal.png"
|
||||
})
|
||||
if RenderingServer.global_shader_parameter_get("sgt_normal_displacement") == null:
|
||||
RenderingServer.global_shader_parameter_add("sgt_normal_displacement", RenderingServer.GLOBAL_VAR_TYPE_SAMPLER2D, load("res://addons/simplegrasstextured/images/normal.png"))
|
||||
if not ProjectSettings.has_setting("shader_globals/sgt_motion_texture"):
|
||||
ProjectSettings.set_setting("shader_globals/sgt_motion_texture", {
|
||||
"type": "sampler2D",
|
||||
"value": "res://addons/simplegrasstextured/images/motion.png"
|
||||
})
|
||||
if RenderingServer.global_shader_parameter_get("sgt_motion_texture") == null:
|
||||
RenderingServer.global_shader_parameter_add("sgt_motion_texture", RenderingServer.GLOBAL_VAR_TYPE_SAMPLER2D, load("res://addons/simplegrasstextured/images/motion.png"))
|
||||
if not ProjectSettings.has_setting("shader_globals/sgt_wind_direction"):
|
||||
ProjectSettings.set_setting("shader_globals/sgt_wind_direction", {
|
||||
"type": "vec3",
|
||||
"value": Vector3(1, 0, 0)
|
||||
})
|
||||
if RenderingServer.global_shader_parameter_get("sgt_wind_direction") == null:
|
||||
RenderingServer.global_shader_parameter_add("sgt_wind_direction", RenderingServer.GLOBAL_VAR_TYPE_VEC3, Vector3(1, 0, 0))
|
||||
if not ProjectSettings.has_setting("shader_globals/sgt_wind_movement"):
|
||||
ProjectSettings.set_setting("shader_globals/sgt_wind_movement", {
|
||||
"type": "vec3",
|
||||
"value": Vector2.ZERO
|
||||
})
|
||||
if RenderingServer.global_shader_parameter_get("sgt_wind_movement") == null:
|
||||
RenderingServer.global_shader_parameter_add("sgt_wind_movement", RenderingServer.GLOBAL_VAR_TYPE_VEC3, Vector3.ZERO)
|
||||
if not ProjectSettings.has_setting("shader_globals/sgt_wind_strength"):
|
||||
ProjectSettings.set_setting("shader_globals/sgt_wind_strength", {
|
||||
"type": "float",
|
||||
"value": 0.15
|
||||
})
|
||||
if RenderingServer.global_shader_parameter_get("sgt_wind_strength") == null:
|
||||
RenderingServer.global_shader_parameter_add("sgt_wind_strength", RenderingServer.GLOBAL_VAR_TYPE_FLOAT, 0.15)
|
||||
if not ProjectSettings.has_setting("shader_globals/sgt_wind_turbulence"):
|
||||
ProjectSettings.set_setting("shader_globals/sgt_wind_turbulence", {
|
||||
"type": "float",
|
||||
"value": 1.0
|
||||
})
|
||||
if RenderingServer.global_shader_parameter_get("sgt_wind_turbulence") == null:
|
||||
RenderingServer.global_shader_parameter_add("sgt_wind_turbulence", RenderingServer.GLOBAL_VAR_TYPE_FLOAT, 1.0)
|
||||
if not ProjectSettings.has_setting("shader_globals/sgt_wind_pattern"):
|
||||
ProjectSettings.set_setting("shader_globals/sgt_wind_pattern", {
|
||||
"type": "sampler2D",
|
||||
"value": "res://addons/simplegrasstextured/images/wind_pattern.png"
|
||||
})
|
||||
if RenderingServer.global_shader_parameter_get("sgt_wind_pattern") == null:
|
||||
RenderingServer.global_shader_parameter_add("sgt_wind_pattern", RenderingServer.GLOBAL_VAR_TYPE_SAMPLER2D, load("res://addons/simplegrasstextured/images/wind_pattern.png"))
|
||||
if not ProjectSettings.has_setting("autoload/SimpleGrass"):
|
||||
add_autoload_singleton("SimpleGrass", "res://addons/simplegrasstextured/singleton.tscn")
|
||||
|
||||
|
||||
func _enable_shaders(enable :bool) -> void:
|
||||
if enable:
|
||||
var dir := DirAccess.open("res://")
|
||||
var scan := false
|
||||
if dir.file_exists("res://addons/simplegrasstextured/shaders/.gdignore"):
|
||||
dir.remove("res://addons/simplegrasstextured/shaders/.gdignore")
|
||||
scan = true
|
||||
if dir.file_exists("res://addons/simplegrasstextured/materials/.gdignore"):
|
||||
dir.remove("res://addons/simplegrasstextured/materials/.gdignore")
|
||||
scan = true
|
||||
if scan:
|
||||
var editor = get_editor_interface()
|
||||
editor.get_resource_filesystem().scan.call_deferred()
|
||||
else:
|
||||
var file := FileAccess.open("res://addons/simplegrasstextured/shaders/.gdignore", FileAccess.WRITE)
|
||||
file.close()
|
||||
file = FileAccess.open("res://addons/simplegrasstextured/materials/.gdignore", FileAccess.WRITE)
|
||||
file.close()
|
||||
var editor = get_editor_interface()
|
||||
editor.get_resource_filesystem().scan.call_deferred()
|
||||
|
||||
|
||||
func _create_shortcut(keycode :Key) -> Shortcut:
|
||||
var shortcut := Shortcut.new()
|
||||
var key := InputEventKey.new()
|
||||
key.keycode = keycode
|
||||
key.pressed = true
|
||||
shortcut.events.append(key)
|
||||
return shortcut
|
||||
|
||||
|
||||
func _custom_config_memorize() -> String:
|
||||
var config := ConfigFile.new()
|
||||
for entry in _custom_settings:
|
||||
config.set_value("s", entry["name"], ProjectSettings.get_setting_with_override(entry["name"]))
|
||||
return config.encode_to_text()
|
||||
|
||||
|
||||
func get_custom_setting(name :String) -> Variant:
|
||||
if ProjectSettings.has_setting(name):
|
||||
return ProjectSettings.get_setting_with_override(name)
|
||||
for entry in _custom_settings:
|
||||
if entry["name"] != name:
|
||||
continue
|
||||
return entry["default"]
|
||||
push_error("SimpleGrassTextured, setting not found: ", name)
|
||||
return null
|
||||
|
||||
|
||||
func set_tool(tool_name: String) -> void:
|
||||
match tool_name:
|
||||
"none":
|
||||
_edit_tool = TOOL.NONE
|
||||
"airbrush":
|
||||
_edit_tool = TOOL.AIRBRUSH
|
||||
"pencil":
|
||||
_edit_tool = TOOL.PENCIL
|
||||
"eraser":
|
||||
_edit_tool = TOOL.ERASER
|
||||
|
||||
|
||||
func set_tool_shape(tool_name: String, shape_name: String) -> void:
|
||||
if _grass_selected == null:
|
||||
return
|
||||
var shape_id: TOOL_SHAPE
|
||||
match shape_name:
|
||||
"sphere":
|
||||
shape_id = TOOL_SHAPE.SPHERE
|
||||
"cylinder":
|
||||
shape_id = TOOL_SHAPE.CYLINDER
|
||||
"cylinder_inf_h":
|
||||
shape_id = TOOL_SHAPE.CYLINDER_INF_H
|
||||
"box":
|
||||
shape_id = TOOL_SHAPE.BOX
|
||||
"box_inf_h":
|
||||
shape_id = TOOL_SHAPE.BOX_INF_H
|
||||
_grass_selected.sgt_tool_shape[tool_name] = shape_id
|
||||
_update_pointer()
|
||||
|
||||
|
||||
func get_tool_shape_name(shape_id: int) -> String:
|
||||
match shape_id:
|
||||
TOOL_SHAPE.SPHERE:
|
||||
return "sphere"
|
||||
TOOL_SHAPE.CYLINDER:
|
||||
return "cylinder"
|
||||
TOOL_SHAPE.CYLINDER_INF_H:
|
||||
return "cylinder_inf_h"
|
||||
TOOL_SHAPE.BOX:
|
||||
return "box"
|
||||
TOOL_SHAPE.BOX_INF_H:
|
||||
return "box_inf_h"
|
||||
return ""
|
||||
|
||||
|
||||
func _init_default_project_settings() -> void:
|
||||
for entry in _custom_settings:
|
||||
if not ProjectSettings.has_setting(entry["name"]):
|
||||
ProjectSettings.set(entry["name"], entry["default"])
|
||||
ProjectSettings.set_initial_value(entry["name"], entry["default"])
|
||||
ProjectSettings.add_property_info(entry)
|
||||
if entry.has("basic") and ProjectSettings.has_method(&"set_as_basic"):
|
||||
ProjectSettings.call(&"set_as_basic", entry["name"], entry["basic"])
|
||||
|
||||
|
||||
func _update_gui() -> void:
|
||||
if _grass_selected != null:
|
||||
if not _grass_selected.sgt_tool_shape.has("airbrush"):
|
||||
_grass_selected.sgt_tool_shape["airbrush"] = TOOL_SHAPE.CYLINDER
|
||||
if not _grass_selected.sgt_tool_shape.has("pencil"):
|
||||
_grass_selected.sgt_tool_shape["pencil"] = TOOL_SHAPE.CYLINDER
|
||||
if not _grass_selected.sgt_tool_shape.has("eraser"):
|
||||
_grass_selected.sgt_tool_shape["eraser"] = TOOL_SHAPE.SPHERE
|
||||
_gui_toolbar.slider_radius.value = _grass_selected.sgt_radius
|
||||
_gui_toolbar.slider_density.value = _grass_selected.sgt_density
|
||||
_gui_toolbar.edit_scale.value = _grass_selected.sgt_scale
|
||||
_gui_toolbar.edit_rotation.value = _grass_selected.sgt_rotation
|
||||
_gui_toolbar.edit_rotation_rand.value = _grass_selected.sgt_rotation_rand
|
||||
_gui_toolbar.edit_distance.value = _grass_selected.sgt_dist_min
|
||||
_gui_toolbar.edit_slope_range.set_value(_grass_selected.sgt_slope.x, _grass_selected.sgt_slope.y)
|
||||
_gui_toolbar.set_current_grass(_grass_selected)
|
||||
_gui_toolbar_up.set_current_grass(_grass_selected)
|
||||
if _grass_selected.multimesh != null:
|
||||
_gui_toolbar.label_stats.text = "Count: " + str(_grass_selected.multimesh.instance_count)
|
||||
_raycast_3d.collision_mask = _grass_selected.collision_mask
|
||||
|
||||
|
||||
func _update_pointer() -> void:
|
||||
if _grass_selected == null:
|
||||
_pointer_decal.visible = false
|
||||
return
|
||||
_pointer_decal.visible = true
|
||||
var tool_name := ""
|
||||
match _edit_tool:
|
||||
TOOL.NONE:
|
||||
_pointer_decal.visible = false
|
||||
return
|
||||
TOOL.PENCIL:
|
||||
tool_name = "pencil"
|
||||
_pointer_rotate = true
|
||||
TOOL.AIRBRUSH:
|
||||
tool_name = "airbrush"
|
||||
_pointer_rotate = true
|
||||
TOOL.ERASER:
|
||||
tool_name = "eraser"
|
||||
_pointer_rotate = false
|
||||
match _grass_selected.sgt_tool_shape[tool_name]:
|
||||
TOOL_SHAPE.SPHERE:
|
||||
if _edit_tool == TOOL.ERASER:
|
||||
_pointer_rotate = true
|
||||
_pointer_depth = _edit_radius
|
||||
_pointer_decal.set_texture(Decal.TEXTURE_ALBEDO, _pointer_img_circle)
|
||||
TOOL_SHAPE.CYLINDER:
|
||||
if _edit_tool == TOOL.ERASER:
|
||||
_pointer_rotate = true
|
||||
_pointer_depth = DEFAULT_POINTER_DEPTH
|
||||
_pointer_decal.set_texture(Decal.TEXTURE_ALBEDO, _pointer_img_circle)
|
||||
TOOL_SHAPE.CYLINDER_INF_H:
|
||||
_pointer_depth = 1000000
|
||||
_pointer_decal.set_texture(Decal.TEXTURE_ALBEDO, _pointer_img_circle)
|
||||
TOOL_SHAPE.BOX:
|
||||
if _edit_tool == TOOL.ERASER:
|
||||
_pointer_rotate = true
|
||||
_pointer_depth = _edit_radius
|
||||
_pointer_decal.set_texture(Decal.TEXTURE_ALBEDO, _pointer_img_rect)
|
||||
TOOL_SHAPE.BOX_INF_H:
|
||||
_pointer_depth = 1000000
|
||||
_pointer_decal.set_texture(Decal.TEXTURE_ALBEDO, _pointer_img_rect)
|
||||
|
||||
|
||||
func _on_project_settings_changed() -> void:
|
||||
_prev_config = _custom_config_memorize()
|
||||
_evaluate_draw_time = get_custom_setting("SimpleGrassTextured/General/evaluate_draw_time")
|
||||
|
||||
|
||||
func _on_button_airbrush_toggled(pressed : bool) -> void:
|
||||
if pressed:
|
||||
_edit_tool = TOOL.AIRBRUSH
|
||||
elif _edit_tool == TOOL.AIRBRUSH:
|
||||
_edit_tool = TOOL.NONE
|
||||
_update_pointer()
|
||||
|
||||
|
||||
func _on_button_pencil_toggled(pressed : bool) -> void:
|
||||
if pressed:
|
||||
_edit_tool = TOOL.PENCIL
|
||||
elif _edit_tool == TOOL.PENCIL:
|
||||
_edit_tool = TOOL.NONE
|
||||
_update_pointer()
|
||||
|
||||
|
||||
func _on_button_eraser_toggled(pressed : bool) -> void:
|
||||
if pressed:
|
||||
_edit_tool = TOOL.ERASER
|
||||
elif _edit_tool == TOOL.ERASER:
|
||||
_edit_tool = TOOL.NONE
|
||||
_update_pointer()
|
||||
|
||||
|
||||
func _on_slider_radius_value_changed(value : float) -> void:
|
||||
_edit_radius = value
|
||||
_update_pointer()
|
||||
_pointer_decal.extents = Vector3(_edit_radius, _pointer_depth, _edit_radius)
|
||||
if _grass_selected != null:
|
||||
_grass_selected.sgt_radius = value
|
||||
|
||||
|
||||
func _on_slider_density_value_changed(value : float) -> void:
|
||||
_edit_density = value
|
||||
if _grass_selected != null:
|
||||
_grass_selected.sgt_density = value
|
||||
|
||||
|
||||
func _on_edit_slope_range_changed(value_min: float, value_max: float) -> void:
|
||||
_edit_slope = Vector2(value_min, value_max)
|
||||
if _grass_selected != null:
|
||||
_grass_selected.sgt_slope = _edit_slope
|
||||
|
||||
|
||||
func _on_edit_scale_value_changed(value : float) -> void:
|
||||
_edit_scale = Vector3(value, value, value)
|
||||
if _grass_selected != null:
|
||||
_grass_selected.sgt_scale = value
|
||||
|
||||
|
||||
func _on_edit_rotation_value_changed(value : float) -> void:
|
||||
_edit_rotation = value
|
||||
if _grass_selected != null:
|
||||
_grass_selected.sgt_rotation = value
|
||||
|
||||
|
||||
func _on_edit_rotation_rand_value_changed(value : float) -> void:
|
||||
_edit_rotation_rand = value
|
||||
if _grass_selected != null:
|
||||
_grass_selected.sgt_rotation_rand = value
|
||||
|
||||
|
||||
func _on_edit_distance_value_changed(value : float) -> void:
|
||||
if _grass_selected != null:
|
||||
_grass_selected.sgt_dist_min = value
|
||||
|
||||
|
||||
func _on_set_tool(value : TOOL) -> void:
|
||||
_edit_tool = value
|
||||
if _edit_tool == TOOL.AIRBRUSH:
|
||||
_pointer_decal.modulate = Color.WHITE
|
||||
_gui_toolbar.slider_density.editable = true
|
||||
_gui_toolbar.button_density.disabled = false
|
||||
_gui_toolbar.button_airbrush.button_pressed = true
|
||||
_gui_toolbar.button_pencil.button_pressed = false
|
||||
_gui_toolbar.button_eraser.button_pressed = false
|
||||
_gui_toolbar.set_density_modulate(Color.WHITE)
|
||||
elif _edit_tool == TOOL.PENCIL:
|
||||
_pointer_decal.modulate = Color.YELLOW
|
||||
_gui_toolbar.slider_density.editable = false
|
||||
_gui_toolbar.button_density.disabled = true
|
||||
_gui_toolbar.button_airbrush.button_pressed = false
|
||||
_gui_toolbar.button_pencil.button_pressed = true
|
||||
_gui_toolbar.button_eraser.button_pressed = false
|
||||
_gui_toolbar.set_density_modulate(Color(1, 1, 1, 0.25))
|
||||
elif _edit_tool == TOOL.ERASER:
|
||||
_pointer_decal.modulate = Color.RED
|
||||
_gui_toolbar.slider_density.editable = false
|
||||
_gui_toolbar.button_density.disabled = true
|
||||
_gui_toolbar.button_airbrush.button_pressed = false
|
||||
_gui_toolbar.button_pencil.button_pressed = false
|
||||
_gui_toolbar.button_eraser.button_pressed = true
|
||||
_gui_toolbar.set_density_modulate(Color(1, 1, 1, 0.25))
|
||||
if _grass_selected != null:
|
||||
_pointer_decal.visible = _edit_tool != TOOL.NONE
|
||||
else:
|
||||
_pointer_decal.visible = false
|
||||
|
||||
|
||||
func _eval_brush() -> void:
|
||||
if _grass_selected == null:
|
||||
return
|
||||
if _edit_tool == TOOL.PENCIL:
|
||||
var steep : float = _grass_selected.sgt_dist_min
|
||||
var list_trans := []
|
||||
var follow_normal : bool = _grass_selected.sgt_follow_normal
|
||||
var slope := Vector2(deg_to_rad(_grass_selected.sgt_slope.x), deg_to_rad(_grass_selected.sgt_slope.y))
|
||||
if steep < 0.05:
|
||||
steep = 0.4
|
||||
_grass_selected.temp_dist_min = steep
|
||||
var x := -_edit_radius
|
||||
while x < _edit_radius:
|
||||
var z := -_edit_radius
|
||||
while z < _edit_radius:
|
||||
var variation: Vector3
|
||||
match _grass_selected.sgt_tool_shape["pencil"]:
|
||||
TOOL_SHAPE.SPHERE, TOOL_SHAPE.CYLINDER, TOOL_SHAPE.CYLINDER_INF_H:
|
||||
variation = Vector3(x + (randf() * steep * 0.5), 0, z + (randf() * steep * 0.5))
|
||||
if variation.length() >= _edit_radius:
|
||||
z += steep
|
||||
continue
|
||||
TOOL_SHAPE.BOX, TOOL_SHAPE.BOX_INF_H:
|
||||
variation = Vector3(x + (randf() * steep * 0.5), 0, z + (randf() * steep * 0.5))
|
||||
_:
|
||||
variation = Vector3(x + (randf() * steep * 0.5), 0, z + (randf() * steep * 0.5))
|
||||
if variation.length() >= _edit_radius:
|
||||
z += steep
|
||||
continue
|
||||
variation = _pointer_decal.to_global(variation) - _pointer_decal.global_position
|
||||
_raycast_3d.global_transform.basis.x = Vector3.RIGHT
|
||||
_raycast_3d.global_transform.basis.y = _normal_draw * -1
|
||||
_raycast_3d.global_transform.basis.z = Vector3.BACK
|
||||
_raycast_3d.global_transform.origin = _position_draw + _normal_draw + variation
|
||||
_raycast_3d.target_position = Vector3(0, _pointer_depth, 0)
|
||||
_raycast_3d.collision_mask = _grass_selected.collision_mask
|
||||
_raycast_3d.force_raycast_update()
|
||||
var pos_grass : Vector3 = _raycast_3d.get_collision_point()
|
||||
if _raycast_3d.is_colliding() and _raycast_3d.get_collider() == _object_draw:
|
||||
var normal := _raycast_3d.get_collision_normal()
|
||||
if normal.angle_to(Vector3.UP) < slope.x or normal.angle_to(Vector3.UP) > slope.y:
|
||||
z += steep
|
||||
continue
|
||||
if not follow_normal:
|
||||
normal = Vector3.UP
|
||||
list_trans.append(_grass_selected.eval_grass_transform(
|
||||
_raycast_3d.get_collision_point() - _grass_selected.global_position,
|
||||
normal,
|
||||
_edit_scale,
|
||||
deg_to_rad(_edit_rotation) + (PI * (_edit_rotation_rand - (randf() * _edit_rotation_rand * 2.0)))
|
||||
))
|
||||
z += steep
|
||||
x += steep
|
||||
_grass_selected.add_grass_batch(list_trans)
|
||||
elif _edit_tool == TOOL.AIRBRUSH:
|
||||
var follow_normal : bool = _grass_selected.sgt_follow_normal
|
||||
var slope := Vector2(deg_to_rad(_grass_selected.sgt_slope.x), deg_to_rad(_grass_selected.sgt_slope.y))
|
||||
for i in _edit_density:
|
||||
var variation: Vector3
|
||||
match _grass_selected.sgt_tool_shape["airbrush"]:
|
||||
TOOL_SHAPE.SPHERE, TOOL_SHAPE.CYLINDER, TOOL_SHAPE.CYLINDER_INF_H:
|
||||
variation = Vector3.RIGHT * _edit_radius * randf()
|
||||
variation = variation.rotated(Vector3.UP, randf() * TAU)
|
||||
TOOL_SHAPE.BOX, TOOL_SHAPE.BOX_INF_H:
|
||||
variation = Vector3(randf_range(-1, 1), 0, randf_range(-1, 1)) * _edit_radius
|
||||
_:
|
||||
variation = Vector3.RIGHT * _edit_radius * randf()
|
||||
variation = variation.rotated(Vector3.UP, randf() * TAU)
|
||||
variation = _pointer_decal.to_global(variation) - _pointer_decal.global_position
|
||||
_raycast_3d.global_transform.basis.x = Vector3.RIGHT
|
||||
_raycast_3d.global_transform.basis.y = _normal_draw * -1
|
||||
_raycast_3d.global_transform.basis.z = Vector3.BACK
|
||||
_raycast_3d.global_transform.origin = _position_draw + _normal_draw + variation
|
||||
_raycast_3d.target_position = Vector3(0, _pointer_depth, 0)
|
||||
_raycast_3d.collision_mask = _grass_selected.collision_mask
|
||||
_raycast_3d.force_raycast_update()
|
||||
if _raycast_3d.is_colliding() and _raycast_3d.get_collider() == _object_draw:
|
||||
var normal := _raycast_3d.get_collision_normal()
|
||||
if normal.angle_to(Vector3.UP) < slope.x or normal.angle_to(Vector3.UP) > slope.y:
|
||||
continue
|
||||
if not follow_normal:
|
||||
normal = Vector3.UP
|
||||
_grass_selected.add_grass(
|
||||
_raycast_3d.get_collision_point() - _grass_selected.global_position,
|
||||
normal,
|
||||
_edit_scale,
|
||||
deg_to_rad(_edit_rotation) + (PI * (_edit_rotation_rand - (randf() * _edit_rotation_rand * 2.0)))
|
||||
)
|
||||
elif _edit_tool == TOOL.ERASER:
|
||||
match _grass_selected.sgt_tool_shape["eraser"]:
|
||||
TOOL_SHAPE.SPHERE:
|
||||
_grass_selected.erase(_position_draw - _grass_selected.global_position, _edit_radius)
|
||||
TOOL_SHAPE.CYLINDER:
|
||||
_grass_selected.erase_cylinder(_position_draw - _grass_selected.global_position, _edit_radius, _pointer_depth, _edit_radius, _pointer_decal.global_transform)
|
||||
TOOL_SHAPE.CYLINDER_INF_H:
|
||||
_grass_selected.erase_cylinder(_position_draw - _grass_selected.global_position, _edit_radius, 1000000, _edit_radius, _pointer_decal.global_transform)
|
||||
TOOL_SHAPE.BOX:
|
||||
_grass_selected.erase_box(_position_draw, Vector3(_edit_radius, _edit_radius, _edit_radius) * 2, _pointer_decal.global_transform)
|
||||
TOOL_SHAPE.BOX_INF_H:
|
||||
_grass_selected.erase_box(_position_draw - _grass_selected.global_position, Vector3(_edit_radius, 1000000, _edit_radius) * 2, _pointer_decal.global_transform)
|
||||
if _grass_selected.multimesh != null:
|
||||
_gui_toolbar.label_stats.text = "Count: " + str(_grass_selected.multimesh.instance_count)
|
||||
Reference in New Issue
Block a user