278 lines
8.9 KiB
GDScript
278 lines
8.9 KiB
GDScript
@tool
|
|
class_name PopochiuGizmoClickablePlugin
|
|
extends EditorPlugin
|
|
|
|
# TODO: move these out of the plugin and into Popochiu (enums) or PopochiuClickable
|
|
enum {
|
|
WALK_TO_POINT,
|
|
LOOK_AT_POINT,
|
|
BASELINE,
|
|
DIALOG_POS
|
|
}
|
|
|
|
# Private vars
|
|
# State
|
|
var _target_node: Node2D
|
|
var _undo: EditorUndoRedoManager
|
|
var _gizmos: Array
|
|
var _active_gizmos: Array
|
|
var _grabbed_gizmo: Gizmo2D
|
|
|
|
|
|
#region Godot ######################################################################################
|
|
|
|
func _enter_tree() -> void:
|
|
# TODO: remove the following 2 lines when the plugin is connected to the appropriate signal
|
|
# e.g. popochiu_ready
|
|
PopochiuEditorConfig.initialize_editor_settings()
|
|
PopochiuConfig.initialize_project_settings()
|
|
|
|
# Initialization of the plugin goes here.
|
|
_undo = get_undo_redo()
|
|
_gizmos.insert(WALK_TO_POINT, _init_popochiu_gizmo(WALK_TO_POINT))
|
|
_gizmos.insert(LOOK_AT_POINT, _init_popochiu_gizmo(LOOK_AT_POINT))
|
|
_gizmos.insert(BASELINE, _init_popochiu_gizmo(BASELINE))
|
|
_gizmos.insert(DIALOG_POS, _init_popochiu_gizmo(DIALOG_POS))
|
|
|
|
EditorInterface.get_editor_settings().settings_changed.connect(_on_gizmo_settings_changed)
|
|
PopochiuEditorHelper.signal_bus.gizmo_visibility_changed.connect(_on_gizmo_visibility_changed)
|
|
|
|
|
|
#endregion
|
|
|
|
#region Virtual ####################################################################################
|
|
|
|
func _edit(object: Object) -> void:
|
|
if object == null or object.get_class() == "EditorDebuggerRemoteObject":
|
|
return
|
|
|
|
_target_node = object
|
|
_active_gizmos.clear()
|
|
|
|
if EditorInterface.get_edited_scene_root() is PopochiuCharacter:
|
|
_active_gizmos.append(_gizmos[DIALOG_POS])
|
|
elif EditorInterface.get_edited_scene_root() is PopochiuRoom:
|
|
_active_gizmos.append(_gizmos[WALK_TO_POINT])
|
|
_active_gizmos.append(_gizmos[LOOK_AT_POINT])
|
|
_active_gizmos.append(_gizmos[BASELINE])
|
|
|
|
for gizmo in _active_gizmos:
|
|
gizmo.set_target_node(_target_node)
|
|
|
|
if not EditorInterface.get_inspector().property_edited.is_connected(_on_property_changed):
|
|
EditorInterface.get_inspector().property_edited.connect(_on_property_changed)
|
|
update_overlays()
|
|
|
|
|
|
func _forward_canvas_draw_over_viewport(viewport_control: Control) -> void:
|
|
for gizmo in _active_gizmos:
|
|
gizmo.draw(viewport_control, _target_node.get(gizmo.target_property))
|
|
|
|
|
|
func _handles(object: Object) -> bool:
|
|
return object is PopochiuClickable
|
|
|
|
|
|
func _forward_canvas_gui_input(event: InputEvent) -> bool:
|
|
if not _target_node or not _target_node.is_visible_in_tree():
|
|
return false
|
|
|
|
# For left mouse buttons, try to grab or release, depending on state
|
|
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT:
|
|
# Grab
|
|
if not _grabbed_gizmo and event.is_pressed():
|
|
return _try_grab_gizmo(event)
|
|
# Release
|
|
elif _grabbed_gizmo and event.is_released():
|
|
return _release_gizmo(event)
|
|
|
|
# For mouse movement, drag the grabbed gizmo
|
|
if event is InputEventMouseMotion:
|
|
return _drag_gizmo(event)
|
|
|
|
# For ESC key or comparable events, cancel the dragging if in place
|
|
if event.is_action_pressed("ui_cancel"):
|
|
return _cancel_dragging_gizmo(event)
|
|
|
|
## Nothing to handle outside the cases above
|
|
return false
|
|
|
|
|
|
#endregion
|
|
|
|
#region Private ####################################################################################
|
|
|
|
func _on_property_changed(property: String):
|
|
update_overlays()
|
|
|
|
|
|
func _on_gizmo_settings_changed() -> void:
|
|
var gizmo_id = 0
|
|
var default_font = EditorInterface.get_editor_theme().default_font
|
|
|
|
for gizmo in _gizmos:
|
|
match gizmo_id:
|
|
WALK_TO_POINT:
|
|
gizmo.set_theme(
|
|
PopochiuEditorConfig.get_editor_setting(PopochiuEditorConfig.GIZMOS_WALK_TO_POINT_COLOR),
|
|
PopochiuEditorConfig.get_editor_setting(PopochiuEditorConfig.GIZMOS_HANDLER_SIZE),
|
|
default_font,
|
|
PopochiuEditorConfig.get_editor_setting(PopochiuEditorConfig.GIZMOS_FONT_SIZE)
|
|
)
|
|
LOOK_AT_POINT:
|
|
gizmo.set_theme(
|
|
PopochiuEditorConfig.get_editor_setting(PopochiuEditorConfig.GIZMOS_LOOK_AT_POINT_COLOR),
|
|
PopochiuEditorConfig.get_editor_setting(PopochiuEditorConfig.GIZMOS_HANDLER_SIZE),
|
|
default_font,
|
|
PopochiuEditorConfig.get_editor_setting(PopochiuEditorConfig.GIZMOS_FONT_SIZE)
|
|
)
|
|
BASELINE:
|
|
gizmo.set_theme(
|
|
PopochiuEditorConfig.get_editor_setting(PopochiuEditorConfig.GIZMOS_BASELINE_COLOR),
|
|
PopochiuEditorConfig.get_editor_setting(PopochiuEditorConfig.GIZMOS_HANDLER_SIZE),
|
|
default_font,
|
|
PopochiuEditorConfig.get_editor_setting(PopochiuEditorConfig.GIZMOS_FONT_SIZE)
|
|
)
|
|
DIALOG_POS:
|
|
gizmo.set_theme(
|
|
PopochiuEditorConfig.get_editor_setting(PopochiuEditorConfig.GIZMOS_DIALOG_POS_COLOR),
|
|
PopochiuEditorConfig.get_editor_setting(PopochiuEditorConfig.GIZMOS_HANDLER_SIZE),
|
|
default_font,
|
|
PopochiuEditorConfig.get_editor_setting(PopochiuEditorConfig.GIZMOS_FONT_SIZE)
|
|
)
|
|
|
|
gizmo.show_connector = PopochiuEditorConfig.get_editor_setting(PopochiuEditorConfig.GIZMOS_SHOW_CONNECTORS)
|
|
gizmo.show_outlines = PopochiuEditorConfig.get_editor_setting(PopochiuEditorConfig.GIZMOS_SHOW_OUTLINE)
|
|
gizmo.show_target_name = PopochiuEditorConfig.get_editor_setting(PopochiuEditorConfig.GIZMOS_SHOW_NODE_NAME)
|
|
gizmo_id += 1
|
|
|
|
update_overlays()
|
|
|
|
|
|
func _on_gizmo_visibility_changed(gizmo_id:int, visibility:bool):
|
|
if gizmo_id < _gizmos.size():
|
|
_gizmos[gizmo_id].visible = visibility
|
|
update_overlays()
|
|
|
|
func _update_properties():
|
|
if _grabbed_gizmo and _grabbed_gizmo.target_property:
|
|
_target_node.set(
|
|
_grabbed_gizmo.target_property,
|
|
_grabbed_gizmo.get_position()
|
|
)
|
|
|
|
|
|
func _init_popochiu_gizmo(gizmo_id: int) -> Gizmo2D:
|
|
var gizmo: Gizmo2D
|
|
var default_font = EditorInterface.get_editor_theme().default_font
|
|
|
|
match gizmo_id:
|
|
WALK_TO_POINT:
|
|
gizmo = Gizmo2D.new(_target_node, "walk_to_point", "Walk To Point", Gizmo2D.GIZMO_POS)
|
|
gizmo.set_theme(
|
|
PopochiuEditorConfig.get_editor_setting(PopochiuEditorConfig.GIZMOS_WALK_TO_POINT_COLOR),
|
|
PopochiuEditorConfig.get_editor_setting(PopochiuEditorConfig.GIZMOS_HANDLER_SIZE),
|
|
default_font,
|
|
PopochiuEditorConfig.get_editor_setting(PopochiuEditorConfig.GIZMOS_FONT_SIZE)
|
|
)
|
|
LOOK_AT_POINT:
|
|
gizmo = Gizmo2D.new(_target_node, "look_at_point", "Look At Point", Gizmo2D.GIZMO_POS)
|
|
gizmo.set_theme(
|
|
PopochiuEditorConfig.get_editor_setting(PopochiuEditorConfig.GIZMOS_LOOK_AT_POINT_COLOR),
|
|
PopochiuEditorConfig.get_editor_setting(PopochiuEditorConfig.GIZMOS_HANDLER_SIZE),
|
|
default_font,
|
|
PopochiuEditorConfig.get_editor_setting(PopochiuEditorConfig.GIZMOS_FONT_SIZE)
|
|
)
|
|
BASELINE:
|
|
gizmo = Gizmo2D.new(_target_node, "baseline", "Baseline", Gizmo2D.GIZMO_VPOS)
|
|
gizmo.set_theme(
|
|
PopochiuEditorConfig.get_editor_setting(PopochiuEditorConfig.GIZMOS_BASELINE_COLOR),
|
|
PopochiuEditorConfig.get_editor_setting(PopochiuEditorConfig.GIZMOS_HANDLER_SIZE),
|
|
default_font,
|
|
PopochiuEditorConfig.get_editor_setting(PopochiuEditorConfig.GIZMOS_FONT_SIZE)
|
|
)
|
|
DIALOG_POS:
|
|
gizmo = Gizmo2D.new(_target_node, "dialog_pos", "Dialog Position", Gizmo2D.GIZMO_POS)
|
|
gizmo.set_theme(
|
|
PopochiuEditorConfig.get_editor_setting(PopochiuEditorConfig.GIZMOS_DIALOG_POS_COLOR),
|
|
PopochiuEditorConfig.get_editor_setting(PopochiuEditorConfig.GIZMOS_HANDLER_SIZE),
|
|
default_font,
|
|
PopochiuEditorConfig.get_editor_setting(PopochiuEditorConfig.GIZMOS_FONT_SIZE)
|
|
)
|
|
return gizmo
|
|
|
|
|
|
func _try_grab_gizmo(event: InputEventMouseButton) -> bool:
|
|
# Check if the mouse click happened on a gizmo
|
|
# The order is reversed to the topmost gizmo
|
|
# (the last been drawn) is selected
|
|
for i in range(_active_gizmos.size() - 1, -1, -1):
|
|
if not _active_gizmos[i].has_point(event.position):
|
|
continue
|
|
_grabbed_gizmo = _active_gizmos[i]
|
|
break
|
|
|
|
# If user clicked on no gizmos
|
|
# ignore the event
|
|
if not _grabbed_gizmo:
|
|
return false
|
|
|
|
# hold the gizmo with the mouse
|
|
_grabbed_gizmo.grab(event.position)
|
|
_undo.create_action("Move gizmo")
|
|
_undo.add_undo_property(
|
|
_grabbed_gizmo.target_node,
|
|
_grabbed_gizmo.target_property,
|
|
_grabbed_gizmo.target_node.get(_grabbed_gizmo.target_property)
|
|
)
|
|
update_overlays()
|
|
return true
|
|
|
|
|
|
func _release_gizmo(event: InputEvent) -> bool:
|
|
# If there is no gizmo to release
|
|
# ignore the event
|
|
if not _grabbed_gizmo:
|
|
return false
|
|
|
|
_grabbed_gizmo.release()
|
|
_undo.add_do_property(
|
|
_grabbed_gizmo.target_node,
|
|
_grabbed_gizmo.target_property,
|
|
_grabbed_gizmo.target_node.get(_grabbed_gizmo.target_property)
|
|
)
|
|
_undo.commit_action()
|
|
update_overlays()
|
|
_grabbed_gizmo = null
|
|
return true
|
|
|
|
|
|
func _drag_gizmo(event: InputEvent) -> bool:
|
|
# If no gizmo to drag
|
|
# ignore the event
|
|
if not _grabbed_gizmo:
|
|
return false
|
|
|
|
# Drag the gizmo
|
|
_grabbed_gizmo.drag_to(event.position)
|
|
_update_properties()
|
|
update_overlays()
|
|
return true
|
|
|
|
|
|
func _cancel_dragging_gizmo(event: InputEvent) -> bool:
|
|
# If ESC/Cancel happens but we're not dragging
|
|
# ignore the event
|
|
if not _grabbed_gizmo:
|
|
return false
|
|
|
|
# Cancel the action
|
|
_grabbed_gizmo.cancel()
|
|
_undo.commit_action()
|
|
_undo.get_history_undo_redo(_undo.get_object_history_id(_grabbed_gizmo.target_node)).undo()
|
|
update_overlays()
|
|
_grabbed_gizmo = null
|
|
return true
|
|
|
|
|
|
#endregion
|