|
|
|
@tool
|
|
|
|
extends EditorPlugin
|
|
|
|
|
|
|
|
const CONTAINER := CustomControlContainer.CONTAINER_SPATIAL_EDITOR_SIDE_RIGHT
|
|
|
|
@onready var controls_scene := preload("terrain_editing_controls.tscn")
|
|
|
|
@onready var controls : TerrainEditingControls = controls_scene.instantiate()
|
|
|
|
|
|
|
|
var current_terrain : StaticBody3D
|
|
|
|
|
|
|
|
func _handles(object: Object) -> bool:
|
|
|
|
return is_terrain(object)
|
|
|
|
|
|
|
|
func _make_visible(visible: bool) -> void:
|
|
|
|
if visible:
|
|
|
|
add_control_to_container(CONTAINER, controls)
|
|
|
|
elif controls and controls.get_parent():
|
|
|
|
remove_control_from_container(CONTAINER, controls)
|
|
|
|
|
|
|
|
func _forward_3d_gui_input(camera: Camera3D, event: InputEvent) -> int:
|
|
|
|
var position := Vector3.ZERO
|
|
|
|
|
|
|
|
if event is InputEventMouse:
|
|
|
|
var previous_terrain := current_terrain
|
|
|
|
current_terrain = null
|
|
|
|
|
|
|
|
var viewport := EditorInterface.get_editor_viewport_3d()
|
|
|
|
if viewport.get_visible_rect().has_point(event.position):
|
|
|
|
var from := camera.project_ray_origin(event.position)
|
|
|
|
var to := from + camera.project_ray_normal(event.position) * camera.far
|
|
|
|
|
|
|
|
var root := EditorInterface.get_edited_scene_root() as Node3D
|
|
|
|
var space := root.get_world_3d().direct_space_state
|
|
|
|
var query := PhysicsRayQueryParameters3D.create(from, to)
|
|
|
|
|
|
|
|
var result := space.intersect_ray(query)
|
|
|
|
var terrain := result.get("collider") as StaticBody3D
|
|
|
|
if is_terrain(terrain):
|
|
|
|
current_terrain = terrain
|
|
|
|
position = result["position"]
|
|
|
|
|
|
|
|
if previous_terrain and previous_terrain != current_terrain:
|
|
|
|
previous_terrain.EditorUnfocus()
|
|
|
|
|
|
|
|
if current_terrain:
|
|
|
|
# Allow terrain access to editor undo redo functionality.
|
|
|
|
current_terrain.EditorUndoRedo = get_undo_redo()
|
|
|
|
if current_terrain.EditorInput(event, controls, position):
|
|
|
|
return AFTER_GUI_INPUT_STOP
|
|
|
|
|
|
|
|
return AFTER_GUI_INPUT_PASS
|
|
|
|
|
|
|
|
func is_terrain(object: Object) -> bool:
|
|
|
|
if not object: return false
|
|
|
|
var script := object.get_script() as CSharpScript
|
|
|
|
return script and script.resource_path.ends_with("/Terrain.cs")
|