121 lines
3.7 KiB
GDScript
121 lines
3.7 KiB
GDScript
extends EditorInspectorPlugin
|
|
|
|
|
|
func _can_handle(object: Object) -> bool:
|
|
return true
|
|
|
|
|
|
func _parse_property(object: Object, type: Variant.Type, name: String, hint_type: PropertyHint, hint_string: String, usage_flags: int, wide: bool) -> bool:
|
|
if type == TYPE_VECTOR2 and hint_string == "direction":
|
|
add_property_editor(name, DirectionInspector.new(), false)
|
|
return true
|
|
return false
|
|
|
|
|
|
class DirectionInspector extends EditorProperty:
|
|
var angle_selector: AngleSelector
|
|
var snap_toggle: TextureButton
|
|
var snap_spinbox: SpinBox
|
|
|
|
var current_value: Vector2
|
|
var updating := false
|
|
var snap := false
|
|
var snap_amount: int = 0
|
|
|
|
func _init() -> void:
|
|
var hbox = HBoxContainer.new()
|
|
hbox.alignment = BoxContainer.ALIGNMENT_BEGIN
|
|
add_child(hbox)
|
|
|
|
var vbox = VBoxContainer.new()
|
|
vbox.alignment = BoxContainer.ALIGNMENT_BEGIN
|
|
vbox.add_theme_constant_override(&"separation", 4)
|
|
vbox.add_spacer(true)
|
|
hbox.add_child(vbox)
|
|
|
|
snap_toggle = TextureButton.new()
|
|
snap_toggle.toggle_mode = true
|
|
snap_toggle.toggled.connect(_on_snap_toggled)
|
|
snap_toggle.texture_normal = EditorInterface.get_editor_theme().get_icon(&"Snap", &"EditorIcons")
|
|
snap_toggle.texture_pressed = snap_toggle.texture_normal
|
|
snap_toggle.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN
|
|
snap_toggle.stretch_mode = TextureButton.STRETCH_KEEP_ASPECT
|
|
vbox.add_child(snap_toggle)
|
|
|
|
snap_spinbox = SpinBox.new()
|
|
snap_spinbox.editable = false
|
|
snap_spinbox.rounded = true
|
|
snap_spinbox.value_changed.connect(_on_snap_amount_changed)
|
|
snap_spinbox.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
|
snap_spinbox.custom_minimum_size = Vector2.ZERO
|
|
vbox.add_child(snap_spinbox)
|
|
|
|
angle_selector = AngleSelector.new()
|
|
angle_selector.direction_clicked.connect(_on_direction_clicked)
|
|
hbox.add_child(angle_selector)
|
|
add_focusable(angle_selector)
|
|
|
|
custom_minimum_size = get_combined_minimum_size()
|
|
size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
|
|
|
_refresh()
|
|
|
|
func _update_property() -> void:
|
|
var new_value: Vector2 = get_edited_object()[get_edited_property()]
|
|
if new_value == current_value:
|
|
return
|
|
|
|
updating = true
|
|
current_value = new_value
|
|
_refresh()
|
|
updating = false
|
|
|
|
func _refresh() -> void:
|
|
angle_selector.direction = current_value
|
|
|
|
func _on_direction_clicked(direction: Vector2) -> void:
|
|
if updating:
|
|
return
|
|
|
|
current_value = direction
|
|
if snap and snap_amount > 0:
|
|
var angle = direction.angle()
|
|
var steps = PI * 0.5 / float(snap_amount)
|
|
angle = roundf(angle / steps) * steps
|
|
current_value = Vector2.from_angle(angle)
|
|
_refresh()
|
|
emit_changed(get_edited_property(), current_value)
|
|
|
|
func _on_snap_toggled(toggled_on: bool) -> void:
|
|
snap = toggled_on
|
|
snap_spinbox.editable = snap
|
|
if toggled_on:
|
|
snap_toggle.modulate = EditorInterface.get_editor_theme().get_color(&"accent_color", &"Editor")
|
|
else:
|
|
snap_toggle.modulate = Color.WHITE
|
|
|
|
func _on_snap_amount_changed(value: float) -> void:
|
|
snap_amount = maxi(0, int(value))
|
|
|
|
class AngleSelector extends Control:
|
|
signal direction_clicked(direction: Vector2)
|
|
|
|
var direction: Vector2:
|
|
set(value):
|
|
direction = value.normalized()
|
|
queue_redraw()
|
|
|
|
func _init() -> void:
|
|
custom_minimum_size = Vector2(48.0, 48.0)
|
|
focus_mode = Control.FOCUS_CLICK
|
|
|
|
func _gui_input(event: InputEvent) -> void:
|
|
if event is InputEventMouseButton or event is InputEventMouseMotion:
|
|
if Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT):
|
|
direction_clicked.emit((size * 0.5).direction_to(get_local_mouse_position()))
|
|
|
|
func _draw() -> void:
|
|
var center = size * 0.5
|
|
var radius = minf(center.x, center.y)
|
|
draw_circle(center, radius, Color.WHITE, false)
|
|
draw_line(center, center + direction * radius, Color.RED, 2.0)
|