diff --git a/addons/Wol/editor/Editor.gd b/addons/Wol/editor/Editor.gd index 5e6a149..0e7a2e3 100644 --- a/addons/Wol/editor/Editor.gd +++ b/addons/Wol/editor/Editor.gd @@ -1,9 +1,12 @@ tool extends Panel +signal closed + var current_graph_node onready var preview = get_node('../Preview') +onready var help = get_node('../Help') onready var wol_editor = find_parent('WolEditor') func _ready(): @@ -23,6 +26,9 @@ func _ready(): func close(): hide() preview.close() + help.close() + + emit_signal('closed') func open_node(graph_node): current_graph_node = graph_node @@ -40,6 +46,7 @@ func open_node(graph_node): show() grab_focus() + text_edit.grab_focus() func toggle_text_edit(text_edit): text_edit.anchor_left = 0 @@ -51,6 +58,7 @@ func toggle_text_edit(text_edit): text_edit.margin_bottom = 0 text_edit.margin_top = 0 text_edit.mouse_filter = MOUSE_FILTER_STOP if text_edit.get_parent().name == 'Content' else MOUSE_FILTER_IGNORE + text_edit.focus_mode = FOCUS_ALL if text_edit.get_parent().name == 'Content' else FOCUS_NONE text_edit.deselect() @@ -72,7 +80,6 @@ func _on_delete_pressed(): func _on_title_changed(text): current_graph_node.node.title = text.replace(' ', '') - prints('title', text) current_graph_node.compile() func _on_visibility_changed(): @@ -86,3 +93,13 @@ func _on_gui_input(event): if event is InputEventKey \ and event.pressed and event.scancode == KEY_ESCAPE: close() + + if event is InputEventKey: + var combination = OS.get_scancode_string(event.get_physical_scancode_with_modifiers()) + + if OS.get_name() == 'OSX': + combination = combination.replace('Command', 'Control') + + match combination: + 'Control+P': + preview.open_node(current_graph_node) diff --git a/addons/Wol/editor/Help.gd b/addons/Wol/editor/Help.gd new file mode 100644 index 0000000..11d2a08 --- /dev/null +++ b/addons/Wol/editor/Help.gd @@ -0,0 +1,16 @@ +extends Panel + +onready var editor = get_node('../Editor') + +func _ready(): + $Tools/Right/Close.connect('pressed', self, 'close') + connect('gui_input', self, '_on_gui_input') + +func close(): + hide() + +func _on_gui_input(event): + if event is InputEventKey \ + and event.pressed and event.scancode == KEY_ESCAPE: + close() + editor.grab_focus() diff --git a/addons/Wol/editor/Preview.gd b/addons/Wol/editor/Preview.gd index 38a3aab..c76a5cb 100644 --- a/addons/Wol/editor/Preview.gd +++ b/addons/Wol/editor/Preview.gd @@ -13,6 +13,8 @@ func _ready(): hide() $Wol.connect('line', self, '_on_line') $Wol.connect('options', self, '_on_options') + $Wol.connect('command', self, '_on_command') + $Wol.connect('finished', self, '_on_finished') connect('gui_input', self, '_on_gui_input') @@ -56,7 +58,7 @@ func clear_chat(): $Options/List.remove_child(child) child.queue_free() - +# TODO: Implement default protagonist setting func guess_protagonist(): var protagonist = 'You' var wol_node = wol_editor.get_program().nodes[current_graph_node.node.title] @@ -89,33 +91,60 @@ func restart(): $Wol.stop() yield(get_tree(), 'idle_frame') - clear_chat() - yield(get_tree(), 'idle_frame') + add_message('Restarting dialogue...') $Wol.start(current_graph_node.node.title) -func _on_line(line): +func add_message(text, align = 'system', color = Color(0, 0, 0, 0)): var line_node = line_template.duplicate() $Content/List.add_child(line_node) $Content/List/PaddingBottom.raise() - # TODO: Add hash() based color from speaker - line_node.get_node('RichTextLabel').bbcode_text = line.text + match align: + 'left': + line_node.get_node('PaddingRight').size_flags_horizontal = SIZE_EXPAND_FILL + 'right': + line_node.get_node('PaddingLeft').size_flags_horizontal = SIZE_EXPAND_FILL + 'center': + line_node.get_node('PaddingRight').size_flags_horizontal = SIZE_EXPAND_FILL + line_node.get_node('PaddingLeft').size_flags_horizontal = SIZE_EXPAND_FILL + 'system': + line_node.get_node('PaddingRight').size_flags_horizontal = SIZE_FILL + line_node.get_node('PaddingLeft').size_flags_horizontal = SIZE_FILL + text = '[color=gray][center][i]%s[/i][/center][/color]' % text + + line_node.get_node('RichTextLabel').bbcode_text = text - var padding_node = 'PaddingRight' if get_protagonist(line) == $Tools/Left/Protagonist.text else 'PaddingLeft' - line_node.get_node(padding_node).size_flags_horizontal = SIZE_EXPAND_FILL - var panel = line_node.get_node('RichTextLabel/Panel').get('custom_styles/panel').duplicate() - panel.bg_color = Color(hash(get_protagonist(line))) + var panel = line_node.get_node('RichTextLabel/Panel') \ + .get('custom_styles/panel') \ + .duplicate() + + panel.bg_color = color line_node.get_node('RichTextLabel/Panel').set('custom_styles/panel', panel) - line_node.show() yield(get_tree(), 'idle_frame') $Content.scroll_vertical = $Content/List.rect_size.y +func _on_line(line): + var align = 'left' if get_protagonist(line) == $Tools/Left/Protagonist.text else 'right' + var color + if get_protagonist(line): + color = Color(hash(get_protagonist(line))) + else: + color = Color.darkgray + + add_message(line.text, align, color) + +func _on_command(command): + add_message('Executed command "%s"' % command.command) + $Wol.resume() + func _on_options(options): + add_message('Being shown %d options' % options.size()) + for option in options: var button = button_template.duplicate() $Options/List.add_child(button) @@ -125,6 +154,7 @@ func _on_options(options): button.show() func _on_option_pressed(option): + add_message('Selected option "%s"' % option.line.text) $Wol.select_option(option.id) for child in $Options/List.get_children(): @@ -134,6 +164,9 @@ func _on_option_pressed(option): grab_focus() +func _on_finished(): + add_message('Dialogue stopped.') + func _on_gui_input(event): if visible: if event is InputEventMouseButton and event.doubleclick: diff --git a/addons/Wol/editor/WolEditor.gd b/addons/Wol/editor/WolEditor.gd index aef0a43..904d3c9 100644 --- a/addons/Wol/editor/WolEditor.gd +++ b/addons/Wol/editor/WolEditor.gd @@ -5,19 +5,18 @@ const Compiler = preload('res://addons/Wol/core/compiler/Compiler.gd') onready var GraphNodeTemplate = $GraphNodeTemplate var path -var selected_node var saved_all_changes = false +var last_save var mouse_panning = false +var focus_pan = Vector2.ZERO onready var original_delete_node_dialog = $DeleteNodeDialog.dialog_text +onready var original_unsaved_dialog = $UnsavedDialog.dialog_text onready var inside_godot_editor = not get_tree().current_scene and Engine.editor_hint # Standalone -# TODO: Add confirm window for creating new file if working on another -# TODO: Make arrow keys / WASD select next node -# TODO: Make ENTER key open a editor -# TODO: Add comprehensive Help in a dialog -# TODO: Add scrolling ability to a node when focussing a node +# TODO: Make arrow keys select options in preview +# FIXME: Fix focus issues while being in-editor # Godot Editor # FIXME: Make all parts of the code "tool"s and safekeep its execution while in editora @@ -32,8 +31,7 @@ onready var inside_godot_editor = not get_tree().current_scene and Engine.editor # TODO: Try to replicate positioning from existing Yarn Editor # TODO: Implement settings # TODO: Add more settings (like custom theme) -# TODO: Make shortcut for opening preview (CMD+P) -# TODO: More messages in preview for different things (command, start, stop, choices, log) +# TODO: Add HSplits instead of HBoxContainer in the editor func _ready(): for menu_button in [$Menu/File]: @@ -42,17 +40,33 @@ func _ready(): $Menu/Settings.connect('pressed', self, 'show_settings') $Menu/About.connect('pressed', self, 'show_about') $Menu/Help.connect('pressed', self, 'show_help') + $Menu/AuthorNotice.connect('pressed', self, '_on_url_clicked', ['https://twitter.com/bram_dingelstad']) $GraphEdit.connect('gui_input', self, '_on_graph_edit_input') $GraphEdit.connect('node_selected', self, '_on_node_selected', [true]) $GraphEdit.connect('node_unselected', self, '_on_node_selected', [false]) $GraphEdit.connect('_end_node_move', self, 'reconnect_nodes') - $DeleteNodeDialog.connect('confirmed', self, 'delete_node') - $HelpDialog/HSplitContainer/Right.connect('meta_clicked', self, '_on_url_clicked') + $HBoxContainer/Editor.connect('closed', self, '_on_editor_closed') - path = 'res://dialogue.wol' - build_nodes() + $DeleteNodeDialog.connect('confirmed', self, 'delete_node') + $HelpDialog/HelpSplit/Right.connect('meta_clicked', self, '_on_url_clicked') + + $UnsavedDialog.add_button('Cancel', false, 'cancel') + $UnsavedDialog.add_button('Don\'t Save', false, 'dont_save') + $UnsavedDialog.add_button('Save & Close', true, 'save_and_close') + $UnsavedDialog.get_cancel().hide() + $UnsavedDialog.get_ok().hide() + + $GraphEdit.get_zoom_hbox().anchor_right = 1 + $GraphEdit.get_zoom_hbox().anchor_left = 1 + $GraphEdit.get_zoom_hbox().anchor_bottom = 0 + $GraphEdit.get_zoom_hbox().anchor_top = 0 + $GraphEdit.get_zoom_hbox().margin_left = -$GraphEdit.get_zoom_hbox().rect_size.x - 18 + + var line_edit_density = $GraphEdit.get_zoom_hbox().get_node('@@24/@@22') + if line_edit_density is LineEdit: + line_edit_density.focus_mode = FOCUS_CLICK if inside_godot_editor: theme = null @@ -62,13 +76,16 @@ func _ready(): $HBoxContainer.set('custom_constants/seperation', 0) + open('res://dialogue.wol') + + func create_node(position = Vector2.ZERO): var graph_node = GraphNodeTemplate.duplicate() $GraphEdit.add_child(graph_node) var node = { 'title': 'NewNode', - 'body': 'Wol: Hello world', + 'body': 'Here begins your new adventure!', 'position': position } @@ -78,17 +95,38 @@ func create_node(position = Vector2.ZERO): graph_node.node = node graph_node.show() -func delete_node(node = selected_node): +func delete_node(node = get_selected_graph_node()): if $HBoxContainer/Editor.visible: $HBoxContainer/Editor.close() $GraphEdit.remove_child(node) node.queue_free() + reconnect_nodes() -func confirm_delete_node(node = selected_node): - selected_node = node - $DeleteNodeDialog.dialog_text = original_delete_node_dialog % selected_node.name +func confirm_delete_node(node = get_selected_graph_node()): + $DeleteNodeDialog.dialog_text = original_delete_node_dialog % node.name $DeleteNodeDialog.popup() +func center_node_on_screen(node): + var start = $GraphEdit.scroll_offset + var zoom = $GraphEdit.zoom + + # FIXME : Calculate it manually rather than weird hack + $GraphEdit.zoom = 1 + $GraphEdit.scroll_offset = node.center - ($GraphEdit.rect_size / 2) + $GraphEdit.zoom = zoom + + $Tween.interpolate_property( + $GraphEdit, + 'scroll_offset', + start, + $GraphEdit.scroll_offset, + .5, + $Tween.TRANS_QUART, + $Tween.EASE_OUT + ) + + $Tween.start() + func build_nodes(): for node in Compiler.new(path).get_nodes(): var graph_node = GraphNodeTemplate.duplicate() @@ -100,6 +138,8 @@ func build_nodes(): graph_node.node = node graph_node.show() + last_save = serialize_to_file() + func get_program(): return Compiler.new(null, serialize_to_file(), true).compile() @@ -135,13 +175,20 @@ func save_as(file_path = null): file.store_string(serialize_to_file()) file.close() -func open(): - $FileDialog.mode = $FileDialog.MODE_OPEN_FILE - # TODO: Set up path based on context (Godot editor, standalone or web) - $FileDialog.popup_centered() - path = yield($FileDialog, 'file_selected') - if not path: - return + saved_all_changes = true + last_save = serialize_to_file() + update_title() + +func open(file_path = ''): + if file_path.empty(): + $FileDialog.mode = $FileDialog.MODE_OPEN_FILE + # TODO: Set up path based on context (Godot editor, standalone or web) + $FileDialog.popup_centered() + path = yield($FileDialog, 'file_selected') + if not path: + return + else: + path = file_path for node in $GraphEdit.get_children(): if node is GraphNode: @@ -152,14 +199,29 @@ func open(): build_nodes() func new(): - # TODO: add dialog for maybe saving existing file - + if not saved_all_changes: + $UnsavedDialog.popup() + $UnsavedDialog.dialog_text = original_unsaved_dialog % path + + var result = yield($UnsavedDialog, 'custom_action') + $UnsavedDialog.hide() + match result: + 'save_and_close': + save_as(path) + 'cancel': + return + 'dont_save': + pass # Continue normal execution + for node in $GraphEdit.get_children(): if node is GraphNode: $GraphEdit.remove_child(node) node.queue_free() path = null + last_save = null + reconnect_nodes() + update_title() func show_settings(): $SettingsDialog.popup() @@ -168,24 +230,18 @@ func show_about(): $AboutDialog.popup() func show_help(): - $HelpDialog.popup() + var help = find_node('HelpSplit') + help.get_parent().remove_child(help) -func _on_url_clicked(url): - OS.shell_open(url) - -func _on_menu_pressed(index, node): - match node.get_item_text(index): - 'New': - new() - 'Save': - save_as(path) - 'Save as...': - save_as() - 'Open': - open() + if $HBoxContainer/Editor.visible: + $HBoxContainer/Help/Content.add_child(help) + $HBoxContainer/Help.show() + $HBoxContainer/Help.grab_focus() + else: + $HelpDialog.add_child(help) + $HelpDialog.popup() -func _on_graph_node_recompiled(_graph_node): - reconnect_nodes() + help.set_owner(get_tree().current_scene) func reconnect_nodes(): $GraphEdit.clear_connections() @@ -196,6 +252,15 @@ func reconnect_nodes(): else: connect_nodes_godot_style() + # NOTE: This gets executed a lot on changes, so check if there are any changes + saved_all_changes = last_save and last_save == serialize_to_file() + update_title() + +func update_title(): + var filename = 'Unnamed file' if not path else path.get_file() + var unsaved = '' if saved_all_changes else '*' + OS.set_window_title('%s%s - Wol Editor' % [filename, unsaved]) + func connect_nodes_single_style(): for graph_node in $GraphEdit.get_children(): if not graph_node is GraphNode: @@ -253,40 +318,74 @@ func connect_nodes_godot_style(): $GraphEdit.connect_node(graph_node.name, 0, connection, 0) -func move_focus(event): +func get_selected_graph_node(): var current_focussed - var first_node for node in $GraphEdit.get_children(): if node is GraphNode: - if not first_node: - first_node = node if node.selected: current_focussed = node + return current_focussed + +func move_focus(): + var current_focussed = get_selected_graph_node() + var nodes = [] + for node in $GraphEdit.get_children(): + if node is GraphNode: + nodes.append(node) + + # FIXME: Make this based on current offset if not current_focussed: - current_focussed = first_node + current_focussed = nodes.back() + $GraphEdit.set_selected(current_focussed) + current_focussed.grab_focus() + center_node_on_screen(current_focussed) + return - var vector = Vector2.RIGHT - match event.scancode: - KEY_D, KEY_RIGHT: - pass # Defaults to right + var closest + for node in nodes: + if node == current_focussed: + continue - KEY_A, KEY_LEFT: - vector = vector.rotated(PI) + if not closest or \ + closest.center.distance_to(current_focussed.center + focus_pan) \ + > node.center.distance_to(current_focussed.center + focus_pan): + closest = node + $GraphEdit.set_selected(closest) + closest.grab_focus() + + focus_pan = null + +func _on_editor_closed(): + get_selected_graph_node().grab_focus() + +func _on_url_clicked(url): + OS.shell_open(url) + +func _on_menu_pressed(index, node): + match node.get_item_text(index): + 'New': + new() + 'Save': + save_as(path) + 'Save as...': + save_as() + 'Open': + open() + +func _on_graph_node_recompiled(_graph_node): + reconnect_nodes() func _on_graph_node_input(event, graph_node): - if event is InputEventMouseButton \ - and event.doubleclick and event.button_index == BUTTON_LEFT: + var double_clicked = event is InputEventMouseButton \ + and event.doubleclick and event.button_index == BUTTON_LEFT + + + if double_clicked: $HBoxContainer/Editor.open_node(graph_node) accept_event() -func _on_node_selected(node, selected): - if not selected: - selected_node = null - else: - selected_node = node - func _on_graph_edit_input(event): if event is InputEventMouseButton \ and event.doubleclick and event.button_index == BUTTON_LEFT: @@ -298,9 +397,7 @@ func _on_graph_edit_input(event): if event is InputEventMouseMotion and mouse_panning: $GraphEdit.scroll_offset -= event.relative - - if event is InputEventKey and not event.pressed: - move_focus(event) + func _input(event): if not visible: @@ -308,10 +405,21 @@ func _input(event): if event is InputEventKey \ and not event.pressed and event.physical_scancode == KEY_DELETE \ - and selected_node \ + and get_selected_graph_node() \ and not $HBoxContainer/Editor.visible: confirm_delete_node() + var selected_node = get_selected_graph_node() + if selected_node and selected_node.has_focus() and event is InputEventKey \ + and not event.pressed and event.scancode == KEY_ENTER: + $HBoxContainer/Editor.open_node(selected_node) + accept_event() + + if selected_node and event is InputEventKey \ + and not event.pressed and event.scancode == KEY_F: + center_node_on_screen(selected_node) + + if event is InputEventKey: var combination = OS.get_scancode_string(event.get_physical_scancode_with_modifiers()) @@ -320,11 +428,15 @@ func _input(event): match combination: 'Control+N': - new() + return new() 'Control+S': - save_as(path) + return save_as(path) 'Shift+Control+S': - save_as() + return save_as() 'Control+O': - open() + return open() + if event.pressed: + focus_pan = Input.get_vector('ui_left', 'ui_right', 'ui_up', 'ui_down') * 500 + elif focus_pan: + move_focus() diff --git a/addons/Wol/editor/WolEditor.tscn b/addons/Wol/editor/WolEditor.tscn index 349c65a..7004649 100644 --- a/addons/Wol/editor/WolEditor.tscn +++ b/addons/Wol/editor/WolEditor.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=24 format=2] +[gd_scene load_steps=25 format=2] [ext_resource path="res://addons/Wol/editor/Editor.gd" type="Script" id=1] [ext_resource path="res://addons/Wol/editor/WolEditor.gd" type="Script" id=2] @@ -16,6 +16,7 @@ [ext_resource path="res://addons/Wol/font/VictorMono-Light.otf" type="DynamicFontData" id=14] [ext_resource path="res://addons/Wol/font/Aileron-SemiBoldItalic.otf" type="DynamicFontData" id=15] [ext_resource path="res://addons/Wol/font/Aileron-Italic.otf" type="DynamicFontData" id=16] +[ext_resource path="res://addons/Wol/editor/Help.gd" type="Script" id=17] [sub_resource type="StyleBoxEmpty" id=2] @@ -67,6 +68,8 @@ __meta__ = { "_edit_use_anchors_": false } +[node name="Tween" type="Tween" parent="."] + [node name="Menu" type="HBoxContainer" parent="."] anchor_right = 1.0 rect_min_size = Vector2( 0, 32 ) @@ -108,12 +111,31 @@ enabled_focus_mode = 0 text = "About" flat = true +[node name="AuthorNotice" type="Button" parent="Menu"] +modulate = Color( 1, 1, 1, 0.466667 ) +margin_left = 846.0 +margin_right = 1016.0 +margin_bottom = 32.0 +focus_mode = 0 +size_flags_horizontal = 10 +text = "By @bram_dingelstad" +flat = true + +[node name="Padding" type="Control" parent="Menu"] +margin_left = 1024.0 +margin_right = 1024.0 +margin_bottom = 32.0 +__meta__ = { +"_edit_use_anchors_": false +} + [node name="GraphNodeTemplate" type="GraphNode" parent="."] visible = false margin_left = 2.0 margin_top = 318.0 margin_right = 322.0 margin_bottom = 575.0 +focus_mode = 1 mouse_filter = 1 title = "Hello world" offset = Vector2( 120, 0 ) @@ -141,6 +163,7 @@ size_flags_vertical = 3 [node name="TextEdit" type="TextEdit" parent="GraphNodeTemplate/Wrapper"] anchor_right = 1.0 anchor_bottom = 1.0 +focus_mode = 0 mouse_filter = 2 size_flags_horizontal = 3 size_flags_vertical = 3 @@ -193,6 +216,7 @@ anchor_right = 1.0 anchor_bottom = 1.0 margin_top = 32.0 custom_styles/bg = SubResource( 2 ) +scroll_offset = Vector2( 0, -511 ) snap_distance = 100 show_zoom_label = true __meta__ = { @@ -203,9 +227,9 @@ __meta__ = { anchor_top = 0.053 anchor_right = 1.0 anchor_bottom = 1.0 -margin_top = 0.199999 +margin_top = 0.200001 mouse_filter = 2 -custom_constants/separation = 32 +custom_constants/separation = 0 alignment = 1 __meta__ = { "_edit_use_anchors_": false @@ -213,10 +237,8 @@ __meta__ = { [node name="Preview" type="Panel" parent="HBoxContainer"] visible = false -margin_left = 352.0 -margin_right = 672.0 +margin_right = 1024.0 margin_bottom = 568.0 -rect_min_size = Vector2( 320, 0 ) focus_mode = 1 size_flags_horizontal = 3 script = ExtResource( 4 ) @@ -240,7 +262,7 @@ __meta__ = { } [node name="Left" type="HBoxContainer" parent="HBoxContainer/Preview/Tools"] -margin_right = 280.0 +margin_right = 504.0 margin_bottom = 26.0 size_flags_horizontal = 3 size_flags_vertical = 3 @@ -252,15 +274,15 @@ margin_bottom = 23.0 text = "Protagonist: " [node name="Protagonist" type="LineEdit" parent="HBoxContainer/Preview/Tools/Left"] -margin_left = 93.0 -margin_right = 165.0 +margin_left = 97.0 +margin_right = 169.0 margin_bottom = 26.0 rect_min_size = Vector2( 72, 0 ) script = ExtResource( 8 ) [node name="Next" type="Button" parent="HBoxContainer/Preview/Tools/Left"] -margin_left = 169.0 -margin_right = 214.0 +margin_left = 177.0 +margin_right = 222.0 margin_bottom = 26.0 focus_mode = 0 enabled_focus_mode = 0 @@ -270,8 +292,8 @@ __meta__ = { } [node name="Restart" type="Button" parent="HBoxContainer/Preview/Tools/Left"] -margin_left = 218.0 -margin_right = 280.0 +margin_left = 230.0 +margin_right = 292.0 margin_bottom = 26.0 focus_mode = 0 enabled_focus_mode = 0 @@ -281,8 +303,8 @@ __meta__ = { } [node name="Right" type="HBoxContainer" parent="HBoxContainer/Preview/Tools"] -margin_left = 284.0 -margin_right = 312.0 +margin_left = 512.0 +margin_right = 1016.0 margin_bottom = 26.0 size_flags_horizontal = 3 size_flags_vertical = 3 @@ -292,8 +314,8 @@ __meta__ = { } [node name="Close" type="Button" parent="HBoxContainer/Preview/Tools/Right"] -margin_left = 4.0 -margin_right = 28.0 +margin_left = 480.0 +margin_right = 504.0 margin_bottom = 26.0 rect_min_size = Vector2( 24, 0 ) text = "x" @@ -315,7 +337,7 @@ __meta__ = { } [node name="List" type="VBoxContainer" parent="HBoxContainer/Preview/Content"] -margin_right = 320.0 +margin_right = 1024.0 margin_bottom = 419.0 mouse_filter = 2 size_flags_horizontal = 3 @@ -326,30 +348,31 @@ __meta__ = { } [node name="PaddingTop" type="Control" parent="HBoxContainer/Preview/Content/List"] -margin_right = 320.0 +margin_right = 1024.0 mouse_filter = 2 [node name="LineTemplate" type="HBoxContainer" parent="HBoxContainer/Preview/Content/List"] visible = false margin_top = 18.0 -margin_right = 320.0 -margin_bottom = 33.0 +margin_right = 1024.0 +margin_bottom = 40.0 mouse_filter = 2 alignment = 1 [node name="PaddingLeft" type="Control" parent="HBoxContainer/Preview/Content/List/LineTemplate"] margin_right = 16.0 -margin_bottom = 15.0 +margin_bottom = 22.0 rect_min_size = Vector2( 16, 0 ) mouse_filter = 2 [node name="RichTextLabel" type="RichTextLabel" parent="HBoxContainer/Preview/Content/List/LineTemplate"] -margin_left = 20.0 -margin_right = 300.0 -margin_bottom = 15.0 +margin_left = 24.0 +margin_right = 1000.0 +margin_bottom = 22.0 rect_clip_content = false mouse_filter = 2 size_flags_horizontal = 3 +size_flags_stretch_ratio = 2.0 bbcode_enabled = true bbcode_text = "Hello world" text = "Hello world" @@ -370,15 +393,15 @@ __meta__ = { } [node name="PaddingRight" type="Control" parent="HBoxContainer/Preview/Content/List/LineTemplate"] -margin_left = 304.0 -margin_right = 320.0 -margin_bottom = 15.0 +margin_left = 1008.0 +margin_right = 1024.0 +margin_bottom = 22.0 rect_min_size = Vector2( 16, 0 ) mouse_filter = 2 [node name="PaddingBottom" type="Control" parent="HBoxContainer/Preview/Content/List"] margin_top = 18.0 -margin_right = 320.0 +margin_right = 1024.0 margin_bottom = 18.0 mouse_filter = 2 @@ -400,7 +423,7 @@ __meta__ = { } [node name="List" type="VBoxContainer" parent="HBoxContainer/Preview/Options"] -margin_right = 288.0 +margin_right = 992.0 margin_bottom = 97.08 mouse_filter = 2 size_flags_horizontal = 3 @@ -418,13 +441,13 @@ text = "Option" [node name="Editor" type="Panel" parent="HBoxContainer"] visible = false -margin_left = 368.0 -margin_right = 1008.0 +margin_left = 362.0 +margin_right = 1024.0 margin_bottom = 568.0 -rect_min_size = Vector2( 640, 0 ) focus_mode = 1 mouse_filter = 1 size_flags_horizontal = 3 +size_flags_stretch_ratio = 2.0 script = ExtResource( 1 ) __meta__ = { "_edit_use_anchors_": false @@ -441,7 +464,7 @@ __meta__ = { } [node name="Left" type="HBoxContainer" parent="HBoxContainer/Editor/Tools"] -margin_right = 314.0 +margin_right = 323.0 margin_bottom = 26.0 size_flags_horizontal = 3 size_flags_vertical = 3 @@ -454,16 +477,16 @@ script = ExtResource( 8 ) disable_spaces = true [node name="Play" type="Button" parent="HBoxContainer/Editor/Tools/Left"] -margin_left = 148.0 -margin_right = 191.0 +margin_left = 152.0 +margin_right = 195.0 margin_bottom = 26.0 focus_mode = 0 enabled_focus_mode = 0 text = "Play" [node name="Right" type="HBoxContainer" parent="HBoxContainer/Editor/Tools"] -margin_left = 318.0 -margin_right = 632.0 +margin_left = 331.0 +margin_right = 654.0 margin_bottom = 26.0 size_flags_horizontal = 3 size_flags_vertical = 3 @@ -473,20 +496,20 @@ __meta__ = { } [node name="Delete" type="Button" parent="HBoxContainer/Editor/Tools/Right"] -margin_left = 199.0 -margin_right = 258.0 +margin_left = 200.0 +margin_right = 259.0 margin_bottom = 26.0 text = "Delete" [node name="Control" type="Control" parent="HBoxContainer/Editor/Tools/Right"] -margin_left = 262.0 -margin_right = 286.0 +margin_left = 267.0 +margin_right = 291.0 margin_bottom = 26.0 rect_min_size = Vector2( 24, 0 ) [node name="Close" type="Button" parent="HBoxContainer/Editor/Tools/Right"] -margin_left = 290.0 -margin_right = 314.0 +margin_left = 299.0 +margin_right = 323.0 margin_bottom = 26.0 rect_min_size = Vector2( 24, 0 ) text = "x" @@ -503,6 +526,59 @@ __meta__ = { "_edit_use_anchors_": false } +[node name="Help" type="Panel" parent="HBoxContainer"] +visible = false +margin_left = 784.0 +margin_right = 1024.0 +margin_bottom = 568.0 +focus_mode = 1 +mouse_filter = 1 +size_flags_horizontal = 3 +script = ExtResource( 17 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Content" type="Control" parent="HBoxContainer/Help"] +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_top = 42.0 +mouse_filter = 2 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Tools" type="HBoxContainer" parent="HBoxContainer/Help"] +anchor_right = 1.0 +margin_left = 4.0 +margin_top = 4.0 +margin_right = -4.0 +margin_bottom = 27.8 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Right" type="HBoxContainer" parent="HBoxContainer/Help/Tools"] +margin_left = 331.0 +margin_right = 654.0 +margin_bottom = 26.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +alignment = 2 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Close" type="Button" parent="HBoxContainer/Help/Tools/Right"] +margin_left = 299.0 +margin_right = 323.0 +margin_bottom = 26.0 +rect_min_size = Vector2( 24, 0 ) +text = "x" +__meta__ = { +"_edit_use_anchors_": false +} + [node name="FileDialog" type="FileDialog" parent="."] anchor_left = 0.5 anchor_top = 0.5 @@ -536,6 +612,22 @@ __meta__ = { "_edit_use_anchors_": false } +[node name="UnsavedDialog" type="ConfirmationDialog" parent="."] +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = -223.0 +margin_top = -70.0 +margin_right = 223.0 +margin_bottom = 70.0 +rect_min_size = Vector2( 400, 140 ) +popup_exclusive = true +dialog_text = "Save changes to \"%s\" before closing?" +__meta__ = { +"_edit_use_anchors_": false +} + [node name="AboutDialog" type="WindowDialog" parent="."] anchor_left = 0.5 anchor_top = 0.5 @@ -591,7 +683,6 @@ align = 1 valign = 1 [node name="HelpDialog" type="WindowDialog" parent="."] -visible = true anchor_left = 0.5 anchor_top = 0.5 anchor_right = 0.5 @@ -608,15 +699,16 @@ __meta__ = { "_edit_use_anchors_": false } -[node name="HSplitContainer" type="HSplitContainer" parent="HelpDialog"] +[node name="HelpSplit" type="HSplitContainer" parent="HelpDialog"] anchor_right = 1.0 anchor_bottom = 1.0 margin_left = 16.0 margin_top = 16.0 margin_right = -16.0 margin_bottom = -16.0 +mouse_filter = 1 -[node name="Left" type="RichTextLabel" parent="HelpDialog/HSplitContainer"] +[node name="Left" type="RichTextLabel" parent="HelpDialog/HelpSplit"] margin_right = 231.0 margin_bottom = 283.0 rect_pivot_offset = Vector2( -370.24, 130.838 ) @@ -691,7 +783,7 @@ __meta__ = { "_edit_use_anchors_": false } -[node name="Right" type="RichTextLabel" parent="HelpDialog/HSplitContainer"] +[node name="Right" type="RichTextLabel" parent="HelpDialog/HelpSplit"] margin_left = 255.0 margin_right = 486.0 margin_bottom = 283.0 diff --git a/addons/Wol/editor/WolGraphNode.gd b/addons/Wol/editor/WolGraphNode.gd index 0ea1b1b..4e384d7 100644 --- a/addons/Wol/editor/WolGraphNode.gd +++ b/addons/Wol/editor/WolGraphNode.gd @@ -11,8 +11,10 @@ var node setget set_node var error_lines = [] var compiler var program +var center = Vector2.ZERO onready var text_edit = $Wrapper/TextEdit +onready var graph_edit = find_parent('GraphEdit') # TODO: Add syntax highlighting @@ -21,6 +23,8 @@ func _ready(): text_edit.connect('text_changed', self, '_on_text_changed') $TextDebounce.connect('timeout', self, '_on_debounce') + center = offset + rect_size / 2 + func get_connections(): # NOTE: Program failed to compile if not program: @@ -29,10 +33,6 @@ func get_connections(): var program_node = program.nodes.values().front() var connections = [] - # FIXME: Don't rely on checking on 'Label\d' - var label_check = RegEx.new() - label_check.compile('^Label\\doption_\\d') - for instruction in program_node.instructions: # NOTE: When next node is explicit if instruction.operation == Constants.ByteCode.RunNode: @@ -43,12 +43,21 @@ func get_connections(): # NOTE: When next node is decided through options if instruction.operation == Constants.ByteCode.AddOption: if instruction.operands.size() == 2 \ - and not label_check.search(instruction.operands[1].value) \ + and graph_edit.has_node(instruction.operands[1].value.replace('.', '_')) \ and instruction.operands[1].value != name: connections.append(instruction.operands[1].value.replace('.', '_')) return connections +func compile(): + var text = 'title: %s\n---\n%s\n===' % [node.title, text_edit.text] + compiler = Compiler.new(null, text, true) + compiler.connect('error', self, '_on_error') + program = compiler.compile() + + yield(get_tree(), 'idle_frame') + emit_signal('recompiled') + func _on_text_changed(): $TextDebounce.start() @@ -61,6 +70,7 @@ func _on_debounce(): func _on_offset_changed(): node.position = offset + center = offset + rect_size / 2 func _on_error(message, line_number, _column): var error_gutter = text_edit.get_node('ErrorGutter') @@ -80,12 +90,3 @@ func set_node(_node): offset = node.position compile() - -func compile(): - var text = 'title: %s\n---\n%s\n===' % [node.title, text_edit.text] - compiler = Compiler.new(null, text, true) - compiler.connect('error', self, '_on_error') - program = compiler.compile() - - yield(get_tree(), 'idle_frame') - emit_signal('recompiled') diff --git a/dialogue.wol b/dialogue.wol index 14b8fa1..7793c6d 100644 --- a/dialogue.wol +++ b/dialogue.wol @@ -47,6 +47,7 @@ Guy: Hey what's up I need your help can you come here? You: Well I can't I'm buying clothes. Guy: All right well hurry up and come over here. You: I can't find them. +test Guy: What do you mean you can't find them? You: I can't find them there's only soup. Guy: What do you mean there's only soup?! diff --git a/project.godot b/project.godot index 54abb15..ac2c9e7 100644 --- a/project.godot +++ b/project.godot @@ -19,6 +19,7 @@ Yarn's similar in style to Twine, so if you already know that, you'll be right a Wol is actively maintained by Bram Dingelstad, if you need a programmer or designer for your next (Godot) project, you can hire him!" run/main_scene="res://addons/Wol/editor/WolEditor.tscn" +run/low_processor_mode=true config/icon="res://addons/Wol/icon-white-with-stroke.svg" [debug] @@ -43,6 +44,37 @@ enabled=PoolStringArray( "res://addons/Wol/plugin.cfg" ) theme/use_hidpi=true +[input] + +ui_left={ +"deadzone": 0.5, +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777231,"physical_scancode":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":14,"pressure":0.0,"pressed":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":0,"physical_scancode":65,"unicode":0,"echo":false,"script":null) + ] +} +ui_right={ +"deadzone": 0.5, +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777233,"physical_scancode":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":15,"pressure":0.0,"pressed":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":0,"physical_scancode":68,"unicode":0,"echo":false,"script":null) + ] +} +ui_up={ +"deadzone": 0.5, +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777232,"physical_scancode":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":12,"pressure":0.0,"pressed":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":0,"physical_scancode":87,"unicode":0,"echo":false,"script":null) + ] +} +ui_down={ +"deadzone": 0.5, +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777234,"physical_scancode":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":13,"pressure":0.0,"pressed":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":0,"physical_scancode":83,"unicode":0,"echo":false,"script":null) + ] +} + [network] limits/debugger_stdout/max_chars_per_second=32384