247 lines
7.2 KiB
GDScript3
247 lines
7.2 KiB
GDScript3
|
tool
|
||
|
extends TextEdit
|
||
|
|
||
|
|
||
|
const ChooseTitleDialog = preload("res://addons/dialogue_manager/views/choose_title_dialog.gd")
|
||
|
|
||
|
|
||
|
signal active_title_changed(title)
|
||
|
|
||
|
|
||
|
export var _choose_title_dialog := NodePath()
|
||
|
|
||
|
onready var choose_title_dialog: ChooseTitleDialog = get_node(_choose_title_dialog)
|
||
|
|
||
|
var active_title_id: int = 0
|
||
|
var current_goto_title: String = ""
|
||
|
var current_goto_line: int = -1
|
||
|
var last_selection_text: String = ""
|
||
|
|
||
|
var GOTO_ITEM_INDEX = -1
|
||
|
var CREATE_ITEM_INDEX = -1
|
||
|
var PICK_ITEM_INDEX = -1
|
||
|
|
||
|
|
||
|
func _ready() -> void:
|
||
|
# Set up popup menu
|
||
|
var menu = get_menu()
|
||
|
menu.connect("about_to_show", self, "_on_menu_about_to_show")
|
||
|
menu.connect("index_pressed", self, "_on_menu_index_pressed")
|
||
|
menu.add_separator()
|
||
|
|
||
|
menu.add_item("Go to " + current_goto_title, 101, KEY_MASK_CTRL | KEY_MASK_SHIFT | KEY_G)
|
||
|
GOTO_ITEM_INDEX = menu.get_item_index(101)
|
||
|
|
||
|
menu.add_item("Create " + current_goto_title, 102, KEY_MASK_CTRL | KEY_MASK_SHIFT | KEY_C)
|
||
|
CREATE_ITEM_INDEX = menu.get_item_index(102)
|
||
|
|
||
|
menu.add_icon_item(get_icon("Search", "EditorIcons"), "Choose a jump target...", 103, KEY_MASK_CTRL | KEY_MASK_SHIFT | KEY_SPACE)
|
||
|
PICK_ITEM_INDEX = menu.get_item_index(103)
|
||
|
|
||
|
# Set up choose title dialog
|
||
|
choose_title_dialog.connect("title_chosen", self, "_on_title_chosen")
|
||
|
|
||
|
# Colors
|
||
|
var title_color = get_color("accent_color", "Editor")
|
||
|
var comment_color = get_color("font_color", "Editor")
|
||
|
comment_color.a = 0.5
|
||
|
var condition_color = get_color("error_color", "Editor")
|
||
|
var value_color = get_color("warning_color", "Editor")
|
||
|
var mutation_color = get_color("success_color", "Editor")
|
||
|
var goto_color = get_color("accent_color", "Editor")
|
||
|
goto_color.a = 0.7
|
||
|
var dialogue_color = get_color("mono_color", "Editor")
|
||
|
|
||
|
# Title
|
||
|
add_color_region("~", "~", title_color, true)
|
||
|
|
||
|
# Comments
|
||
|
add_color_region("#", "##", comment_color, true)
|
||
|
|
||
|
# Conditions
|
||
|
add_keyword_color("if", condition_color)
|
||
|
add_keyword_color("elif", condition_color)
|
||
|
add_keyword_color("else", condition_color)
|
||
|
add_keyword_color("endif", condition_color)
|
||
|
add_keyword_color("in", condition_color)
|
||
|
add_keyword_color("and", condition_color)
|
||
|
add_keyword_color("or", condition_color)
|
||
|
add_keyword_color("not", condition_color)
|
||
|
|
||
|
# Values
|
||
|
add_keyword_color("true", value_color)
|
||
|
add_keyword_color("false", value_color)
|
||
|
add_color_override("number_color", value_color)
|
||
|
add_color_region("\"", "\"", value_color)
|
||
|
|
||
|
# Mutations
|
||
|
add_keyword_color("do", mutation_color)
|
||
|
add_keyword_color("set", mutation_color)
|
||
|
add_color_override("function_color", mutation_color)
|
||
|
|
||
|
# Jumps
|
||
|
add_color_region("=>", "<=", goto_color, true)
|
||
|
|
||
|
# Dialogue
|
||
|
add_color_region(": ", "::", dialogue_color, true)
|
||
|
|
||
|
# Errors
|
||
|
add_color_override("bookmark_color", Color("ff5555"))
|
||
|
|
||
|
# General UI
|
||
|
add_constant_override("line_spacing", 10)
|
||
|
add_color_override("symbol_color", get_color("font_color", "Editor"))
|
||
|
add_color_override("font_color", get_color("font_color", "Editor"))
|
||
|
add_color_override("background_color", get_color("base_color", "Editor"))
|
||
|
add_color_override("current_line_color", get_color("base_color", "Editor").lightened(0.1))
|
||
|
add_font_override("font", get_font("source", "EditorFonts"))
|
||
|
|
||
|
|
||
|
func _gui_input(event):
|
||
|
if not event is InputEventKey: return
|
||
|
if not event.is_pressed(): return
|
||
|
|
||
|
match event.as_text():
|
||
|
"Control+Shift+G":
|
||
|
go_to_title(current_goto_title)
|
||
|
"Control+Shift+C":
|
||
|
create_title(current_goto_title)
|
||
|
"Control+Shift+Space":
|
||
|
choose_title_dialog.choose_a_title(get_titles())
|
||
|
|
||
|
|
||
|
func insert_bbcode(open_tag: String, close_tag: String = "") -> void:
|
||
|
if close_tag == "":
|
||
|
insert_text_at_cursor(open_tag)
|
||
|
grab_focus()
|
||
|
else:
|
||
|
var selected_text = get_selection_text()
|
||
|
insert_text_at_cursor("%s%s%s" % [open_tag, selected_text, close_tag])
|
||
|
grab_focus()
|
||
|
cursor_set_column(cursor_get_column() - close_tag.length())
|
||
|
|
||
|
|
||
|
func get_titles() -> Array:
|
||
|
var titles = PoolStringArray([])
|
||
|
var lines = text.split("\n")
|
||
|
for line in lines:
|
||
|
if line.begins_with("~ "):
|
||
|
titles.append(line.substr(2).strip_edges())
|
||
|
return titles
|
||
|
|
||
|
|
||
|
func go_to_title(title: String) -> void:
|
||
|
var lines = text.split("\n")
|
||
|
for i in range(0, lines.size()):
|
||
|
if lines[i].strip_edges() == "~ " + title:
|
||
|
cursor_set_line(i)
|
||
|
center_viewport_to_cursor()
|
||
|
|
||
|
|
||
|
func create_title(title: String) -> void:
|
||
|
text = text + "\n\n~ " + title + "\n\nCharacter: This is a new node."
|
||
|
emit_signal("text_changed")
|
||
|
cursor_set_line(get_line_count() - 1)
|
||
|
|
||
|
|
||
|
func check_active_title() -> void:
|
||
|
var line_number = cursor_get_line()
|
||
|
var lines = text.split("\n")
|
||
|
# Look at each line above this one to find the next title line
|
||
|
for i in range(line_number, -1, -1):
|
||
|
if lines[i].begins_with("~ "):
|
||
|
emit_signal("active_title_changed", lines[i].replace("~ ", ""))
|
||
|
active_title_id = i
|
||
|
break
|
||
|
|
||
|
|
||
|
func update_current_goto_title() -> void:
|
||
|
var line_number = cursor_get_line()
|
||
|
var current_line = get_line(line_number)
|
||
|
|
||
|
# If we are on a goto line then make a note of the title and the line
|
||
|
# of the target title (if it exists)
|
||
|
if "=> " in current_line:
|
||
|
current_goto_title = current_line.substr(current_line.find("=> ") + 3).strip_edges()
|
||
|
# Check if title exists
|
||
|
current_goto_line = -1
|
||
|
var lines = text.split("\n")
|
||
|
for i in range(0, lines.size()):
|
||
|
if lines[i].strip_edges() == "~ " + current_goto_title:
|
||
|
current_goto_line = i
|
||
|
break
|
||
|
|
||
|
# Otherwise just clear it out
|
||
|
else:
|
||
|
current_goto_title = ""
|
||
|
current_goto_line = -1
|
||
|
|
||
|
|
||
|
### Signals
|
||
|
|
||
|
|
||
|
func _on_menu_about_to_show():
|
||
|
update_current_goto_title()
|
||
|
|
||
|
# Update our special menu items based on what the goto details are
|
||
|
var menu = get_menu()
|
||
|
if current_goto_title != "":
|
||
|
# END is a special title which ends the conversation. It never points
|
||
|
# to an actual title
|
||
|
if current_goto_title == "END":
|
||
|
menu.set_item_text(CREATE_ITEM_INDEX, "Create node")
|
||
|
menu.set_item_disabled(CREATE_ITEM_INDEX, true)
|
||
|
menu.set_item_text(GOTO_ITEM_INDEX, "Jump to node")
|
||
|
menu.set_item_disabled(GOTO_ITEM_INDEX, true)
|
||
|
# Otherwise we can either go to the title or create it if it doesn't
|
||
|
# exist.
|
||
|
else:
|
||
|
menu.set_item_text(GOTO_ITEM_INDEX, "Jump to " + current_goto_title)
|
||
|
menu.set_item_disabled(GOTO_ITEM_INDEX, current_goto_line == -1)
|
||
|
menu.set_item_text(CREATE_ITEM_INDEX, "Create " + current_goto_title)
|
||
|
menu.set_item_disabled(CREATE_ITEM_INDEX, current_goto_line > -1)
|
||
|
menu.set_item_disabled(PICK_ITEM_INDEX, false)
|
||
|
|
||
|
# If we aren't on a goto line then just disable the options
|
||
|
else:
|
||
|
menu.set_item_text(GOTO_ITEM_INDEX, "Jump to node")
|
||
|
menu.set_item_disabled(GOTO_ITEM_INDEX, true)
|
||
|
menu.set_item_text(CREATE_ITEM_INDEX, "Create node")
|
||
|
menu.set_item_disabled(CREATE_ITEM_INDEX, true)
|
||
|
menu.set_item_disabled(PICK_ITEM_INDEX, true)
|
||
|
|
||
|
|
||
|
func _on_menu_index_pressed(index):
|
||
|
match index:
|
||
|
GOTO_ITEM_INDEX:
|
||
|
go_to_title(current_goto_title)
|
||
|
|
||
|
CREATE_ITEM_INDEX:
|
||
|
create_title(current_goto_title)
|
||
|
|
||
|
PICK_ITEM_INDEX:
|
||
|
choose_title_dialog.choose_a_title(get_titles())
|
||
|
|
||
|
|
||
|
func _on_title_chosen(title):
|
||
|
var cursor_line = cursor_get_line()
|
||
|
var line: String = get_line(cursor_line)
|
||
|
line = line.substr(0, line.find("=> ") + 2)
|
||
|
|
||
|
set_line(cursor_line, line + " " + title)
|
||
|
current_goto_title = title
|
||
|
|
||
|
cursor_set_line(cursor_line)
|
||
|
|
||
|
|
||
|
func _on_CodeEditor_cursor_changed():
|
||
|
check_active_title()
|
||
|
update_current_goto_title()
|
||
|
|
||
|
last_selection_text = get_selection_text()
|
||
|
|
||
|
|
||
|
func _on_CodeEditor_text_changed():
|
||
|
check_active_title()
|
||
|
update_current_goto_title()
|