From 999df4feef941814cd64a85c8263584983b0bb08 Mon Sep 17 00:00:00 2001 From: FrobozzWaxwing Date: Mon, 27 Mar 2023 17:11:23 -0500 Subject: [PATCH] Update to version 0.0.38 Disabled IFID reset option. (I had intended to disable this before the previous version, but forgot.) Changed how spool list is saved, such that order of spools is saved while maintaining ability to merge json files together. Changed overview table to alternate between two different colors each row. Added edit button to playscreen so that an encounter reached during playtesting can be loaded more quickly and easily. Deleted antagonist-selection menu from encounter editor scene. (It had been invisible, but now I've simply removed it completely.) Implemented greatly improved interface for drag-and-drop lists that have built in context menus. The lists for options, reactions, and effects now all use this interface. Different context menus are shown depending on whether the author right-clicked on an item or in the empty space of the list. Set compiler to remove console.log calls from interpreter when exporting storyworld in release mode. Exporting in debug mode will leave them in. Changed interpreter to use customized popup dialog in place of window confirm calls. Also fixed some bugs involving saving and loading games. First, characters were not being saved and reloaded properly, and second, saving a game when "the end" screen had been reached, then reloading, was loading the most recent encounter instead of the end. Both issues should now be solved. Removed saved game journal entry feature in interpreter. Removed some unused code from interpreter. The editor had a bug that caused a storyworld's modified_time to be updated upon loading it from a project file. Loading numerical values, such as earliest and latest turns, into spinboxes activates the "value_changed" signal. This can be fixed fully upon porting SweepWeave to Godot 4, as Godot 4 has new functions that one can call to set range interface values without triggering their value_changed signals, but in the meantime the interface elements for changing an encounter's earliest and latest turns have simply been deleted. I'm not sure if the bug can still occur under some circumstances, but I can worry about porting SweepWeave to Godot 4 another time. Added new option to help menu to let authors check for updates to SweepWeave. Updated gui theming for popup windows. Popup windows will now be centered upon popup. Changed default relationship model to use depth 1 properties for pTraits. Reorganized files. --- godot/AuthoredPropertyCreationScreen.gd | 4 +- godot/BNumberBlueprint.gd | 5 + godot/BNumberEffect.gd | 5 +- godot/CharacterEditScreen.gd | 2 +- godot/Clipboard.gd | 119 ++ godot/Compiler.gd | 7 +- godot/Desiderata_settings.tscn | 21 - godot/DocPageDisplay.tscn | 2 - godot/DragAndDropList.gd | 271 ++++- godot/DragAndDropList.tscn | 11 + godot/Encounter.gd | 11 +- godot/EncounterEditScreen.gd | 1030 +++++++---------- godot/EncounterEditScreen.tscn | 245 ++-- godot/EncounterOverviewScreen.gd | 13 +- godot/EncounterOverviewScreen.tscn | 1 + godot/FileMenu.gd | 1 - godot/GUI.gd | 88 +- godot/GUI.tscn | 85 +- godot/HelpMenu.gd | 1 + godot/Option.gd | 9 + godot/PlayScreen.gd | 37 +- godot/PlayScreen.tscn | 38 +- godot/Reaction.gd | 9 + godot/SWEffect.gd | 22 + godot/ScriptEditScreen.gd | 2 +- godot/SettingsEditScreen.gd | 2 +- godot/SettingsEditScreen.tscn | 9 +- godot/SingleBNumberBlueprintEditPanel.gd | 4 +- godot/Spool.gd | 15 + godot/SpoolEditScreen.gd | 44 +- godot/SpoolEditScreen.tscn | 2 +- godot/SpoolEffect.gd | 5 +- godot/Storyworld.gd | 40 +- godot/StoryworldValidationInterface.gd | 2 +- godot/StoryworldValidationInterface.tscn | 10 +- godot/UpdateScreen.gd | 41 + godot/UpdateScreen.tscn | 47 + godot/custom_resources/clarity.tres | 17 +- godot/custom_resources/encounter_engine.html | 321 +++-- godot/custom_resources/lapis_lazuli.tres | 19 +- godot/export_presets.cfg | 6 +- godot/project.godot | 60 +- .../AbsoluteValueOperator.gd | 0 .../ArithmeticComparator.gd | 0 .../ArithmeticMeanOperator.gd | 0 .../ArithmeticNegationOperator.gd | 0 godot/{ => sw_scripting}/BNumberConstant.gd | 0 godot/{ => sw_scripting}/BNumberPointer.gd | 0 godot/{ => sw_scripting}/BSumOperator.gd | 0 godot/{ => sw_scripting}/BlendOperator.gd | 0 godot/{ => sw_scripting}/BooleanComparator.gd | 0 godot/{ => sw_scripting}/BooleanConstant.gd | 0 godot/{ => sw_scripting}/Desideratum.gd | 0 godot/{ => sw_scripting}/EventPointer.gd | 0 godot/{ => sw_scripting}/NudgeOperator.gd | 0 godot/{ => sw_scripting}/SWEqualsOperator.gd | 0 godot/{ => sw_scripting}/SWIfOperator.gd | 0 godot/{ => sw_scripting}/SWMaxOperator.gd | 0 godot/{ => sw_scripting}/SWMinOperator.gd | 0 godot/{ => sw_scripting}/SWNotOperator.gd | 0 godot/{ => sw_scripting}/SWOperator.gd | 0 godot/{ => sw_scripting}/SWPointer.gd | 0 godot/{ => sw_scripting}/SWScriptElement.gd | 0 godot/{ => sw_scripting}/ScriptManager.gd | 8 +- godot/{ => sw_scripting}/SpoolPointer.gd | 0 .../{ => sw_scripting}/SpoolStatusPointer.gd | 0 .../StringConcatenationOperator.gd | 0 godot/{ => sw_scripting}/StringConstant.gd | 0 .../StringFormatOperator.gd | 0 69 files changed, 1456 insertions(+), 1235 deletions(-) create mode 100644 godot/Clipboard.gd delete mode 100644 godot/Desiderata_settings.tscn create mode 100644 godot/UpdateScreen.gd create mode 100644 godot/UpdateScreen.tscn rename godot/{ => sw_scripting}/AbsoluteValueOperator.gd (100%) rename godot/{ => sw_scripting}/ArithmeticComparator.gd (100%) rename godot/{ => sw_scripting}/ArithmeticMeanOperator.gd (100%) rename godot/{ => sw_scripting}/ArithmeticNegationOperator.gd (100%) rename godot/{ => sw_scripting}/BNumberConstant.gd (100%) rename godot/{ => sw_scripting}/BNumberPointer.gd (100%) rename godot/{ => sw_scripting}/BSumOperator.gd (100%) rename godot/{ => sw_scripting}/BlendOperator.gd (100%) rename godot/{ => sw_scripting}/BooleanComparator.gd (100%) rename godot/{ => sw_scripting}/BooleanConstant.gd (100%) rename godot/{ => sw_scripting}/Desideratum.gd (100%) rename godot/{ => sw_scripting}/EventPointer.gd (100%) rename godot/{ => sw_scripting}/NudgeOperator.gd (100%) rename godot/{ => sw_scripting}/SWEqualsOperator.gd (100%) rename godot/{ => sw_scripting}/SWIfOperator.gd (100%) rename godot/{ => sw_scripting}/SWMaxOperator.gd (100%) rename godot/{ => sw_scripting}/SWMinOperator.gd (100%) rename godot/{ => sw_scripting}/SWNotOperator.gd (100%) rename godot/{ => sw_scripting}/SWOperator.gd (100%) rename godot/{ => sw_scripting}/SWPointer.gd (100%) rename godot/{ => sw_scripting}/SWScriptElement.gd (100%) rename godot/{ => sw_scripting}/ScriptManager.gd (99%) rename godot/{ => sw_scripting}/SpoolPointer.gd (100%) rename godot/{ => sw_scripting}/SpoolStatusPointer.gd (100%) rename godot/{ => sw_scripting}/StringConcatenationOperator.gd (100%) rename godot/{ => sw_scripting}/StringConstant.gd (100%) rename godot/{ => sw_scripting}/StringFormatOperator.gd (100%) diff --git a/godot/AuthoredPropertyCreationScreen.gd b/godot/AuthoredPropertyCreationScreen.gd index 3ea8126..1f6fa35 100644 --- a/godot/AuthoredPropertyCreationScreen.gd +++ b/godot/AuthoredPropertyCreationScreen.gd @@ -53,7 +53,7 @@ func _on_AddButton_pressed(): $PropertyCreationWindow/VBC/BNumberEditPanel.current_authored_property = draft_of_new_authored_property $PropertyCreationWindow/VBC/BNumberEditPanel.creating_new_property = true $PropertyCreationWindow/VBC/BNumberEditPanel.refresh() - $PropertyCreationWindow.popup() + $PropertyCreationWindow.popup_centered() func _on_PropertyCreationWindow_confirmed(): var property = $PropertyCreationWindow/VBC/BNumberEditPanel.current_authored_property @@ -102,7 +102,7 @@ func _on_DeleteButton_pressed(): # new_label = Label.new() # new_label.text = "If you want to delete these properties, please select another property to replace them with in those scripts that currently use them." # $ConfirmPropertyDeletionWindow/VBC.add_child(new_label) - $ConfirmPropertyDeletionWindow.popup() + $ConfirmPropertyDeletionWindow.popup_centered() func _on_ConfirmPropertyDeletionWindow_confirmed(): if (0 == authored_properties_to_delete.size()): diff --git a/godot/BNumberBlueprint.gd b/godot/BNumberBlueprint.gd index f998716..aa20202 100644 --- a/godot/BNumberBlueprint.gd +++ b/godot/BNumberBlueprint.gd @@ -26,6 +26,11 @@ func _init(in_storyworld, in_creation_index, in_id, in_property_name, in_depth = creation_time = OS.get_unix_time() modified_time = OS.get_unix_time() +func get_index(): + if (null != storyworld): + return storyworld.authored_properties.find(self) + return -1 + func get_property_name(): if ("" != property_name): return property_name diff --git a/godot/BNumberEffect.gd b/godot/BNumberEffect.gd index 1474ee4..d4e2281 100644 --- a/godot/BNumberEffect.gd +++ b/godot/BNumberEffect.gd @@ -39,6 +39,7 @@ func set_as_copy_of(original): assignment_script.set_as_copy_of(original.assignment_script) else: success = false + cause = original.cause return success func remap(storyworld): @@ -99,7 +100,7 @@ func load_from_json_v0_0_21_through_v0_0_29(storyworld, data_to_load): else: return false -func load_from_json_v0_0_34_through_v0_0_37(storyworld, data_to_load): +func load_from_json_v0_0_34_through_v0_0_38(storyworld, data_to_load): clear() if (data_to_load.has_all(["Set", "to"])): if (data_to_load["Set"].has_all(["pointer_type", "character", "coefficient", "keyring"]) and "Bounded Number Pointer" == data_to_load["Set"]["pointer_type"] and TYPE_STRING == typeof(data_to_load["Set"]["character"]) and storyworld.character_directory.has(data_to_load["Set"]["character"])): @@ -116,7 +117,7 @@ func load_from_json_v0_0_34_through_v0_0_37(storyworld, data_to_load): output_datatype = sw_script_data_types.BNUMBER elif (assignee.output_type == sw_script_data_types.BOOLEAN): output_datatype = sw_script_data_types.BOOLEAN - script.load_from_json_v0_0_34_through_v0_0_37(storyworld, data_to_load["to"], output_datatype) + script.load_from_json_v0_0_34_through_v0_0_38(storyworld, data_to_load["to"], output_datatype) assignment_script = script if (null != assignee and assignee is BNumberPointer and null != assignment_script and assignment_script is ScriptManager): return true diff --git a/godot/CharacterEditScreen.gd b/godot/CharacterEditScreen.gd index 4d55e69..50e35bc 100644 --- a/godot/CharacterEditScreen.gd +++ b/godot/CharacterEditScreen.gd @@ -100,7 +100,7 @@ func _on_DeleteCharacter_pressed(): $ConfirmCharacterDeletion/Center/AntagonistReplacementPicker.set_item_metadata(option_index, each) option_index += 1 $ConfirmCharacterDeletion/Center/AntagonistReplacementPicker.select(0) - $ConfirmCharacterDeletion.popup() + $ConfirmCharacterDeletion.popup_centered() else: print("The storyworld must have at least one character.") diff --git a/godot/Clipboard.gd b/godot/Clipboard.gd new file mode 100644 index 0000000..cd37918 --- /dev/null +++ b/godot/Clipboard.gd @@ -0,0 +1,119 @@ +extends Object +class_name Clipboard + +var storyworld = null +#Clipboard system variables: +var clipped_copies = [] #Copies of the clipped data. +var clipped_originals = [] #References to the original objects that were clipped. +enum clipboard_task_types {NONE, CUT, COPY} +var clipboard_task = clipboard_task_types.NONE +enum clippable_item_types {OPTION, REACTION, EFFECT} + +func _init(): + pass + +func clear(): + clipped_originals.clear() + for item in clipped_copies: + item.clear() + item.call_deferred("free") + clipped_copies.clear() + clipboard_task = clipboard_task_types.NONE + +func clip(items): + clear() + clipped_originals = items + for item in items: + if (item is Option): + var copy = Option.new(null, "", "") + copy.set_as_copy_of(item, false) + clipped_copies.append(copy) + elif (item is Reaction): + var copy = Reaction.new(null, "", "") + copy.set_as_copy_of(item, false) + clipped_copies.append(copy) + elif (item is BNumberEffect): + var copy = BNumberEffect.new() + copy.set_as_copy_of(item) + clipped_copies.append(copy) + elif (item is SpoolEffect): + var copy = SpoolEffect.new() + copy.set_as_copy_of(item) + clipped_copies.append(copy) + +func cut(items): + clip(items) + clipboard_task = clipboard_task_types.CUT + +func copy(items): + clip(items) + clipboard_task = clipboard_task_types.COPY + +func log_update(encounter = null): + #If encounter == null, then the project as a whole is being updated, rather than a specific encounter, or an encounter has been added, deleted, or duplicated. + if (null != encounter): + encounter.log_update() + storyworld.log_update() + OS.set_window_title("SweepWeave - " + storyworld.storyworld_title + "*") + storyworld.project_saved = false + emit_signal("refresh_encounter_list") + +func delete_clipped_originals(): + if (clipped_originals.empty()): + return + for item in clipped_originals: + if (item is Option): + storyworld.delete_option_from_scripts(item) + if (null != item.encounter): + item.encounter.options.erase(item) + item.encounter.wordcount() + log_update(item.encounter) + item.clear() + item.call_deferred("free") + emit_signal("refresh_graphview") + elif (item is Reaction): + storyworld.delete_reaction_from_scripts(item) + if (null != item.option): + item.option.reactions.erase(item) + item.option.encounter.wordcount() + log_update(item.option.encounter) + item.clear() + item.call_deferred("free") + emit_signal("refresh_graphview") + elif (item is BNumberEffect): + if (null != item.cause): + item.cause.after_effects.erase(item) + log_update(item.cause.option.encounter) + item.clear() + item.call_deferred("free") + elif (item is SpoolEffect): + if (null != item.cause): + item.cause.after_effects.erase(item) + log_update(item.cause.option.encounter) + item.clear() + item.call_deferred("free") + clipped_originals.clear() + +func paste(): + var items_to_paste = [] + if (null == storyworld or !(storyworld is Storyworld)): + #Cannot create new items without a storyworld to tie them to. + return items_to_paste + for item in clipped_copies: + if (item is Option): + var copy = storyworld.create_new_generic_option(null) + copy.set_as_copy_of(item, false) + items_to_paste.append(copy) + elif (item is Reaction): + var copy = storyworld.create_new_generic_reaction(null) + copy.set_as_copy_of(item, false) + items_to_paste.append(copy) + elif (item is BNumberEffect): + var copy = BNumberEffect.new() + copy.set_as_copy_of(item) + items_to_paste.append(copy) + elif (item is SpoolEffect): + var copy = SpoolEffect.new() + copy.set_as_copy_of(item) + items_to_paste.append(copy) + return items_to_paste diff --git a/godot/Compiler.gd b/godot/Compiler.gd index 0127bc8..bcb44cd 100644 --- a/godot/Compiler.gd +++ b/godot/Compiler.gd @@ -22,14 +22,17 @@ func get_template_from_file(): print(error_message) return html_content -func _init(game_data, storyworld_title, storyworld_author, ifid, template = "res://custom_resources/encounter_engine.html"): +func _init(game_data, storyworld_title, storyworld_author, ifid, storyworld_debug_mode_on, template = "res://custom_resources/encounter_engine.html"): file_to_read = template output = get_template_from_file() + if (!storyworld_debug_mode_on): + var regex = RegEx.new() + regex.compile("\\s*console\\.log\\(.*\\);") + output = regex.sub(output, "", true) if ("" != storyworld_title): output = output.replacen("SweepWeave Storyworld Interpreter", "" + storyworld_title + "") if ("" != storyworld_author): output = output.replacen("", "") if ("" != ifid): output = output.replacen("", "") - output = output.replacen('', "") diff --git a/godot/Desiderata_settings.tscn b/godot/Desiderata_settings.tscn deleted file mode 100644 index 92422f9..0000000 --- a/godot/Desiderata_settings.tscn +++ /dev/null @@ -1,21 +0,0 @@ -[gd_scene format=2] - -[node name="Control" type="Control"] -anchor_right = 1.0 -anchor_bottom = 1.0 - -[node name="VBoxContainer" type="VBoxContainer" parent="."] -margin_right = 40.0 -margin_bottom = 40.0 -__meta__ = { -"_edit_use_anchors_": false -} - -[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer"] -margin_right = 40.0 - -[node name="ItemList" type="ItemList" parent="VBoxContainer/HBoxContainer"] - -[node name="ItemList2" type="ItemList" parent="VBoxContainer/HBoxContainer"] -margin_left = 4.0 -margin_right = 4.0 diff --git a/godot/DocPageDisplay.tscn b/godot/DocPageDisplay.tscn index 1cbb405..bcd8224 100644 --- a/godot/DocPageDisplay.tscn +++ b/godot/DocPageDisplay.tscn @@ -15,7 +15,5 @@ size_flags_vertical = 3 scroll_horizontal_enabled = false [node name="VBC" type="VBoxContainer" parent="Scroll"] -margin_right = 1366.0 -margin_bottom = 736.0 size_flags_horizontal = 3 size_flags_vertical = 3 diff --git a/godot/DragAndDropList.gd b/godot/DragAndDropList.gd index 1f8f3b6..443ecde 100644 --- a/godot/DragAndDropList.gd +++ b/godot/DragAndDropList.gd @@ -1,36 +1,42 @@ extends Tree -#For other examples of how to implement drag and drop, see: -# 1) https://godotengine.org/qa/19320/how-to-add-drag-and-drop-to-a-tree-node -# 2) https://www.youtube.com/watch?v=cNvzGKCkNXg -#var list_to_display = [{"text": "Alpha", "metadata": "Alpha_"}, -# {"text": "Beta", "metadata": "Beta_"}, -# {"text": "Gamma", "metadata": "Gamma_"}, -# {"text": "Delta", "metadata": "Delta_"}] -var list_to_display = [] -var last_item = null +var items_to_list = [] +var last_treeitem = null +var item_count = 0 +var context_menu_enabled = false +var item_type = "" #Used by context menu. +var focused_item = null +var clipboard = null signal moved_item(item, from_index, to_index) +signal add_at(index) +signal cut(items) +signal copy(items) +signal paste_at(index) +signal delete(items) +signal duplicate(items) func _ready(): refresh() -func refresh(): - display_list(list_to_display) +func list_item(item): + var branch = create_item(get_root()) + branch.set_text(0, item.get_listable_text()) + branch.set_tooltip(0, item.get_listable_text(70)) + var meta = {} + meta["index"] = item_count + meta["listed_object"] = item + branch.set_metadata(0, meta) + last_treeitem = branch + item_count += 1 -func display_list(list): +func refresh(): clear() - var root = create_item() - var entry_index = 0 - for entry in list: - var branch = create_item(root) - branch.set_text(0, entry["text"]) - var meta = {} - meta["index"] = entry_index - meta["listed_object"] = entry["metadata"] - branch.set_metadata(0, meta) - last_item = branch - entry_index += 1 + create_item() + last_treeitem = null + item_count = 0 + for item in items_to_list: + list_item(item) func get_drag_data(position): # begin drag set_drop_mode_flags(DROP_MODE_INBETWEEN) @@ -59,35 +65,214 @@ func drop_data(position, item): # end drag var relocated_object = item.get_metadata(0)["listed_object"] emit_signal('moved_item', relocated_object, from_index, to_index) # Rearrange list. - var element = list_to_display.pop_at(from_index) + var element = items_to_list.pop_at(from_index) if (to_index > from_index): to_index = to_index - 1 - if (to_index < list_to_display.size()): - list_to_display.insert(to_index, element) + if (to_index < items_to_list.size()): + items_to_list.insert(to_index, element) else: - list_to_display.append(element) - display_list(list_to_display) - -func get_selected_metadata(): - #Returns the element stored as metadata in the currently selected list item. - var selection = get_selected() - if (null != selection and selection is TreeItem): - return selection.get_metadata(0)["listed_object"] + items_to_list.append(element) + refresh() + select_linked_item(element) + +func get_first_selected_metadata(): + #Returns the element stored as metadata in the first currently selected list item. + var selected_item = get_next_selected(null) + if (null != selected_item and selected_item is TreeItem): + return selected_item.get_metadata(0)["listed_object"] + else: + return null + +func get_first_selected_index(): + #Returns the index of the first currently selected list item. + var selected_item = get_next_selected(null) + if (null != selected_item and selected_item is TreeItem): + return selected_item.get_metadata(0)["index"] else: return null +func get_all_selected_metadata(): + #Returns the element stored as metadata in the first currently selected list item. + var selected_item = get_next_selected(null) + var metadata = [] + while (null != selected_item): + metadata.append(selected_item.get_metadata(0)["listed_object"]) + selected_item = get_next_selected(selected_item) + return metadata + func select_first_item(): var treeitem = get_root().get_children() if (null != treeitem): treeitem.select(0) func select_last_item(): - if (null != last_item): - last_item.select(0) - -func replace_item(object, replacement, unique_rows = true): - for row in list_to_display: - if (object == row["metadata"]): - row["metadata"] = replacement - if (unique_rows): - break + if (null != last_treeitem): + last_treeitem.select(0) + +func select_linked_item(search_term): + #Finds and selects the treeitem associated with an option, reaction, effect, or other object. + var branch = get_root().get_children() + while (null != branch): + if (search_term == branch.get_metadata(0)["listed_object"]): + branch.select(0) + break + branch = branch.get_next() + +func select_only_linked_item(search_term): + #Selects the linked item while deselecting all other items. + var branch = get_root().get_children() + while (null != branch): + if (search_term == branch.get_metadata(0)["listed_object"]): + branch.select(0) + else: + branch.deselect(0) + branch = branch.get_next() + +func select_all(): + var branch = get_root().get_children() + while (null != branch): + branch.select(0) + branch = branch.get_next() + +func deselect_all(): + var branch = get_root().get_children() + while (null != branch): + branch.deselect(0) + branch = branch.get_next() + +func raise_selected_item(): + var index = get_first_selected_index() + if (0 < index and index < items_to_list.size()): + var swap = items_to_list[index] + items_to_list[index] = items_to_list[index - 1] + items_to_list[index - 1] = swap + refresh() + select_linked_item(swap) + emit_signal('moved_item', swap, index, index - 1) + +func lower_selected_item(): + var index = get_first_selected_index() + if (index < (items_to_list.size() - 1)): + var swap = items_to_list[index] + items_to_list[index] = items_to_list[index + 1] + items_to_list[index + 1] = swap + refresh() + select_linked_item(swap) + emit_signal('moved_item', swap, index, index + 2) + +func can_paste(): + if (clipboard.clipped_copies.empty()): + return false + elif (clipboard.clipped_copies.front() is Option and "option" == item_type): + return true + elif (clipboard.clipped_copies.front() is Reaction and "reaction" == item_type): + return true + elif (clipboard.clipped_copies.front() is SWEffect and "effect" == item_type): + return true + else: + return false + +func _on_item_rmb_selected(position): + if (context_menu_enabled): + focused_item = get_item_at_position(position).get_metadata(0)["listed_object"] + # Bring up context menu. + var mouse_position = get_global_mouse_position() + var context_menu = $ContextMenu + context_menu.clear() + if ("option" == item_type or "reaction" == item_type): + context_menu.add_item("Add " + item_type + " before this", 0) + context_menu.add_item("Add " + item_type + " after this", 1) + context_menu.add_item("Cut", 3) + context_menu.add_item("Copy", 4) + context_menu.add_item("Paste before this", 5) + context_menu.add_item("Paste after this", 6) + if (!can_paste()): + #Disable pasting options. + context_menu.set_item_disabled((context_menu.get_item_count() - 1), true) + context_menu.set_item_disabled((context_menu.get_item_count() - 2), true) + context_menu.add_item("Delete", 8) + context_menu.add_item("Duplicate", 9) + context_menu.add_item("Select all", 10) + context_menu.add_item("Deselect all", 11) + context_menu.popup(Rect2(mouse_position.x, mouse_position.y, context_menu.rect_size.x, context_menu.rect_size.y)) + +func show_outer_context_menu(): + #This shows the context menu that is designed for when the user clicks the empty part of the tree. + focused_item = null + # Bring up context menu. + var mouse_position = get_global_mouse_position() + var context_menu = $ContextMenu + context_menu.clear() + if ("option" == item_type or "reaction" == item_type): + context_menu.add_item("Add new " + item_type, 2) + context_menu.add_item("Paste", 7) + if (!can_paste()): + #Disable pasting options. + context_menu.set_item_disabled((context_menu.get_item_count() - 1), true) + context_menu.add_item("Select all", 10) + context_menu.add_item("Deselect all", 11) + context_menu.set_as_minsize() + context_menu.popup(Rect2(mouse_position.x, mouse_position.y, context_menu.rect_size.x, context_menu.rect_size.y)) + +func _on_empty_rmb(position): + if (context_menu_enabled): + show_outer_context_menu() + +func _on_empty_tree_rmb_selected(position): + if (context_menu_enabled): + show_outer_context_menu() + +func _on_ContextMenu_id_pressed(id): + var index = 0 + if (null != focused_item): + if (focused_item is Option or focused_item is Reaction or focused_item is SWEffect): + index = focused_item.get_index() + match id: + 0: + #Add new item before + emit_signal("add_at", index) + print ("Adding new " + item_type + " before the selected one.") + 1: + #Add new item after + emit_signal("add_at", index + 1) + print ("Adding new " + item_type + " after the selected one.") + 2: + #Add new item at end of list + emit_signal("add_at", item_count) + print ("Adding new " + item_type + " at the end of the list.") + 3: + #Cut + emit_signal("cut", get_all_selected_metadata()) + print ("Cutting selected " + item_type + " for pasting.") + 4: + #Copy + emit_signal("copy", get_all_selected_metadata()) + print ("Copying selected " + item_type + ".") + 5: + #Paste before + emit_signal("paste_at", index) + print ("Pasting before selected " + item_type + ".") + 6: + #Paste after + emit_signal("paste_at", index + 1) + print ("Pasting after selected " + item_type + ".") + 7: + #Paste at end of list + emit_signal("paste_at", item_count) + print ("Pasting at the end of the list.") + 8: + #Delete + emit_signal("delete", get_all_selected_metadata()) + print ("Asking for confirmation for possible deletion of " + item_type + "s.") + 9: + #Duplicate + emit_signal("duplicate", get_all_selected_metadata()) + print ("Duplicating selected " + item_type + "s.") + 10: + #Select all + select_all() + print ("Selecting all " + item_type + "s.") + 11: + #Deselect all + deselect_all() + print ("Deselecting all " + item_type + "s.") diff --git a/godot/DragAndDropList.tscn b/godot/DragAndDropList.tscn index 8d37f99..3d17311 100644 --- a/godot/DragAndDropList.tscn +++ b/godot/DragAndDropList.tscn @@ -7,5 +7,16 @@ anchor_right = 1.0 anchor_bottom = 1.0 rect_min_size = Vector2( 0, 32 ) custom_colors/drop_position_color = Color( 0.12549, 0.501961, 1, 1 ) +allow_rmb_select = true hide_root = true +select_mode = 2 script = ExtResource( 1 ) + +[node name="ContextMenu" type="PopupMenu" parent="."] +margin_right = 20.0 +margin_bottom = 20.0 + +[connection signal="empty_rmb" from="." to="." method="_on_empty_rmb"] +[connection signal="empty_tree_rmb_selected" from="." to="." method="_on_empty_tree_rmb_selected"] +[connection signal="item_rmb_selected" from="." to="." method="_on_item_rmb_selected"] +[connection signal="id_pressed" from="ContextMenu" to="." method="_on_ContextMenu_id_pressed"] diff --git a/godot/Encounter.gd b/godot/Encounter.gd index f585c3e..29a36c4 100644 --- a/godot/Encounter.gd +++ b/godot/Encounter.gd @@ -40,7 +40,6 @@ func get_index(): if (null != storyworld): return storyworld.encounters.find(self) return -1 - return -1 func get_text(leaf = null): if (text_script is ScriptManager): @@ -53,6 +52,15 @@ func set_text(new_text): if (text_script.contents is StringConstant): text_script.contents.set_value(new_text) +func get_listable_text(maximum_output_length = 50): + var text = title + if ("" == text): + return "[Untitled Encounter]" + elif (maximum_output_length >= text.length()): + return text + else: + return text.left(maximum_output_length - 3) + "..." + func calculate_desirability(leaf, report): var result = null if (null != desirability_script and desirability_script is ScriptManager): @@ -119,6 +127,7 @@ func remap(to_storyworld): for reaction in option.reactions: for effect in reaction.after_effects: effect.remap(to_storyworld) + effect.cause = reaction if (null != reaction.consequence and null != reaction.consequence.id): if (storyworld.encounter_directory.has(reaction.consequence.id)): reaction.consequence = storyworld.encounter_directory[reaction.consequence.id] diff --git a/godot/EncounterEditScreen.gd b/godot/EncounterEditScreen.gd index bfe6da5..6cb981c 100644 --- a/godot/EncounterEditScreen.gd +++ b/godot/EncounterEditScreen.gd @@ -5,16 +5,10 @@ var current_option = null var current_reaction = null var storyworld = null var node_scene = preload("res://graphview_node.tscn") -#Track objects to delete. -var encounters_to_delete = [] -var options_to_delete = null -var reactions_to_delete = null -var effect_to_delete = null +#Track items to delete. +var items_to_delete = [] #Clipboard system variables: -var clipboard = [] #Copies of the clipped data. -var clipped_originals = [] #References to the original objects that were clipped. -enum clipboard_task_types {NONE, CUT, COPY} -var clipboard_task = clipboard_task_types.NONE +var clipboard = null #Display options: #Track whether or not to display the quick reaction desirability script editor. var display_reaction_qdse = true @@ -50,49 +44,37 @@ func set_display_reaction_qdse(display): display_reaction_qdse = display refresh_quick_reaction_scripting_interface() -func list_option(option, cutoff = 50): - var optionslist = $HSC/Column2/OptionsScroll/OptionsList - var index = optionslist.get_item_count() - var text = option.get_text() - if ("" == text): - optionslist.add_item("[Blank Option]") - elif (text.left(cutoff) == text): - optionslist.add_item(text) - else: - optionslist.add_item(text.left(cutoff) + "...") - optionslist.set_item_tooltip(index, text) - optionslist.set_item_metadata(index, option) +func set_clipboard(new_clipboard): + clipboard = new_clipboard + $HSC/Column2/OptionsList.clipboard = new_clipboard + $HSC/Column3/ReactionsList.clipboard = new_clipboard + $HSC/Column3/AfterReactionEffectsDisplay.clipboard = new_clipboard -func refresh_option_list(cutoff = 100): - $HSC/Column2/OptionsScroll/OptionsList.clear() +func refresh_option_list(): + $HSC/Column2/OptionsList.clear() if (null != current_encounter): - for option in current_encounter.options: - list_option(option, cutoff) + $HSC/Column2/OptionsList.items_to_list = current_encounter.options.duplicate() + $HSC/Column2/OptionsList.refresh() if (0 < current_encounter.options.size()): - load_Option(current_encounter.options[0]) - $HSC/Column2/OptionsScroll/OptionsList.select(0) - -func list_reaction(reaction, cutoff = 50): - var reactionslist = $HSC/Column3/ReactionsScroll/ReactionList - var index = reactionslist.get_item_count() - var text = reaction.get_text() - if ("" == text): - reactionslist.add_item("[Blank Reaction]") - elif (text.left(cutoff) == text): - reactionslist.add_item(text) + load_Option(current_encounter.options.front()) + $HSC/Column2/OptionsList.select_first_item() else: - reactionslist.add_item(text.left(cutoff) + "...") - reactionslist.set_item_tooltip(index, text) - reactionslist.set_item_metadata(index, reaction) + $HSC/Column2/OptionsList.items_to_list.clear() + $HSC/Column2/OptionsList.refresh() -func refresh_reaction_list(cutoff = 100): - $HSC/Column3/ReactionsScroll/ReactionList.clear() +func refresh_reaction_list(): + $HSC/Column3/ReactionsList.clear() if (null != current_option): - for reaction in current_option.reactions: - list_reaction(reaction, cutoff) + $HSC/Column3/ReactionsList.items_to_list = current_option.reactions.duplicate() + $HSC/Column3/ReactionsList.refresh() + if (0 < current_option.reactions.size()): + load_Reaction(current_option.reactions.front()) + $HSC/Column3/ReactionsList.select_first_item() + else: + $HSC/Column3/ReactionsList.items_to_list.clear() + $HSC/Column3/ReactionsList.refresh() func replace_character(deleted_character, replacement): - print("Replacing " + deleted_character.char_name + " with " + replacement.char_name) log_update(null) refresh_bnumber_property_lists() @@ -104,11 +86,10 @@ func refresh_character_names(): func refresh_reaction_after_effects_list(): $HSC/Column3/AfterReactionEffectsDisplay.clear() - $HSC/Column3/AfterReactionEffectsDisplay.list_to_display.clear() if (null != current_reaction): - for change in current_reaction.after_effects: - var entry = {"text": change.data_to_string(), "metadata": change} - $HSC/Column3/AfterReactionEffectsDisplay.list_to_display.append(entry) + $HSC/Column3/AfterReactionEffectsDisplay.items_to_list = current_reaction.after_effects.duplicate() + else: + $HSC/Column3/AfterReactionEffectsDisplay.items_to_list.clear() $HSC/Column3/AfterReactionEffectsDisplay.refresh() $EffectEditor/EffectEditorScreen.reset() $EffectEditor/EffectEditorScreen.refresh() @@ -238,7 +219,7 @@ func load_Option(option): $HSC/Column2/OptionText.text = option.get_text() if (0 < option.reactions.size()): load_Reaction(option.reactions[0]) - $HSC/Column3/ReactionsScroll/ReactionList.select(0) + $HSC/Column3/ReactionsList.select_first_item() func load_Encounter(encounter): if (null == encounter): @@ -247,13 +228,11 @@ func load_Encounter(encounter): current_encounter = encounter $HSC/Column2/HBCTitle/EncounterTitleEdit.text = encounter.title $HSC/Column2/EncounterMainTextEdit.text = encounter.get_text() - $HSC/Column2/HBCTurn/VBC/EarliestTurn.value = encounter.earliest_turn - $HSC/Column2/HBCTurn/VBC2/LatestTurn.value = encounter.latest_turn refresh_bnumber_property_lists() refresh_option_list() if (0 < encounter.options.size()): load_Option(encounter.options[0]) - $HSC/Column2/OptionsScroll/OptionsList.select(0) + $HSC/Column2/OptionsList.select_first_item() else: load_Option(null) @@ -268,13 +247,15 @@ func Clear_Encounter_Editing_Screen(): current_reaction = null $HSC/Column2/HBCTitle/EncounterTitleEdit.text = "" $HSC/Column2/EncounterMainTextEdit.text = "" - $HSC/Column2/HBCTurn/VBC/EarliestTurn.value = 0 - $HSC/Column2/HBCTurn/VBC2/LatestTurn.value = 0 - $HSC/Column2/OptionsScroll/OptionsList.clear() - $HSC/Column3/ReactionsScroll/ReactionList.clear() + $HSC/Column2/OptionsList.items_to_list.clear() + $HSC/Column2/OptionsList.refresh() $HSC/Column2/OptionText.text = "" + $HSC/Column3/ReactionsList.items_to_list.clear() + $HSC/Column3/ReactionsList.refresh() $HSC/Column3/ReactionText.text = "" $HSC/Column3/IncBlendWeightLabel.text = "Reaction desirability:" + $HSC/Column3/AfterReactionEffectsDisplay.items_to_list.clear() + $HSC/Column3/AfterReactionEffectsDisplay.refresh() refresh_bnumber_property_lists() load_Option(null) @@ -292,6 +273,8 @@ func log_update(encounter = null): storyworld.project_saved = false emit_signal("refresh_encounter_list") +#Encounter editing interface: + func _on_AddButton_pressed(): var new_encounter = storyworld.create_new_generic_encounter() storyworld.add_encounter(new_encounter) @@ -306,7 +289,6 @@ func _on_AddButton_pressed(): func _on_EncountersList_multi_selected(index, selected): var encounter_to_edit = storyworld.encounters[index] - print("Loading Encounter: " + encounter_to_edit.title) load_Encounter(encounter_to_edit) func _on_Duplicate_pressed(): @@ -317,7 +299,6 @@ func _on_Duplicate_pressed(): encounters_to_duplicate.append(storyworld.encounters[entry]) var encounter_to_edit = null for entry in encounters_to_duplicate: - print("Duplicating Encounter: " + entry.title) var new_encounter = storyworld.duplicate_encounter(entry) if (encounter_to_edit == null): encounter_to_edit = new_encounter @@ -345,345 +326,204 @@ func _on_EncounterMainTextEdit_text_changed(): log_update(current_encounter) emit_signal("refresh_graphview") -func _on_ConfirmEncounterDeletion_confirmed(): - var encounter_to_select = current_encounter - var starting_index = storyworld.encounters.find(current_encounter) - if (null != current_encounter and encounters_to_delete.has(current_encounter) and encounters_to_delete.size() < storyworld.encounters.size()): - for index in range(starting_index, storyworld.encounters.size()): - if (!encounters_to_delete.has(storyworld.encounters[index])): - encounter_to_select = storyworld.encounters[index] - break - if (encounter_to_select == current_encounter): - for index in range(starting_index, -1, -1): - if (!encounters_to_delete.has(storyworld.encounters[index])): +func _on_ConfirmDeletion_confirmed(): + if (items_to_delete.front() is Encounter): + var encounter_to_select = current_encounter + var starting_index = storyworld.encounters.find(current_encounter) + if (null != current_encounter and items_to_delete.has(current_encounter) and items_to_delete.size() < storyworld.encounters.size()): + for index in range(starting_index, storyworld.encounters.size()): + if (!items_to_delete.has(storyworld.encounters[index])): encounter_to_select = storyworld.encounters[index] break - if (encounter_to_select == current_encounter): - encounter_to_select = null - load_Encounter(encounter_to_select) - for each in encounters_to_delete: - storyworld.delete_encounter(each) - log_update(null) - refresh_encounter_list() - if (null != encounter_to_select): - $Column1/VScroll/EncountersList.select(storyworld.encounters.find(encounter_to_select)) + if (encounter_to_select == current_encounter): + for index in range(starting_index, -1, -1): + if (!items_to_delete.has(storyworld.encounters[index])): + encounter_to_select = storyworld.encounters[index] + break + if (encounter_to_select == current_encounter): + encounter_to_select = null + load_Encounter(encounter_to_select) + for each in items_to_delete: + storyworld.delete_encounter(each) + refresh_encounter_list() + if (null != encounter_to_select): + $Column1/VScroll/EncountersList.select(storyworld.encounters.find(encounter_to_select)) + log_update(null) + elif (items_to_delete.front() is Option): + for option in items_to_delete: + storyworld.delete_option_from_scripts(option) + option.encounter.options.erase(option) + option.clear() + option.call_deferred("free") + refresh_option_list() + if (!current_encounter.options.empty()): + load_Option(current_encounter.options.front()) + $HSC/Column2/OptionsList.select_first_item() + else: + load_Option(null) + update_wordcount(current_encounter) + log_update(current_encounter) + elif (items_to_delete.front() is Reaction): + for reaction in items_to_delete: + storyworld.delete_reaction_from_scripts(reaction) + reaction.option.reactions.erase(reaction) + reaction.clear() + reaction.call_deferred("free") + load_Option(current_option) + if (null != current_option and 0 < current_option.reactions.size()): + current_reaction = current_option.reactions[0] + load_Reaction(current_reaction) + $HSC/Column3/ReactionsList.select_first_item() + update_wordcount(current_encounter) + log_update(current_encounter) + elif (items_to_delete.front() is SWEffect): + for effect in items_to_delete: + current_reaction.after_effects.erase(effect) + effect.clear() + effect.call_deferred("free") + log_update(current_encounter) + refresh_reaction_after_effects_list() emit_signal("refresh_graphview") func _on_DeleteButton_pressed(): if ($Column1/VScroll/EncountersList.is_anything_selected()): var selection = $Column1/VScroll/EncountersList.get_selected_items() - encounters_to_delete.clear() + items_to_delete.clear() + $ConfirmDeletion/ItemsToDelete.clear() for each in selection: - encounters_to_delete.append(storyworld.encounters[each]) - if (!encounters_to_delete.empty()): - var dialog_text = "" - if (1 == encounters_to_delete.size()): - dialog_text = "Are you sure you wish to delete the following encounter?" + items_to_delete.append(storyworld.encounters[each]) + $ConfirmDeletion/ItemsToDelete.add_item(each.title) + if (!items_to_delete.empty()): + if (1 == items_to_delete.size()): + $ConfirmDeletion.dialog_text = "Are you sure you wish to delete the following encounter?" else: - dialog_text = "Are you sure you wish to delete the following encounters?" - $ConfirmEncounterDeletion/EncountersToDelete.clear() - for each in encounters_to_delete: - $ConfirmEncounterDeletion/EncountersToDelete.add_item(each.title) - $ConfirmEncounterDeletion.dialog_text = dialog_text - $ConfirmEncounterDeletion.popup() - -func _on_EarliestTurn_value_changed(value): - if (null != current_encounter): - current_encounter.earliest_turn = value - log_update(current_encounter) - -func _on_LatestTurn_value_changed(value): - if (null != current_encounter): - current_encounter.latest_turn = value - log_update(current_encounter) + $ConfirmDeletion.dialog_text = "Are you sure you wish to delete the following encounters?" + $ConfirmDeletion.popup_centered() -#Options and Reactions interface elements: #Option editing interface: func _on_AddOption_pressed(): if (null != current_encounter): var new_option = storyworld.create_new_generic_option(current_encounter) current_encounter.options.append(new_option) - list_option(new_option) + $HSC/Column2/OptionsList.items_to_list.append(new_option) + $HSC/Column2/OptionsList.list_item(new_option) load_Option(new_option) - $HSC/Column2/OptionsScroll/OptionsList.select(new_option.get_index()) + $HSC/Column2/OptionsList.deselect_all() + $HSC/Column2/OptionsList.select_last_item() update_wordcount(current_encounter) log_update(current_encounter) -func _on_ConfirmOptionDeletion_confirmed(): - for option in options_to_delete: - storyworld.delete_option_from_scripts(option) - option.encounter.options.erase(option) - option.clear() - option.call_deferred("free") - refresh_option_list() - if (!current_encounter.options.empty()): - load_Option(current_encounter.options.front()) - $HSC/Column2/OptionsScroll/OptionsList.select(0) - else: - load_Option(null) - update_wordcount(current_encounter) - log_update(current_encounter) - emit_signal("refresh_graphview") +func confirm_option_deletion(options): + items_to_delete = options + if (!items_to_delete.empty()): + $ConfirmDeletion/ItemsToDelete.clear() + for each in items_to_delete: + $ConfirmDeletion/ItemsToDelete.add_item(each.get_listable_text(30)) + if (1 == items_to_delete.size()): + $ConfirmDeletion.dialog_text = "Are you sure you wish to delete the following option?" + else: + $ConfirmDeletion.dialog_text = "Are you sure you wish to delete the following options?" + $ConfirmDeletion.popup_centered() func _on_DeleteOption_pressed(): - if ($HSC/Column2/OptionsScroll/OptionsList.is_anything_selected()): - var selection = $HSC/Column2/OptionsScroll/OptionsList.get_selected_items() - options_to_delete = [] - for each in selection: - options_to_delete.append(current_encounter.options[each]) - var dialog_text = "" - if (1 == options_to_delete.size()): - dialog_text = "Are you sure you wish to delete the following option?" - else: - dialog_text = "Are you sure you wish to delete the following options?" - for option in options_to_delete: - dialog_text += " (" + option.get_text() + ")" - $ConfirmOptionDeletion.dialog_text = dialog_text - $ConfirmOptionDeletion.popup() + confirm_option_deletion($HSC/Column2/OptionsList.get_all_selected_metadata()) + +func _on_OptionsList_moved_item(item, from_index, to_index): + if (null == current_encounter): + refresh_option_list() + return + var option = current_encounter.options.pop_at(from_index) + if (to_index > from_index): + to_index = to_index - 1 + if (to_index < current_encounter.options.size()): + current_encounter.options.insert(to_index, option) + else: + current_encounter.options.append(option) func _on_MoveOptionUpButton_pressed(): - if ($HSC/Column2/OptionsScroll/OptionsList.is_anything_selected()): - var selection = $HSC/Column2/OptionsScroll/OptionsList.get_selected_items() - if (0 != selection[0]): - var swap = current_encounter.options[selection[0]] - current_encounter.options[selection[0]] = current_encounter.options[selection[0]-1] - current_encounter.options[selection[0]-1] = swap - refresh_option_list() - if (0 < current_encounter.options.size()): - current_option = current_encounter.options[selection[0]-1] - $HSC/Column2/OptionsScroll/OptionsList.select(selection[0]-1) - load_Option(current_option) - $HSC/Column3/ReactionsScroll/ReactionList.select(0) - load_Reaction(current_option.reactions[0]) - log_update(current_encounter) + $HSC/Column2/OptionsList.raise_selected_item() func _on_MoveOptionDownButton_pressed(): - if ($HSC/Column2/OptionsScroll/OptionsList.is_anything_selected()): - var selection = $HSC/Column2/OptionsScroll/OptionsList.get_selected_items() - if ((current_encounter.options.size()-1) != selection[0]): - var swap = current_encounter.options[selection[0]] - current_encounter.options[selection[0]] = current_encounter.options[selection[0]+1] - current_encounter.options[selection[0]+1] = swap - refresh_option_list() - if (0 < current_encounter.options.size()): - current_option = current_encounter.options[selection[0]+1] - $HSC/Column2/OptionsScroll/OptionsList.select(selection[0]+1) - load_Option(current_option) - $HSC/Column3/ReactionsScroll/ReactionList.select(0) - load_Reaction(current_option.reactions[0]) - log_update(current_encounter) - -func _on_OptionsList_item_selected(index): - if ($HSC/Column2/OptionsScroll/OptionsList.is_anything_selected()): - var selection = $HSC/Column2/OptionsScroll/OptionsList.get_selected_items() - current_option = current_encounter.options[selection[0]] - load_Option(current_option) - $HSC/Column3/ReactionsScroll/ReactionList.select(0) - load_Reaction(current_option.reactions[0]) + $HSC/Column2/OptionsList.lower_selected_item() -func _on_OptionsList_multi_selected(index, selected): - if ($HSC/Column2/OptionsScroll/OptionsList.is_anything_selected()): - var selection = $HSC/Column2/OptionsScroll/OptionsList.get_selected_items() - current_option = current_encounter.options[selection[0]] +func _on_OptionsList_multi_selected(item, column, selected): + var selected_option = $HSC/Column2/OptionsList.get_first_selected_metadata() + if (null != selected_option): + current_option = selected_option load_Option(current_option) - $HSC/Column3/ReactionsScroll/ReactionList.select(0) - load_Reaction(current_option.reactions[0]) + load_Reaction(current_option.reactions.front()) + $HSC/Column3/ReactionsList.select_first_item() func _on_OptionText_text_changed(new_text): if (null != current_option): current_option.set_text($HSC/Column2/OptionText.text) - var optionslist = $HSC/Column2/OptionsScroll/OptionsList - var text = current_option.get_text() - if ("" == text): - optionslist.set_item_text(current_option.get_index(), "[Blank Option]") - elif (text.left(50) == text): - optionslist.set_item_text(current_option.get_index(), text) - else: - var index = current_option.get_index() - optionslist.set_item_text(index, text.left(50) + "...") - optionslist.set_item_tooltip(index, text) + $HSC/Column2/OptionsList.refresh() + $HSC/Column2/OptionsList.select_linked_item(current_option) update_wordcount(current_encounter) log_update(current_encounter) -func _on_OptionsList_item_rmb_selected(index, at_position): - # Bring up context menu. - var mouse_position = get_global_mouse_position() - var context_menu = $HSC/Column2/OptionsScroll/OptionsList/OptionsContextMenu - if ($HSC/Column2/OptionsScroll/OptionsList.is_anything_selected()): - var text_of_selection = "this." - context_menu.clear() - context_menu.add_item("Add option before " + text_of_selection, 0) - context_menu.set_item_metadata((context_menu.get_item_count() - 1), index) - context_menu.add_item("Add option after " + text_of_selection, 1) - context_menu.set_item_metadata((context_menu.get_item_count() - 1), index) - context_menu.add_item("Cut", 2) - context_menu.set_item_metadata((context_menu.get_item_count() - 1), index) - context_menu.add_item("Copy", 3) - context_menu.set_item_metadata((context_menu.get_item_count() - 1), index) - context_menu.add_item("Paste before " + text_of_selection, 4) - context_menu.set_item_metadata((context_menu.get_item_count() - 1), index) - context_menu.add_item("Paste after " + text_of_selection, 5) - context_menu.set_item_metadata((context_menu.get_item_count() - 1), index) - context_menu.add_item("Delete", 6) - context_menu.set_item_metadata((context_menu.get_item_count() - 1), index) - context_menu.add_item("Duplicate", 7) - context_menu.set_item_metadata((context_menu.get_item_count() - 1), index) -# context_menu.add_item("Select all", 8) -# context_menu.set_item_metadata((context_menu.get_item_count() - 1), index) - context_menu.popup(Rect2(mouse_position.x, mouse_position.y, context_menu.rect_size.x, context_menu.rect_size.y)) +#Option list context menu: func add_options_at_position(options_to_add, position): - if (0 == options_to_add.size()): - return - var copies_to_add = [] - for object in options_to_add: - var copy = storyworld.create_new_generic_option(current_encounter) - copy.set_as_copy_of(object, false) - copy.encounter = current_encounter - copies_to_add.append(copy) - if (1 == copies_to_add.size()): - current_encounter.options.insert(position, copies_to_add[0]) + if (1 == options_to_add.size()): + current_encounter.options.insert(position, options_to_add.front()) elif (0 >= position): - copies_to_add.append_array(current_encounter.options) - current_encounter.options = copies_to_add + options_to_add.append_array(current_encounter.options) + current_encounter.options = options_to_add elif (position < current_encounter.options.size()): var new_array = current_encounter.options.slice(0, (position - 1)) - new_array.append_array(copies_to_add) + new_array.append_array(options_to_add) new_array.append_array(current_encounter.options.slice(position, (current_encounter.options.size() - 1))) current_encounter.options = new_array elif (position >= current_encounter.options.size()): - current_encounter.options.append_array(copies_to_add) - refresh_option_list() - if (0 < current_encounter.options.size()): - if (0 < copies_to_add.size()): - load_Option(copies_to_add[0]) - $HSC/Column2/OptionsScroll/OptionsList.select(copies_to_add[0].get_index()) - else: - load_Option(current_encounter.options[0]) - $HSC/Column2/OptionsScroll/OptionsList.select(current_encounter.options[0].get_index()) - else: - load_Option(null) - update_wordcount(current_encounter) - log_update(current_encounter) - emit_signal("refresh_graphview") + current_encounter.options.append_array(options_to_add) -func duplicate_selected_options(): - if ($HSC/Column2/OptionsScroll/OptionsList.is_anything_selected()): +func duplicate_selected_options(selected_items): + if (!selected_items.empty()): var last_option_added = null - var selection = $HSC/Column2/OptionsScroll/OptionsList.get_selected_items() - for each in selection: - var option = $HSC/Column2/OptionsScroll/OptionsList.get_item_metadata(each) + for option in selected_items: var new_option = storyworld.create_new_generic_option(current_encounter) new_option.set_as_copy_of(option, false) new_option.encounter = current_encounter current_encounter.options.append(new_option) - list_option(new_option) + $HSC/Column2/OptionsList.items_to_list.append(new_option) + $HSC/Column2/OptionsList.list_item(new_option) last_option_added = new_option load_Option(last_option_added) + $HSC/Column2/OptionsList.select_only_linked_item(last_option_added) update_wordcount(current_encounter) log_update(current_encounter) emit_signal("refresh_graphview") -func add_selected_options_to_clipboard(): - if ($HSC/Column2/OptionsScroll/OptionsList.is_anything_selected()): - var selection = $HSC/Column2/OptionsScroll/OptionsList.get_selected_items() - for each in selection: - var option = $HSC/Column2/OptionsScroll/OptionsList.get_item_metadata(each) - var new_option = storyworld.create_new_generic_option(current_encounter) - new_option.set_as_copy_of(option, false) - clipboard.append(new_option) - clipped_originals.append(option) - -func delete_clipped_originals(): - if (0 >= clipped_originals.size()): - return - if (clipped_originals[0] is Option): - for object in clipped_originals: - if (object is Option): - print("Deleting option: " + object.get_truncated_text(20)) - storyworld.delete_option_from_scripts(object) - object.encounter.options.erase(object) - update_wordcount(object.encounter) - log_update(object.encounter) - object.clear() - object.call_deferred("free") +func _on_OptionsList_add_at(index): + if (null != current_encounter): + var new_option = storyworld.create_new_generic_option(current_encounter) + current_encounter.options.insert(index, new_option) refresh_option_list() - if (0 < current_encounter.options.size()): - load_Option(current_encounter.options[0]) - $HSC/Column2/OptionsScroll/OptionsList.select(0) - else: - load_Option(null) - elif (clipped_originals[0] is Reaction): - for object in clipped_originals: - if (object is Reaction): - print("Deleting reaction: " + object.get_truncated_text(20)) - storyworld.delete_reaction_from_scripts(object) - object.option.reactions.erase(object) - update_wordcount(object.option.encounter) - log_update(object.option.encounter) - object.clear() - object.call_deferred("free") - refresh_reaction_list() - if (0 < current_option.reactions.size()): - load_Reaction(current_option.reactions[0]) - $HSC/Column3/ReactionsScroll/ReactionList.select(0) - else: - load_Reaction(null) - emit_signal("refresh_graphview") + load_Option(new_option) + $HSC/Column2/OptionsList.select_only_linked_item(new_option) + update_wordcount(current_encounter) + log_update(current_encounter) -func _on_OptionsContextMenu_id_pressed(id): - var item_index = $HSC/Column2/OptionsScroll/OptionsList/OptionsContextMenu.get_item_metadata(id) - match id: - 0: - #Add new option before - var new_option = storyworld.create_new_generic_option(current_encounter) - add_options_at_position([new_option], item_index) - print ("Adding new option before the selected one.") - 1: - #Add new option after - var new_option = storyworld.create_new_generic_option(current_encounter) - add_options_at_position([new_option], item_index + 1) - print ("Adding new option after the selected one.") - 2: - #Cut - clipboard = [] - clipped_originals = [] - add_selected_options_to_clipboard() - clipboard_task = clipboard_task_types.CUT - print ("Cutting selected option for pasting.") - 3: - #Copy - clipboard = [] - clipped_originals = [] - add_selected_options_to_clipboard() - clipboard_task = clipboard_task_types.COPY - print ("Copying selected option.") - 4: - #Paste before - add_options_at_position(clipboard, item_index) - if (clipboard_task_types.CUT == clipboard_task): - delete_clipped_originals() - print ("Pasting before selected option.") - 5: - #Paste after - add_options_at_position(clipboard, item_index + 1) - if (clipboard_task_types.CUT == clipboard_task): - delete_clipped_originals() - print ("Pasting after selected option.") - 6: - #Delete - _on_DeleteOption_pressed() - print ("Asking for confirmation for possible deletion of options.") - 7: - #Duplicate - duplicate_selected_options() - print ("Duplicating selected option.") -# 8: -# #Select all -# for each in range($HSC/Column2/OptionsScroll/OptionsList.get_item_count()): -# $HSC/Column2/OptionsScroll/OptionsList.select(each) -# print ("Selecting all options.") +func _on_OptionsList_cut(items): + clipboard.cut(items) + +func _on_OptionsList_copy(items): + clipboard.copy(items) + +func _on_OptionsList_paste_at(index): + var items_to_add = clipboard.paste() + if (!items_to_add.empty()): + add_options_at_position(items_to_add, index) + if (clipboard.clipboard_task_types.CUT == clipboard.clipboard_task): + clipboard.delete_clipped_originals() + refresh_option_list() + load_Option(items_to_add.front()) + $HSC/Column2/OptionsList.select_only_linked_item(items_to_add.front()) + update_wordcount(current_encounter) + log_update(current_encounter) + emit_signal("refresh_graphview") #Reaction editing interface: @@ -691,107 +531,66 @@ func _on_AddReaction_pressed(): if (null != current_option): current_reaction = storyworld.create_new_generic_reaction(current_option) current_option.reactions.append(current_reaction) - list_reaction(current_reaction) + $HSC/Column3/ReactionsList.items_to_list.append(current_reaction) + $HSC/Column3/ReactionsList.list_item(current_reaction) load_Reaction(current_reaction) - $HSC/Column3/ReactionsScroll/ReactionList.select(current_reaction.get_index()) + $HSC/Column3/ReactionsList.deselect_all() + $HSC/Column3/ReactionsList.select_last_item() update_wordcount(current_encounter) log_update(current_encounter) -func _on_ConfirmReactionDeletion_confirmed(): - for reaction in reactions_to_delete: - print("Deleting reaction: " + reaction.get_truncated_text(25)) - storyworld.delete_reaction_from_scripts(reaction) - reaction.option.reactions.erase(reaction) - reaction.clear() - reaction.call_deferred("free") - load_Option(current_option) - if (null != current_option and 0 < current_option.reactions.size()): - current_reaction = current_option.reactions[0] - load_Reaction(current_reaction) - $HSC/Column3/ReactionsScroll/ReactionList.select(0) - update_wordcount(current_encounter) - log_update(current_encounter) - emit_signal("refresh_graphview") - -func _on_DeleteReaction_pressed(): - if ($HSC/Column3/ReactionsScroll/ReactionList.is_anything_selected()): - var selection = $HSC/Column3/ReactionsScroll/ReactionList.get_selected_items() - reactions_to_delete = [] - for each in selection: - reactions_to_delete.append(current_option.reactions[each]) +func confirm_reaction_deletion(reactions): + items_to_delete = reactions + if (!items_to_delete.empty()): + $ConfirmDeletion/ItemsToDelete.clear() + for each in items_to_delete: + $ConfirmDeletion/ItemsToDelete.add_item(each.get_listable_text(30)) if (1 == current_option.reactions.size()): $CannotDelete.dialog_text = 'Cannot delete reaction. Each option must have at least one reaction.' - $CannotDelete.popup() - print("Cannot delete reaction. Each option must have at least one reaction.") - elif(reactions_to_delete.size() == current_option.reactions.size()): + $CannotDelete.popup_centered() + elif(items_to_delete.size() == current_option.reactions.size()): #Print "reactions" instead of "reaction." $CannotDelete.dialog_text = 'Cannot delete reactions. Each option must have at least one reaction.' - $CannotDelete.popup() - print("Cannot delete reactions. Each option must have at least one reaction.") + $CannotDelete.popup_centered() else: - var dialog_text = "" - if (1 == reactions_to_delete.size()): - dialog_text = "Are you sure you wish to delete the following reaction?" + if (1 == items_to_delete.size()): + $ConfirmDeletion.dialog_text = "Are you sure you wish to delete the following reaction?" else: - dialog_text = "Are you sure you wish to delete the following reactions?" - for reaction in reactions_to_delete: - dialog_text += " (" + reaction.get_text() + ")" - $ConfirmReactionDeletion.dialog_text = dialog_text - $ConfirmReactionDeletion.popup() + $ConfirmDeletion.dialog_text = "Are you sure you wish to delete the following reactions?" + $ConfirmDeletion.popup_centered() + +func _on_DeleteReaction_pressed(): + confirm_reaction_deletion($HSC/Column3/ReactionsList.get_all_selected_metadata()) + +func _on_ReactionsList_moved_item(item, from_index, to_index): + if (null == current_option): + refresh_reaction_list() + return + var reaction = current_option.reactions.pop_at(from_index) + if (to_index > from_index): + to_index = to_index - 1 + if (to_index < current_option.reactions.size()): + current_option.reactions.insert(to_index, reaction) + else: + current_option.reactions.append(reaction) func _on_MoveReactionUpButton_pressed(): - if ($HSC/Column3/ReactionsScroll/ReactionList.is_anything_selected()): - var selection = $HSC/Column3/ReactionsScroll/ReactionList.get_selected_items() - if (0 != selection[0]): - var swap = current_option.reactions[selection[0]] - current_option.reactions[selection[0]] = current_option.reactions[selection[0]-1] - current_option.reactions[selection[0]-1] = swap - refresh_reaction_list() - if (0 < current_option.reactions.size()): - current_reaction = current_option.reactions[selection[0]-1] - $HSC/Column3/ReactionsScroll/ReactionList.select(selection[0]-1) - load_Reaction(current_reaction) - log_update(current_encounter) + $HSC/Column3/ReactionsList.raise_selected_item() func _on_MoveReactionDownButton_pressed(): - if ($HSC/Column3/ReactionsScroll/ReactionList.is_anything_selected()): - var selection = $HSC/Column3/ReactionsScroll/ReactionList.get_selected_items() - if ((current_option.reactions.size()-1) != selection[0]): - var swap = current_option.reactions[selection[0]] - current_option.reactions[selection[0]] = current_option.reactions[selection[0]+1] - current_option.reactions[selection[0]+1] = swap - refresh_reaction_list() - if (0 < current_option.reactions.size()): - current_reaction = current_option.reactions[selection[0]+1] - $HSC/Column3/ReactionsScroll/ReactionList.select(selection[0]+1) - load_Reaction(current_reaction) - log_update(current_encounter) - -func _on_ReactionList_item_selected(index): - if ($HSC/Column3/ReactionsScroll/ReactionList.is_anything_selected()): - var selection = $HSC/Column3/ReactionsScroll/ReactionList.get_selected_items() - current_reaction = current_option.reactions[selection[0]] - load_Reaction(current_reaction) + $HSC/Column3/ReactionsList.lower_selected_item() -func _on_ReactionList_multi_selected(index, selected): - if ($HSC/Column3/ReactionsScroll/ReactionList.is_anything_selected()): - var selection = $HSC/Column3/ReactionsScroll/ReactionList.get_selected_items() - current_reaction = current_option.reactions[selection[0]] +func _on_ReactionsList_multi_selected(item, column, selected): + var selected_reaction = $HSC/Column3/ReactionsList.get_first_selected_metadata() + if (null != selected_reaction): + current_reaction = selected_reaction load_Reaction(current_reaction) func _on_ReactionText_text_changed(): if (null != current_reaction): - var reactionslist = $HSC/Column3/ReactionsScroll/ReactionList current_reaction.set_text($HSC/Column3/ReactionText.text) - var index = current_reaction.get_index() - var text = current_reaction.get_text() - if ("" == text): - reactionslist.set_item_text(index, "[Blank Reaction]") - elif (text.left(50) == text): - reactionslist.set_item_text(index, text) - else: - reactionslist.set_item_text(index, text.left(50) + "...") - reactionslist.set_item_tooltip(index, text) + $HSC/Column3/ReactionsList.refresh() + $HSC/Column3/ReactionsList.select_linked_item(current_reaction) update_wordcount(current_encounter) log_update(current_encounter) @@ -830,31 +629,93 @@ func _on_Trait2Selector_bnumber_property_selected(selected_property): current_reaction.desirability_script.contents.operands[1].set_as_copy_of(selected_property) log_update(current_encounter) +#Reaction list context menu: + +func add_reactions_at_position(reactions_to_add, position): + if (1 == reactions_to_add.size()): + current_option.reactions.insert(position, reactions_to_add.front()) + elif (0 >= position): + reactions_to_add.append_array(current_option.reactions) + current_option.reactions = reactions_to_add + elif (position < current_option.reactions.size()): + var new_array = current_option.reactions.slice(0, (position - 1)) + new_array.append_array(reactions_to_add) + new_array.append_array(current_option.reactions.slice(position, (current_option.reactions.size() - 1))) + current_option.reactions = new_array + elif (position >= current_option.reactions.size()): + current_option.reactions.append_array(reactions_to_add) + +func duplicate_selected_reactions(selected_items): + if (!selected_items.empty()): + var last_reaction_added = null + for reaction in selected_items: + var new_reaction = storyworld.create_new_generic_reaction(current_option) + new_reaction.set_as_copy_of(reaction, false) + new_reaction.option = current_option + current_option.reactions.append(new_reaction) + $HSC/Column3/ReactionsList.items_to_list.append(new_reaction) + $HSC/Column3/ReactionsList.list_item(new_reaction) + last_reaction_added = new_reaction + load_Reaction(last_reaction_added) + $HSC/Column3/ReactionsList.select_only_linked_item(last_reaction_added) + update_wordcount(current_encounter) + log_update(current_encounter) + emit_signal("refresh_graphview") + +func _on_ReactionsList_add_at(index): + var new_reaction = storyworld.create_new_generic_reaction(current_option) + current_option.reactions.insert(index, new_reaction) + refresh_reaction_list() + load_Reaction(new_reaction) + $HSC/Column3/ReactionsList.select_only_linked_item(new_reaction) + update_wordcount(current_encounter) + log_update(current_encounter) + +func _on_ReactionsList_cut(items): + clipboard.cut(items) + +func _on_ReactionsList_copy(items): + clipboard.copy(items) + +func _on_ReactionsList_paste_at(index): + var items_to_add = clipboard.paste() + if (!items_to_add.empty()): + add_reactions_at_position(items_to_add, index) + if (clipboard.clipboard_task_types.CUT == clipboard.clipboard_task): + clipboard.delete_clipped_originals() + refresh_reaction_list() + load_Reaction(items_to_add.front()) + $HSC/Column3/ReactionsList.select_only_linked_item(items_to_add.front()) + update_wordcount(current_encounter) + log_update(current_encounter) + emit_signal("refresh_graphview") + +#Effect editing interface: + func _on_ChangeConsequence_pressed(): if (null != current_reaction and current_reaction is Reaction): $EffectEditor/EffectEditorScreen.storyworld = storyworld $EffectEditor/EffectEditorScreen.reset() $EffectEditor/EffectEditorScreen.load_effect(current_reaction.consequence) - $EffectEditor.popup() + $EffectEditor.popup_centered() func _on_AddEffect_pressed(): if (null != current_reaction): if (null != storyworld and 0 < storyworld.characters.size() and 0 < storyworld.authored_properties.size()): $EffectEditor/EffectEditorScreen.storyworld = storyworld $EffectEditor/EffectEditorScreen.reset() - effect_to_delete = null - $EffectEditor.popup() - else: - print("No reaction currently selected.") + items_to_delete.clear() + $EffectEditor.popup_centered() func _on_EffectEditor_confirmed(): if (null != current_reaction): var new_change = $EffectEditor/EffectEditorScreen.get_effect() if (null != new_change): if (new_change is SWEffect): + new_change.cause = current_reaction var index = -1 - if (null != effect_to_delete): - index = current_reaction.after_effects.find(effect_to_delete) + if (!items_to_delete.empty()): + index = current_reaction.after_effects.find(items_to_delete.front()) if (-1 == index): current_reaction.after_effects.append(new_change) refresh_reaction_after_effects_list() @@ -863,171 +724,118 @@ func _on_EffectEditor_confirmed(): current_reaction.after_effects[index] = new_change refresh_reaction_after_effects_list() log_update(current_encounter) - effect_to_delete = null + items_to_delete.clear() elif (new_change is EventPointer): if (null == new_change.encounter or new_change.encounter is Encounter): current_reaction.consequence = new_change.encounter refresh_reaction_consequence_display() log_update(current_encounter) emit_signal("refresh_graphview") - else: - print("No reaction currently selected.") -func _on_DeleteEffect_pressed(): - var selected_change = $HSC/Column3/AfterReactionEffectsDisplay.get_selected_metadata() - if (null != selected_change and selected_change is SWEffect): - effect_to_delete = selected_change - var dialog_text = "" - dialog_text = "Are you sure you wish to delete the following reaction effect?" - dialog_text += " \"" + selected_change.data_to_string() + "\"" - $ConfirmReactionEffectDeletion.dialog_text = dialog_text - $ConfirmReactionEffectDeletion.popup() - -func _on_ConfirmReactionEffectDeletion_confirmed(): - if (current_reaction.after_effects.has(effect_to_delete)): - current_reaction.after_effects.erase(effect_to_delete) - if (effect_to_delete is SWEffect): - effect_to_delete.clear() - effect_to_delete.call_deferred("free") - log_update(current_encounter) - refresh_reaction_after_effects_list() +func confirm_effect_deletion(effects): + items_to_delete = effects.duplicate() + if (!items_to_delete.empty()): + $ConfirmDeletion/ItemsToDelete.clear() + for each in items_to_delete: + $ConfirmDeletion/ItemsToDelete.add_item(each.data_to_string()) + if (!items_to_delete.empty()): + if (1 == items_to_delete.size()): + $ConfirmDeletion.dialog_text = "Are you sure you wish to delete the following effect?" + else: + $ConfirmDeletion.dialog_text = "Are you sure you wish to delete the following effects?" + $ConfirmDeletion.popup_centered() -func _on_ReactionList_item_rmb_selected(index, at_position): - # Bring up context menu. - var mouse_position = get_global_mouse_position() - var context_menu = $HSC/Column3/ReactionsScroll/ReactionList/ReactionsContextMenu - if ($HSC/Column3/ReactionsScroll/ReactionList.is_anything_selected()): - var text_of_selection = "this." - context_menu.clear() - context_menu.add_item("Add reaction before " + text_of_selection, 0) - context_menu.set_item_metadata((context_menu.get_item_count() - 1), index) - context_menu.add_item("Add reaction after " + text_of_selection, 1) - context_menu.set_item_metadata((context_menu.get_item_count() - 1), index) - context_menu.add_item("Cut", 2) - context_menu.set_item_metadata((context_menu.get_item_count() - 1), index) - context_menu.add_item("Copy", 3) - context_menu.set_item_metadata((context_menu.get_item_count() - 1), index) - context_menu.add_item("Paste before " + text_of_selection, 4) - context_menu.set_item_metadata((context_menu.get_item_count() - 1), index) - context_menu.add_item("Paste after " + text_of_selection, 5) - context_menu.set_item_metadata((context_menu.get_item_count() - 1), index) - context_menu.add_item("Delete", 6) - context_menu.set_item_metadata((context_menu.get_item_count() - 1), index) - context_menu.add_item("Duplicate", 7) - context_menu.set_item_metadata((context_menu.get_item_count() - 1), index) -# context_menu.add_item("Select all", 8) -# context_menu.set_item_metadata((context_menu.get_item_count() - 1), index) - context_menu.popup(Rect2(mouse_position.x, mouse_position.y, context_menu.rect_size.x, context_menu.rect_size.y)) +func _on_DeleteEffect_pressed(): + confirm_effect_deletion($HSC/Column3/AfterReactionEffectsDisplay.get_all_selected_metadata()) -func add_reactions_at_position(reactions_to_add, position): - if (0 == reactions_to_add.size()): +func _on_AfterReactionEffectsDisplay_moved_item(item, from_index, to_index): + if (null == current_reaction): + refresh_reaction_after_effects_list() return - var copies_to_add = [] - for object in reactions_to_add: - var copy = storyworld.create_new_generic_reaction(current_option) - copy.set_as_copy_of(object, false) - copy.option = current_option - copies_to_add.append(copy) - if (1 == copies_to_add.size()): - current_option.reactions.insert(position, copies_to_add[0]) - elif (0 >= position): - copies_to_add.append_array(current_option.reactions) - current_option.reactions = copies_to_add - elif (position < current_option.reactions.size()): - var new_array = current_option.reactions.slice(0, (position - 1)) - new_array.append_array(copies_to_add) - new_array.append_array(current_option.reactions.slice(position, (current_option.reactions.size() - 1))) - current_option.reactions = new_array - elif (position >= current_option.reactions.size()): - current_option.reactions.append_array(copies_to_add) - refresh_reaction_list() - if (0 < current_option.reactions.size()): - if (0 < copies_to_add.size()): - load_Reaction(copies_to_add[0]) - $HSC/Column3/ReactionsScroll/ReactionList.select(copies_to_add[0].get_index()) - else: - load_Reaction(current_option.reactions[0]) - $HSC/Column3/ReactionsScroll/ReactionList.select(current_option.reactions[0].get_index()) + var effect = current_reaction.after_effects.pop_at(from_index) + if (to_index > from_index): + to_index = to_index - 1 + if (to_index < current_reaction.after_effects.size()): + current_reaction.after_effects.insert(to_index, effect) else: - load_Reaction(null) - update_wordcount(current_encounter) - log_update(current_encounter) - emit_signal("refresh_graphview") + current_reaction.after_effects.append(effect) -func duplicate_selected_reactions(): - if ($HSC/Column3/ReactionsScroll/ReactionList.is_anything_selected()): - var last_reaction_added = null - var selection = $HSC/Column3/ReactionsScroll/ReactionList.get_selected_items() - for each in selection: - var reaction = $HSC/Column3/ReactionsScroll/ReactionList.get_item_metadata(each) - var new_reaction = storyworld.create_new_generic_reaction(current_option) - new_reaction.set_as_copy_of(reaction, false) - new_reaction.option = current_option - current_option.reactions.append(new_reaction) - list_reaction(new_reaction) - last_reaction_added = new_reaction - load_Reaction(last_reaction_added) +func _on_MoveEffectUpButton_pressed(): + $HSC/Column3/AfterReactionEffectsDisplay.raise_selected_item() + +func _on_MoveEffectDownButton_pressed(): + $HSC/Column3/AfterReactionEffectsDisplay.lower_selected_item() + +func _on_AfterReactionEffectsDisplay_item_activated(): + if (null != current_reaction): + if (null != storyworld): + $EffectEditor/EffectEditorScreen.storyworld = storyworld + $EffectEditor/EffectEditorScreen.reset() + var effect = $HSC/Column3/AfterReactionEffectsDisplay.get_first_selected_metadata() + $EffectEditor/EffectEditorScreen.load_effect(effect) + items_to_delete.clear() + items_to_delete.append(effect) + $EffectEditor.popup_centered() + +#Effect list context menu: + +func add_effects_at_position(effects_to_add, position): + if (1 == effects_to_add.size()): + current_reaction.after_effects.insert(position, effects_to_add.front()) + elif (0 >= position): + effects_to_add.append_array(current_reaction.after_effects) + current_reaction.after_effects = effects_to_add + elif (position < current_reaction.after_effects.size()): + var new_array = current_reaction.after_effects.slice(0, (position - 1)) + new_array.append_array(effects_to_add) + new_array.append_array(current_reaction.after_effects.slice(position, (current_reaction.after_effects.size() - 1))) + current_reaction.after_effects = new_array + elif (position >= current_reaction.after_effects.size()): + current_reaction.after_effects.append_array(effects_to_add) + +func duplicate_selected_effects(selected_items): + if (!selected_items.empty()): + for item in selected_items: + var change_made = false + if (item is BNumberEffect): + var copy = BNumberEffect.new() + copy.set_as_copy_of(item) + copy.cause = current_reaction + current_reaction.after_effects.append(copy) + $HSC/Column3/AfterReactionEffectsDisplay.items_to_list.append(copy) + $HSC/Column3/AfterReactionEffectsDisplay.list_item(copy) + change_made = true + elif (item is SpoolEffect): + var copy = SpoolEffect.new() + copy.set_as_copy_of(item) + copy.cause = current_reaction + current_reaction.after_effects.append(copy) + $HSC/Column3/AfterReactionEffectsDisplay.items_to_list.append(copy) + $HSC/Column3/AfterReactionEffectsDisplay.list_item(copy) + change_made = true + if (change_made): + log_update(current_encounter) + +func _on_AfterReactionEffectsDisplay_add_at(index): + pass # To do: let authors create new effects that are inserted into the effects list in a specified location upon being created. + +func _on_AfterReactionEffectsDisplay_cut(items): + clipboard.cut(items) + +func _on_AfterReactionEffectsDisplay_copy(items): + clipboard.copy(items) + +func _on_AfterReactionEffectsDisplay_paste_at(index): + var items_to_paste = clipboard.paste() + if (!items_to_paste.empty()): + add_effects_at_position(items_to_paste, index) + if (clipboard.clipboard_task_types.CUT == clipboard.clipboard_task): + clipboard.delete_clipped_originals() + refresh_reaction_after_effects_list() update_wordcount(current_encounter) log_update(current_encounter) - emit_signal("refresh_graphview") -func add_selected_reactions_to_clipboard(): - if ($HSC/Column3/ReactionsScroll/ReactionList.is_anything_selected()): - var selection = $HSC/Column3/ReactionsScroll/ReactionList.get_selected_items() - for each in selection: - var reaction = $HSC/Column3/ReactionsScroll/ReactionList.get_item_metadata(each) - var new_reaction = storyworld.create_new_generic_reaction(current_option) - new_reaction.set_as_copy_of(reaction, false) - clipboard.append(new_reaction) - clipped_originals.append(reaction) - -func _on_ReactionsContextMenu_id_pressed(id): - var item_index = $HSC/Column3/ReactionsScroll/ReactionList/ReactionsContextMenu.get_item_metadata(id) - match id: - 0: - #Add new reaction before - var new_reaction = storyworld.create_new_generic_reaction(current_option) - add_reactions_at_position([new_reaction], item_index) - print ("Adding new reaction before the selected one.") - 1: - #Add new reaction after - var new_reaction = storyworld.create_new_generic_reaction(current_option) - add_reactions_at_position([new_reaction], item_index + 1) - print ("Adding new reaction after the selected one.") - 2: - #Cut - clipboard = [] - clipped_originals = [] - add_selected_reactions_to_clipboard() - clipboard_task = clipboard_task_types.CUT - print ("Cutting selected reactions for pasting.") - 3: - #Copy - clipboard = [] - clipped_originals = [] - add_selected_reactions_to_clipboard() - clipboard_task = clipboard_task_types.COPY - print ("Copying selected reactions.") - 4: - #Paste before - add_reactions_at_position(clipboard, item_index) - if (clipboard_task_types.CUT == clipboard_task): - delete_clipped_originals() - print ("Pasting before selected reactions.") - 5: - #Paste after - add_reactions_at_position(clipboard, item_index + 1) - if (clipboard_task_types.CUT == clipboard_task): - delete_clipped_originals() - print ("Pasting after selected reactions.") - 6: - #Delete - _on_DeleteReaction_pressed() - print ("Asking for confirmation for possible deletion of reactions.") - 7: - #Duplicate - duplicate_selected_reactions() - print ("Duplicating selected reactions.") +#General: func update_wordcount(encounter): #In order to try to avoid sluggishness, we only do this if sort_by is set to word count or rev. word count. @@ -1041,6 +849,12 @@ func update_wordcount(encounter): func _ready(): if (0 < $Column1/SortMenu.get_item_count()): $Column1/SortMenu.select(0) + $HSC/Column2/OptionsList.context_menu_enabled = true + $HSC/Column2/OptionsList.item_type = "option" + $HSC/Column3/ReactionsList.context_menu_enabled = true + $HSC/Column3/ReactionsList.item_type = "reaction" + $HSC/Column3/AfterReactionEffectsDisplay.context_menu_enabled = true + $HSC/Column3/AfterReactionEffectsDisplay.item_type = "effect" #Script Editing: @@ -1051,9 +865,7 @@ func _on_EditEncounterAcceptabilityScriptButton_pressed(): $ScriptEditWindow/ScriptEditScreen.script_to_edit = current_encounter.acceptability_script $ScriptEditWindow/ScriptEditScreen.allow_root_character_editing = true $ScriptEditWindow/ScriptEditScreen.refresh_script_display() - $ScriptEditWindow.popup() - else: - print("You must open an encounter before you can edit its settings.") + $ScriptEditWindow.popup_centered() func _on_EditEncounterDesirabilityScriptButton_pressed(): if (null != current_encounter and current_encounter is Encounter): @@ -1062,9 +874,7 @@ func _on_EditEncounterDesirabilityScriptButton_pressed(): $ScriptEditWindow/ScriptEditScreen.script_to_edit = current_encounter.desirability_script $ScriptEditWindow/ScriptEditScreen.allow_root_character_editing = true $ScriptEditWindow/ScriptEditScreen.refresh_script_display() - $ScriptEditWindow.popup() - else: - print("You must open an encounter before you can edit its settings.") + $ScriptEditWindow.popup_centered() func _on_ARDSEButton_pressed(): var title = current_reaction.get_truncated_text(40) @@ -1074,7 +884,7 @@ func _on_ARDSEButton_pressed(): $ScriptEditWindow/ScriptEditScreen.script_to_edit = current_reaction.desirability_script $ScriptEditWindow/ScriptEditScreen.allow_root_character_editing = true $ScriptEditWindow/ScriptEditScreen.refresh_script_display() - $ScriptEditWindow.popup() + $ScriptEditWindow.popup_centered() func _on_ScriptEditScreen_sw_script_changed(sw_script): if (current_reaction.desirability_script == sw_script): @@ -1082,32 +892,6 @@ func _on_ScriptEditScreen_sw_script_changed(sw_script): emit_signal("refresh_graphview") log_update(current_encounter) -func _on_AfterReactionEffectsDisplay_moved_item(item, from_index, to_index): - if (null == current_reaction): - refresh_reaction_after_effects_list() - return - var effect = current_reaction.after_effects.pop_at(from_index) - print(effect.data_to_string()) - print(str(current_reaction.after_effects.size())) - if (to_index > from_index): - to_index = to_index - 1 - if (to_index < current_reaction.after_effects.size()): - current_reaction.after_effects.insert(to_index, effect) - else: - current_reaction.after_effects.append(effect) - -func _on_AfterReactionEffectsDisplay_item_activated(): - if (null != current_reaction): - if (null != storyworld): - $EffectEditor/EffectEditorScreen.storyworld = storyworld - $EffectEditor/EffectEditorScreen.reset() - var effect = $HSC/Column3/AfterReactionEffectsDisplay.get_selected_metadata() - $EffectEditor/EffectEditorScreen.load_effect(effect) - effect_to_delete = effect - $EffectEditor.popup() - else: - print("No reaction currently selected.") - func _on_EditOptionVisibilityScriptButton_pressed(): if (null != current_option and current_option is Option): var title = current_option.get_truncated_text(40) @@ -1117,7 +901,7 @@ func _on_EditOptionVisibilityScriptButton_pressed(): $ScriptEditWindow/ScriptEditScreen.script_to_edit = current_option.visibility_script $ScriptEditWindow/ScriptEditScreen.allow_root_character_editing = true $ScriptEditWindow/ScriptEditScreen.refresh_script_display() - $ScriptEditWindow.popup() + $ScriptEditWindow.popup_centered() func _on_EditOptionPerformabilityScriptButton_pressed(): if (null != current_option and current_option is Option): @@ -1128,7 +912,7 @@ func _on_EditOptionPerformabilityScriptButton_pressed(): $ScriptEditWindow/ScriptEditScreen.script_to_edit = current_option.performability_script $ScriptEditWindow/ScriptEditScreen.allow_root_character_editing = true $ScriptEditWindow/ScriptEditScreen.refresh_script_display() - $ScriptEditWindow.popup() + $ScriptEditWindow.popup_centered() #GUI Themes: @@ -1147,29 +931,33 @@ func set_gui_theme(theme_name, background_color): "Clarity": $Column1/HBC/AddButton.icon = add_icon_dark $Column1/HBC/DeleteButton.icon = delete_icon_dark - $HSC/Column2/HBCTurn2/AddOption.icon = add_icon_dark - $HSC/Column2/HBCTurn2/DeleteOption.icon = delete_icon_dark - $HSC/Column2/HBCTurn2/MoveOptionUpButton.icon = move_up_icon_dark - $HSC/Column2/HBCTurn2/MoveOptionDownButton.icon = move_down_icon_dark + $HSC/Column2/HBCOptionButtons/AddOption.icon = add_icon_dark + $HSC/Column2/HBCOptionButtons/DeleteOption.icon = delete_icon_dark + $HSC/Column2/HBCOptionButtons/MoveOptionUpButton.icon = move_up_icon_dark + $HSC/Column2/HBCOptionButtons/MoveOptionDownButton.icon = move_down_icon_dark $HSC/Column3/HBC/AddReaction.icon = add_icon_dark $HSC/Column3/HBC/DeleteReaction.icon = delete_icon_dark $HSC/Column3/HBC/MoveReactionUpButton.icon = move_up_icon_dark $HSC/Column3/HBC/MoveReactionDownButton.icon = move_down_icon_dark $HSC/Column3/HBCEffectButtons/AddEffect.icon = add_icon_dark $HSC/Column3/HBCEffectButtons/DeleteEffect.icon = delete_icon_dark + $HSC/Column3/HBCEffectButtons/MoveEffectUpButton.icon = move_up_icon_dark + $HSC/Column3/HBCEffectButtons/MoveEffectDownButton.icon = move_down_icon_dark "Lapis Lazuli": $Column1/HBC/AddButton.icon = add_icon_light $Column1/HBC/DeleteButton.icon = delete_icon_light - $HSC/Column2/HBCTurn2/AddOption.icon = add_icon_light - $HSC/Column2/HBCTurn2/DeleteOption.icon = delete_icon_light - $HSC/Column2/HBCTurn2/MoveOptionUpButton.icon = move_up_icon_light - $HSC/Column2/HBCTurn2/MoveOptionDownButton.icon = move_down_icon_light + $HSC/Column2/HBCOptionButtons/AddOption.icon = add_icon_light + $HSC/Column2/HBCOptionButtons/DeleteOption.icon = delete_icon_light + $HSC/Column2/HBCOptionButtons/MoveOptionUpButton.icon = move_up_icon_light + $HSC/Column2/HBCOptionButtons/MoveOptionDownButton.icon = move_down_icon_light $HSC/Column3/HBC/AddReaction.icon = add_icon_light $HSC/Column3/HBC/DeleteReaction.icon = delete_icon_light $HSC/Column3/HBC/MoveReactionUpButton.icon = move_up_icon_light $HSC/Column3/HBC/MoveReactionDownButton.icon = move_down_icon_light $HSC/Column3/HBCEffectButtons/AddEffect.icon = add_icon_light $HSC/Column3/HBCEffectButtons/DeleteEffect.icon = delete_icon_light + $HSC/Column3/HBCEffectButtons/MoveEffectUpButton.icon = move_up_icon_light + $HSC/Column3/HBCEffectButtons/MoveEffectDownButton.icon = move_down_icon_light $HSC/Column3/HBCLSL/BlendWeightSelector.set_gui_theme(theme_name, background_color) $EffectEditor/EffectEditorScreen.set_gui_theme(theme_name, background_color) $ScriptEditWindow/ScriptEditScreen.set_gui_theme(theme_name, background_color) diff --git a/godot/EncounterEditScreen.tscn b/godot/EncounterEditScreen.tscn index 335384f..a6fb08f 100644 --- a/godot/EncounterEditScreen.tscn +++ b/godot/EncounterEditScreen.tscn @@ -123,7 +123,7 @@ caret_blink_speed = 0.5 [node name="EncounterMainTextEdit" type="TextEdit" parent="HSC/Column2"] margin_top = 28.0 margin_right = 667.0 -margin_bottom = 495.0 +margin_bottom = 467.0 rect_min_size = Vector2( 0, 320 ) size_flags_horizontal = 3 size_flags_vertical = 3 @@ -133,9 +133,9 @@ smooth_scrolling = true wrap_enabled = true [node name="HBCEncounterSettingsButtons" type="HBoxContainer" parent="HSC/Column2"] -margin_top = 499.0 +margin_top = 471.0 margin_right = 667.0 -margin_bottom = 519.0 +margin_bottom = 491.0 alignment = 1 [node name="EditEncounterAcceptabilityScriptButton" type="Button" parent="HSC/Column2/HBCEncounterSettingsButtons"] @@ -150,98 +150,36 @@ margin_right = 561.0 margin_bottom = 20.0 text = "Edit Encounter Desirability Script" -[node name="HBCTurn" type="HBoxContainer" parent="HSC/Column2"] -visible = false -margin_top = 460.0 -margin_right = 578.0 -margin_bottom = 519.0 -size_flags_horizontal = 3 -alignment = 1 - -[node name="VBC" type="VBoxContainer" parent="HSC/Column2/HBCTurn"] -margin_left = 213.0 -margin_right = 287.0 -margin_bottom = 59.0 - -[node name="EarliestTurnLabel" type="Label" parent="HSC/Column2/HBCTurn/VBC"] -margin_right = 74.0 -margin_bottom = 31.0 -text = "Earliest -turn:" - -[node name="EarliestTurn" type="SpinBox" parent="HSC/Column2/HBCTurn/VBC"] -margin_top = 35.0 -margin_right = 74.0 -margin_bottom = 59.0 -rounded = true -allow_greater = true -allow_lesser = true - -[node name="VBC2" type="VBoxContainer" parent="HSC/Column2/HBCTurn"] -margin_left = 291.0 -margin_right = 365.0 -margin_bottom = 59.0 - -[node name="LatestTurnLabel" type="Label" parent="HSC/Column2/HBCTurn/VBC2"] -margin_right = 74.0 -margin_bottom = 31.0 -text = "Latest -turn: " - -[node name="LatestTurn" type="SpinBox" parent="HSC/Column2/HBCTurn/VBC2"] -margin_top = 35.0 -margin_right = 74.0 -margin_bottom = 59.0 -rounded = true -allow_greater = true -allow_lesser = true - -[node name="VBC3" type="VBoxContainer" parent="HSC/Column2/HBCTurn"] -visible = false -margin_left = 329.0 -margin_right = 405.0 -margin_bottom = 59.0 - -[node name="AntagonistPickerLabel" type="Label" parent="HSC/Column2/HBCTurn/VBC3"] -margin_right = 76.0 -margin_bottom = 14.0 -text = "Antagonist: " - -[node name="AntagonistPicker" type="OptionButton" parent="HSC/Column2/HBCTurn/VBC3"] -margin_top = 18.0 -margin_right = 76.0 -margin_bottom = 38.0 - -[node name="HBCTurn2" type="HBoxContainer" parent="HSC/Column2"] -margin_top = 523.0 +[node name="HBCOptionButtons" type="HBoxContainer" parent="HSC/Column2"] +margin_top = 495.0 margin_right = 667.0 -margin_bottom = 553.0 +margin_bottom = 525.0 size_flags_horizontal = 3 -[node name="AddOption" type="Button" parent="HSC/Column2/HBCTurn2"] +[node name="AddOption" type="Button" parent="HSC/Column2/HBCOptionButtons"] margin_right = 36.0 margin_bottom = 30.0 icon = ExtResource( 11 ) -[node name="DeleteOption" type="Button" parent="HSC/Column2/HBCTurn2"] +[node name="DeleteOption" type="Button" parent="HSC/Column2/HBCOptionButtons"] margin_left = 40.0 margin_right = 76.0 margin_bottom = 30.0 icon = ExtResource( 10 ) -[node name="MoveOptionUpButton" type="Button" parent="HSC/Column2/HBCTurn2"] +[node name="MoveOptionUpButton" type="Button" parent="HSC/Column2/HBCOptionButtons"] margin_left = 80.0 margin_right = 116.0 margin_bottom = 30.0 icon = ExtResource( 2 ) -[node name="MoveOptionDownButton" type="Button" parent="HSC/Column2/HBCTurn2"] +[node name="MoveOptionDownButton" type="Button" parent="HSC/Column2/HBCOptionButtons"] margin_left = 120.0 margin_right = 156.0 margin_bottom = 30.0 icon = ExtResource( 3 ) -[node name="Label" type="Label" parent="HSC/Column2/HBCTurn2"] +[node name="Label" type="Label" parent="HSC/Column2/HBCOptionButtons"] margin_left = 160.0 margin_top = 8.0 margin_right = 219.0 @@ -249,26 +187,13 @@ margin_bottom = 22.0 text = "Options: " align = 1 -[node name="OptionsScroll" type="ScrollContainer" parent="HSC/Column2"] -margin_top = 557.0 +[node name="OptionsList" parent="HSC/Column2" instance=ExtResource( 8 )] +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_top = 529.0 margin_right = 667.0 margin_bottom = 657.0 -rect_min_size = Vector2( 264, 100 ) -scroll_horizontal_enabled = false - -[node name="OptionsList" type="ItemList" parent="HSC/Column2/OptionsScroll"] -margin_right = 667.0 -margin_bottom = 100.0 -rect_min_size = Vector2( 264, 100 ) -size_flags_horizontal = 3 -select_mode = 1 -allow_rmb_select = true -max_text_lines = 3 -auto_height = true - -[node name="OptionsContextMenu" type="PopupMenu" parent="HSC/Column2/OptionsScroll/OptionsList"] -margin_right = 20.0 -margin_bottom = 20.0 +rect_min_size = Vector2( 0, 128 ) [node name="OptTxtLabel" type="Label" parent="HSC/Column2"] margin_top = 661.0 @@ -357,38 +282,24 @@ margin_right = 230.0 margin_bottom = 22.0 text = "Reactions: " -[node name="ReactionsScroll" type="ScrollContainer" parent="HSC/Column3"] +[node name="ReactionsList" parent="HSC/Column3" instance=ExtResource( 8 )] +anchor_right = 0.0 +anchor_bottom = 0.0 margin_top = 34.0 margin_right = 668.0 -margin_bottom = 114.0 -rect_min_size = Vector2( 235, 80 ) -scroll_horizontal_enabled = false - -[node name="ReactionList" type="ItemList" parent="HSC/Column3/ReactionsScroll"] -margin_right = 668.0 -margin_bottom = 80.0 -rect_min_size = Vector2( 250, 80 ) -size_flags_horizontal = 3 -size_flags_vertical = 3 -select_mode = 1 -allow_rmb_select = true -max_text_lines = 2 -auto_height = true - -[node name="ReactionsContextMenu" type="PopupMenu" parent="HSC/Column3/ReactionsScroll/ReactionList"] -margin_right = 20.0 -margin_bottom = 20.0 +margin_bottom = 162.0 +rect_min_size = Vector2( 0, 128 ) [node name="Label" type="Label" parent="HSC/Column3"] -margin_top = 118.0 +margin_top = 166.0 margin_right = 668.0 -margin_bottom = 132.0 +margin_bottom = 180.0 text = "Reaction text:" [node name="ReactionText" type="TextEdit" parent="HSC/Column3"] -margin_top = 136.0 +margin_top = 184.0 margin_right = 668.0 -margin_bottom = 339.0 +margin_bottom = 363.0 rect_min_size = Vector2( 0, 100 ) size_flags_horizontal = 3 size_flags_vertical = 3 @@ -396,15 +307,15 @@ syntax_highlighting = true wrap_enabled = true [node name="IncBlendWeightLabel" type="Label" parent="HSC/Column3"] -margin_top = 343.0 +margin_top = 367.0 margin_right = 668.0 -margin_bottom = 357.0 +margin_bottom = 381.0 text = "Reaction desirability:" [node name="HBCLSL" type="HBoxContainer" parent="HSC/Column3"] -margin_top = 361.0 +margin_top = 385.0 margin_right = 668.0 -margin_bottom = 421.0 +margin_bottom = 445.0 alignment = 1 [node name="Label" type="Label" parent="HSC/Column3/HBCLSL"] @@ -432,9 +343,9 @@ text = "Trait align = 1 [node name="HBCTT" type="HBoxContainer" parent="HSC/Column3"] -margin_top = 425.0 +margin_top = 449.0 margin_right = 668.0 -margin_bottom = 457.0 +margin_bottom = 481.0 alignment = 1 [node name="Trait1Selector" parent="HSC/Column3/HBCTT" instance=ExtResource( 5 )] @@ -451,15 +362,15 @@ margin_bottom = 32.0 rect_min_size = Vector2( 0, 32 ) [node name="ARDSEButton" type="Button" parent="HSC/Column3"] -margin_top = 461.0 +margin_top = 485.0 margin_right = 668.0 -margin_bottom = 481.0 +margin_bottom = 505.0 text = "Edit Reaction Desirability Script" [node name="HBCConsequence" type="HBoxContainer" parent="HSC/Column3"] -margin_top = 485.0 +margin_top = 509.0 margin_right = 668.0 -margin_bottom = 485.0 +margin_bottom = 509.0 [node name="ChangeConsequence" type="Button" parent="HSC/Column3/HBCConsequence"] visible = false @@ -469,9 +380,9 @@ hint_tooltip = "This sets the reaction's consequence to the first currently sele text = "Change Consequence:" [node name="HBCEffectButtons" type="HBoxContainer" parent="HSC/Column3"] -margin_top = 489.0 +margin_top = 513.0 margin_right = 668.0 -margin_bottom = 519.0 +margin_bottom = 543.0 __meta__ = { "_edit_use_anchors_": false } @@ -487,10 +398,20 @@ margin_right = 76.0 margin_bottom = 30.0 icon = ExtResource( 10 ) -[node name="ReactionEffectsLabel" type="Label" parent="HSC/Column3/HBCEffectButtons"] +[node name="MoveEffectUpButton" type="Button" parent="HSC/Column3/HBCEffectButtons"] margin_left = 80.0 +margin_right = 92.0 +margin_bottom = 30.0 + +[node name="MoveEffectDownButton" type="Button" parent="HSC/Column3/HBCEffectButtons"] +margin_left = 96.0 +margin_right = 108.0 +margin_bottom = 30.0 + +[node name="ReactionEffectsLabel" type="Label" parent="HSC/Column3/HBCEffectButtons"] +margin_left = 112.0 margin_top = 8.0 -margin_right = 186.0 +margin_right = 218.0 margin_bottom = 22.0 hint_tooltip = "When the selected reaction occurs, the following changes will be made to relationships between non-player characters and the player character." mouse_filter = 1 @@ -499,7 +420,7 @@ text = "Reaction effects:" [node name="AfterReactionEffectsDisplay" parent="HSC/Column3" instance=ExtResource( 8 )] anchor_right = 0.0 anchor_bottom = 0.0 -margin_top = 523.0 +margin_top = 547.0 margin_right = 668.0 margin_bottom = 727.0 rect_min_size = Vector2( 0, 50 ) @@ -526,7 +447,7 @@ margin_top = 8.0 margin_right = -8.0 margin_bottom = -36.0 -[node name="ConfirmEncounterDeletion" type="ConfirmationDialog" parent="."] +[node name="ConfirmDeletion" type="ConfirmationDialog" parent="."] margin_right = 256.0 margin_bottom = 200.0 rect_min_size = Vector2( 200, 100 ) @@ -534,27 +455,12 @@ resizable = true dialog_text = "Are you sure you want to delete these encounters?" dialog_autowrap = true -[node name="EncountersToDelete" type="ItemList" parent="ConfirmEncounterDeletion"] +[node name="ItemsToDelete" type="ItemList" parent="ConfirmDeletion"] margin_left = 8.0 margin_top = 39.0 margin_right = 248.0 margin_bottom = 164.0 -[node name="ConfirmOptionDeletion" type="ConfirmationDialog" parent="."] -margin_right = 200.0 -margin_bottom = 70.0 -dialog_autowrap = true - -[node name="ConfirmReactionDeletion" type="ConfirmationDialog" parent="."] -margin_right = 200.0 -margin_bottom = 70.0 -dialog_autowrap = true - -[node name="ConfirmReactionEffectDeletion" type="ConfirmationDialog" parent="."] -margin_right = 200.0 -margin_bottom = 70.0 -dialog_autowrap = true - [node name="CannotDelete" type="AcceptDialog" parent="."] margin_right = 160.0 margin_bottom = 58.0 @@ -584,16 +490,18 @@ margin_bottom = -36.0 [connection signal="text_changed" from="HSC/Column2/EncounterMainTextEdit" to="." method="_on_EncounterMainTextEdit_text_changed"] [connection signal="pressed" from="HSC/Column2/HBCEncounterSettingsButtons/EditEncounterAcceptabilityScriptButton" to="." method="_on_EditEncounterAcceptabilityScriptButton_pressed"] [connection signal="pressed" from="HSC/Column2/HBCEncounterSettingsButtons/EditEncounterDesirabilityScriptButton" to="." method="_on_EditEncounterDesirabilityScriptButton_pressed"] -[connection signal="value_changed" from="HSC/Column2/HBCTurn/VBC/EarliestTurn" to="." method="_on_EarliestTurn_value_changed"] -[connection signal="value_changed" from="HSC/Column2/HBCTurn/VBC2/LatestTurn" to="." method="_on_LatestTurn_value_changed"] -[connection signal="pressed" from="HSC/Column2/HBCTurn2/AddOption" to="." method="_on_AddOption_pressed"] -[connection signal="pressed" from="HSC/Column2/HBCTurn2/DeleteOption" to="." method="_on_DeleteOption_pressed"] -[connection signal="pressed" from="HSC/Column2/HBCTurn2/MoveOptionUpButton" to="." method="_on_MoveOptionUpButton_pressed"] -[connection signal="pressed" from="HSC/Column2/HBCTurn2/MoveOptionDownButton" to="." method="_on_MoveOptionDownButton_pressed"] -[connection signal="item_rmb_selected" from="HSC/Column2/OptionsScroll/OptionsList" to="." method="_on_OptionsList_item_rmb_selected"] -[connection signal="item_selected" from="HSC/Column2/OptionsScroll/OptionsList" to="." method="_on_OptionsList_item_selected"] -[connection signal="multi_selected" from="HSC/Column2/OptionsScroll/OptionsList" to="." method="_on_OptionsList_multi_selected"] -[connection signal="id_pressed" from="HSC/Column2/OptionsScroll/OptionsList/OptionsContextMenu" to="." method="_on_OptionsContextMenu_id_pressed"] +[connection signal="pressed" from="HSC/Column2/HBCOptionButtons/AddOption" to="." method="_on_AddOption_pressed"] +[connection signal="pressed" from="HSC/Column2/HBCOptionButtons/DeleteOption" to="." method="_on_DeleteOption_pressed"] +[connection signal="pressed" from="HSC/Column2/HBCOptionButtons/MoveOptionUpButton" to="." method="_on_MoveOptionUpButton_pressed"] +[connection signal="pressed" from="HSC/Column2/HBCOptionButtons/MoveOptionDownButton" to="." method="_on_MoveOptionDownButton_pressed"] +[connection signal="add_at" from="HSC/Column2/OptionsList" to="." method="_on_OptionsList_add_at"] +[connection signal="copy" from="HSC/Column2/OptionsList" to="." method="_on_OptionsList_copy"] +[connection signal="cut" from="HSC/Column2/OptionsList" to="." method="_on_OptionsList_cut"] +[connection signal="delete" from="HSC/Column2/OptionsList" to="." method="confirm_option_deletion"] +[connection signal="duplicate" from="HSC/Column2/OptionsList" to="." method="duplicate_selected_options"] +[connection signal="moved_item" from="HSC/Column2/OptionsList" to="." method="_on_OptionsList_moved_item"] +[connection signal="multi_selected" from="HSC/Column2/OptionsList" to="." method="_on_OptionsList_multi_selected"] +[connection signal="paste_at" from="HSC/Column2/OptionsList" to="." method="_on_OptionsList_paste_at"] [connection signal="text_changed" from="HSC/Column2/OptionText" to="." method="_on_OptionText_text_changed"] [connection signal="pressed" from="HSC/Column2/OptionSettingsButton" to="." method="_on_OptionSettingsButton_pressed"] [connection signal="pressed" from="HSC/Column2/HBCOptionSettingsButtons/EditOptionVisibilityScriptButton" to="." method="_on_EditOptionVisibilityScriptButton_pressed"] @@ -602,10 +510,14 @@ margin_bottom = -36.0 [connection signal="pressed" from="HSC/Column3/HBC/DeleteReaction" to="." method="_on_DeleteReaction_pressed"] [connection signal="pressed" from="HSC/Column3/HBC/MoveReactionUpButton" to="." method="_on_MoveReactionUpButton_pressed"] [connection signal="pressed" from="HSC/Column3/HBC/MoveReactionDownButton" to="." method="_on_MoveReactionDownButton_pressed"] -[connection signal="item_rmb_selected" from="HSC/Column3/ReactionsScroll/ReactionList" to="." method="_on_ReactionList_item_rmb_selected"] -[connection signal="item_selected" from="HSC/Column3/ReactionsScroll/ReactionList" to="." method="_on_ReactionList_item_selected"] -[connection signal="multi_selected" from="HSC/Column3/ReactionsScroll/ReactionList" to="." method="_on_ReactionList_multi_selected"] -[connection signal="id_pressed" from="HSC/Column3/ReactionsScroll/ReactionList/ReactionsContextMenu" to="." method="_on_ReactionsContextMenu_id_pressed"] +[connection signal="add_at" from="HSC/Column3/ReactionsList" to="." method="_on_ReactionsList_add_at"] +[connection signal="copy" from="HSC/Column3/ReactionsList" to="." method="_on_ReactionsList_copy"] +[connection signal="cut" from="HSC/Column3/ReactionsList" to="." method="_on_ReactionsList_cut"] +[connection signal="delete" from="HSC/Column3/ReactionsList" to="." method="confirm_reaction_deletion"] +[connection signal="duplicate" from="HSC/Column3/ReactionsList" to="." method="duplicate_selected_reactions"] +[connection signal="moved_item" from="HSC/Column3/ReactionsList" to="." method="_on_ReactionsList_moved_item"] +[connection signal="multi_selected" from="HSC/Column3/ReactionsList" to="." method="_on_ReactionsList_multi_selected"] +[connection signal="paste_at" from="HSC/Column3/ReactionsList" to="." method="_on_ReactionsList_paste_at"] [connection signal="text_changed" from="HSC/Column3/ReactionText" to="." method="_on_ReactionText_text_changed"] [connection signal="bnumber_value_changed" from="HSC/Column3/HBCLSL/BlendWeightSelector" to="." method="_on_BlendWeightSelector_bnumber_value_changed"] [connection signal="bnumber_property_selected" from="HSC/Column3/HBCTT/Trait1Selector" to="." method="_on_Trait1Selector_bnumber_property_selected"] @@ -614,11 +526,16 @@ margin_bottom = -36.0 [connection signal="pressed" from="HSC/Column3/HBCConsequence/ChangeConsequence" to="." method="_on_ChangeConsequence_pressed"] [connection signal="pressed" from="HSC/Column3/HBCEffectButtons/AddEffect" to="." method="_on_AddEffect_pressed"] [connection signal="pressed" from="HSC/Column3/HBCEffectButtons/DeleteEffect" to="." method="_on_DeleteEffect_pressed"] +[connection signal="pressed" from="HSC/Column3/HBCEffectButtons/MoveEffectUpButton" to="." method="_on_MoveEffectUpButton_pressed"] +[connection signal="pressed" from="HSC/Column3/HBCEffectButtons/MoveEffectDownButton" to="." method="_on_MoveEffectDownButton_pressed"] +[connection signal="add_at" from="HSC/Column3/AfterReactionEffectsDisplay" to="." method="_on_AfterReactionEffectsDisplay_add_at"] +[connection signal="copy" from="HSC/Column3/AfterReactionEffectsDisplay" to="." method="_on_AfterReactionEffectsDisplay_copy"] +[connection signal="cut" from="HSC/Column3/AfterReactionEffectsDisplay" to="." method="_on_AfterReactionEffectsDisplay_cut"] +[connection signal="delete" from="HSC/Column3/AfterReactionEffectsDisplay" to="." method="confirm_effect_deletion"] +[connection signal="duplicate" from="HSC/Column3/AfterReactionEffectsDisplay" to="." method="duplicate_selected_effects"] [connection signal="item_activated" from="HSC/Column3/AfterReactionEffectsDisplay" to="." method="_on_AfterReactionEffectsDisplay_item_activated"] [connection signal="moved_item" from="HSC/Column3/AfterReactionEffectsDisplay" to="." method="_on_AfterReactionEffectsDisplay_moved_item"] +[connection signal="paste_at" from="HSC/Column3/AfterReactionEffectsDisplay" to="." method="_on_AfterReactionEffectsDisplay_paste_at"] [connection signal="confirmed" from="EffectEditor" to="." method="_on_EffectEditor_confirmed"] -[connection signal="confirmed" from="ConfirmEncounterDeletion" to="." method="_on_ConfirmEncounterDeletion_confirmed"] -[connection signal="confirmed" from="ConfirmOptionDeletion" to="." method="_on_ConfirmOptionDeletion_confirmed"] -[connection signal="confirmed" from="ConfirmReactionDeletion" to="." method="_on_ConfirmReactionDeletion_confirmed"] -[connection signal="confirmed" from="ConfirmReactionEffectDeletion" to="." method="_on_ConfirmReactionEffectDeletion_confirmed"] +[connection signal="confirmed" from="ConfirmDeletion" to="." method="_on_ConfirmDeletion_confirmed"] [connection signal="sw_script_changed" from="ScriptEditWindow/ScriptEditScreen" to="." method="_on_ScriptEditScreen_sw_script_changed"] diff --git a/godot/EncounterOverviewScreen.gd b/godot/EncounterOverviewScreen.gd index 2cbe1e1..d63065d 100644 --- a/godot/EncounterOverviewScreen.gd +++ b/godot/EncounterOverviewScreen.gd @@ -70,6 +70,7 @@ func refresh(): table_of_encounters.clear() var root = table_of_encounters.create_item() root.set_text(0, "Encounters: ") + var even = false for encounter in storyworld.encounters: if ("" == searchterm or encounter.has_search_text(searchterm)): var entry = table_of_encounters.create_item(root) @@ -118,6 +119,16 @@ func refresh(): entry.set_text(5, spool_names) #Word Count: entry.set_text(6, str(encounter.wordcount())) + #Set even rows to have different color: + if (even): + entry.set_custom_bg_color(0, Color(0.235294, 0.470588, 0.941176, 0.392157)) + entry.set_custom_bg_color(1, Color(0.235294, 0.470588, 0.941176, 0.392157)) + entry.set_custom_bg_color(2, Color(0.235294, 0.470588, 0.941176, 0.392157)) + entry.set_custom_bg_color(3, Color(0.235294, 0.470588, 0.941176, 0.392157)) + entry.set_custom_bg_color(4, Color(0.235294, 0.470588, 0.941176, 0.392157)) + entry.set_custom_bg_color(5, Color(0.235294, 0.470588, 0.941176, 0.392157)) + entry.set_custom_bg_color(6, Color(0.235294, 0.470588, 0.941176, 0.392157)) + even = !even func _on_SortMenu_item_selected(index): refresh() @@ -154,7 +165,7 @@ func _on_DeleteEncounterButton_pressed(): for each in encounters_to_delete: $ConfirmEncounterDeletion/EncountersToDelete.add_item(each.title) $ConfirmEncounterDeletion.dialog_text = dialog_text - $ConfirmEncounterDeletion.popup() + $ConfirmEncounterDeletion.popup_centered() func _on_ConfirmEncounterDeletion_confirmed(): for each in encounters_to_delete: diff --git a/godot/EncounterOverviewScreen.tscn b/godot/EncounterOverviewScreen.tscn index a231667..2ff456e 100644 --- a/godot/EncounterOverviewScreen.tscn +++ b/godot/EncounterOverviewScreen.tscn @@ -93,6 +93,7 @@ margin_top = 34.0 margin_right = 1366.0 margin_bottom = 736.0 size_flags_vertical = 3 +custom_constants/hseparation = 0 columns = 7 column_titles_visible = true hide_root = true diff --git a/godot/FileMenu.gd b/godot/FileMenu.gd index cfbd81f..1253c40 100644 --- a/godot/FileMenu.gd +++ b/godot/FileMenu.gd @@ -6,7 +6,6 @@ func _ready(): get_popup().add_item("New Storyworld") get_popup().add_item("Open") # get_popup().add_item("Import from Storyworld") -# get_popup().add_item("Import from XML") get_popup().add_item("Save") get_popup().add_item("Save As") get_popup().add_item("Compile to HTML") diff --git a/godot/GUI.gd b/godot/GUI.gd index 99eef44..11c3945 100644 --- a/godot/GUI.gd +++ b/godot/GUI.gd @@ -4,8 +4,9 @@ var current_project_path = "" var current_html_template_path = "res://custom_resources/encounter_engine.html" var open_after_compiling = false -var sweepweave_version_number = "0.0.37" +var sweepweave_version_number = "0.0.38" var storyworld = null +var clipboard = Clipboard.new() #Theme variables: var theme_background_colors = {} @@ -22,6 +23,7 @@ func on_character_name_changed(character): #File Management func load_project(file_text): + clipboard.clear() storyworld.load_from_json(file_text) storyworld.sweepweave_version_number = sweepweave_version_number $Background/VBC/EditorTabs/Encounters.refresh_encounter_list() @@ -30,13 +32,13 @@ func load_project(file_text): $Background/VBC/EditorTabs/Encounters.load_and_focus_first_encounter() $Background/VBC/EditorTabs/Characters.refresh_character_list() if (0 < storyworld.characters.size()): - $Background/VBC/EditorTabs/Characters.load_character(storyworld.characters[0]) + $Background/VBC/EditorTabs/Characters.load_character(storyworld.characters.front()) $Background/VBC/EditorTabs/Spools.refresh() $Background/VBC/EditorTabs/Settings.refresh() $Background/VBC/EditorTabs/GraphView.refresh_graphview() $Background/VBC/EditorTabs/PersonalityModel.refresh_property_list() if (0 < storyworld.authored_properties.size()): - $Background/VBC/EditorTabs/PersonalityModel.load_authored_property(storyworld.authored_properties[0]) + $Background/VBC/EditorTabs/PersonalityModel.load_authored_property(storyworld.authored_properties.front()) $Background/VBC/EditorTabs/Overview.refresh() $Background/VBC/EditorTabs/Play.clear() $StoryworldTroubleshooting/StoryworldValidationInterface.refresh() @@ -49,11 +51,6 @@ func save_project(save_as = false): OS.set_window_title("SweepWeave - " + storyworld.storyworld_title) $Background/VBC/EditorTabs/Encounters.refresh_encounter_list() -# Functions to import from Chris Crawford's XML format - -#func _on_ImportXMLFileDialog_file_selected(path): -# pass # - # On Startup func new_storyworld(): @@ -69,9 +66,11 @@ func new_storyworld(): $Background/VBC/EditorTabs/Play.reference_storyworld = storyworld $Background/VBC/EditorTabs/PersonalityModel.storyworld = storyworld $StoryworldTroubleshooting/StoryworldValidationInterface.storyworld = storyworld + clipboard.storyworld = storyworld else: storyworld.clear() storyworld.sweepweave_version_number = sweepweave_version_number + clipboard.clear() #Initiate personality / relationship model. storyworld.init_classical_personality_model() #Add at least one character to the storyworld. @@ -124,7 +123,9 @@ func _ready(): $Background/VBC/MenuBar/ViewMenu.connect("menu_input", self, "_on_viewmenu_item_toggled") $Background/VBC/MenuBar/HelpMenu.get_popup().connect("id_pressed", self, "_on_helpmenu_item_pressed") $About/VBC/VersionMessage.text = "SweepWeave v." + sweepweave_version_number -# $Background/VBC/EditorTabs/Play.connect("encounter_loaded", self, "load_Encounter_by_id") + $CheckForUpdates/UpdateScreen/VBC/VersionMessage.text = "Current SweepWeave version: " + sweepweave_version_number + $CheckForUpdates/UpdateScreen.sweepweave_version_number = sweepweave_version_number + $Background/VBC/EditorTabs/Play.connect("encounter_edit_button_pressed", self, "display_encounter_by_id") $Background/VBC/EditorTabs/Characters.connect("new_character_created", $Background/VBC/EditorTabs/Encounters, "add_character_to_lists") $Background/VBC/EditorTabs/Characters.connect("character_deleted", $Background/VBC/EditorTabs/Encounters, "replace_character") $Background/VBC/EditorTabs/Characters.connect("character_name_changed", self, "on_character_name_changed") @@ -144,6 +145,8 @@ func _ready(): $Background/VBC/EditorTabs/PersonalityModel.connect("refresh_authored_property_lists", $Background/VBC/EditorTabs/Characters, "refresh_property_list") $Background/VBC/EditorTabs/PersonalityModel.connect("refresh_authored_property_lists", $Background/VBC/EditorTabs/Encounters, "refresh_bnumber_property_lists") $Background/VBC/EditorTabs.set_current_tab(1) + #Initialize clipboard: + $Background/VBC/EditorTabs/Encounters.set_clipboard(clipboard) #Set GUI theme variables: theme_background_colors["Clarity"] = Color(0.882353, 0.882353, 0.882353) theme_background_colors["Lapis Lazuli"] = Color(0, 0.062745, 0.12549) @@ -154,7 +157,7 @@ func _ready(): func _notification(what): if (what == MainLoop.NOTIFICATION_WM_QUIT_REQUEST): if(false == storyworld.project_saved): - $ConfirmQuit.popup() + $ConfirmQuit.popup_centered() else: get_tree().quit() @@ -166,27 +169,27 @@ func _input(event): #This check must come before the Control + S check, otherwise Control + S will take precedence. print("Control + Alt + S pressed") $SaveAsFileDialog.invalidate() - $SaveAsFileDialog.popup() + $SaveAsFileDialog.popup_centered() elif event.is_action_pressed("project_save_overwrite"): print("Control + S pressed") if ("" != current_project_path): save_project() else: $SaveAsFileDialog.invalidate() - $SaveAsFileDialog.popup() + $SaveAsFileDialog.popup_centered() elif event.is_action_pressed("project_new"): print("Control + N pressed") if(false == storyworld.project_saved): - $ConfirmNewStoryworld.popup() + $ConfirmNewStoryworld.popup_centered() else: new_storyworld() elif event.is_action_pressed("project_load"): print("Control + O pressed") if(false == storyworld.project_saved): - $ConfirmOpenWhenUnsaved.popup() + $ConfirmOpenWhenUnsaved.popup_centered() else: $LoadFileDialog.invalidate() - $LoadFileDialog.popup() + $LoadFileDialog.popup_centered() func log_update(encounter = null): #If encounter == wild_encounter, then the project as a whole is being updated, rather than a specific encounter, or an encounter has been added, deleted, or duplicated. @@ -200,40 +203,38 @@ func _on_filemenu_item_pressed(id): var item_name = $Background/VBC/MenuBar/FileMenu.get_popup().get_item_text(id) if ("New Storyworld" == item_name): if(false == storyworld.project_saved): - $ConfirmNewStoryworld.popup() + $ConfirmNewStoryworld.popup_centered() else: new_storyworld() elif ("Open" == item_name): if(false == storyworld.project_saved): - $ConfirmOpenWhenUnsaved.popup() + $ConfirmOpenWhenUnsaved.popup_centered() else: $LoadFileDialog.invalidate() - $LoadFileDialog.popup() + $LoadFileDialog.popup_centered() elif ("Import from Storyworld" == item_name): $ImportFromStoryworldFileDialog.invalidate() - $ImportFromStoryworldFileDialog.popup() - elif ("Import from XML" == item_name): - $ImportXMLFileDialog.popup() + $ImportFromStoryworldFileDialog.popup_centered() elif ("Save" == item_name): if ("" != current_project_path): save_project() else: $SaveAsFileDialog.invalidate() - $SaveAsFileDialog.popup() + $SaveAsFileDialog.popup_centered() elif ("Save As" == item_name): $SaveAsFileDialog.invalidate() - $SaveAsFileDialog.popup() + $SaveAsFileDialog.popup_centered() elif ("Compile to HTML" == item_name): open_after_compiling = false $CompileFileDialog.invalidate() - $CompileFileDialog.popup() + $CompileFileDialog.popup_centered() elif ("Compile and Playtest" == item_name): open_after_compiling = true $CompileFileDialog.invalidate() - $CompileFileDialog.popup() + $CompileFileDialog.popup_centered() elif ("Quit" == item_name): if(false == storyworld.project_saved): - $ConfirmQuit.popup() + $ConfirmQuit.popup_centered() else: get_tree().quit() @@ -260,17 +261,24 @@ func _on_viewmenu_item_pressed(id): var item_name = $Background/VBC/MenuBar/ViewMenu.get_popup().get_item_text(id) if ("Summary" == item_name): $Summary/Statistics.refresh_statistical_overview() - $Summary.popup() + $Summary.popup_centered() func _on_helpmenu_item_pressed(id): var item_name = $Background/VBC/MenuBar/HelpMenu.get_popup().get_item_text(id) if ("About" == item_name): - $About.popup() + $About.popup_centered() elif ("Validate and Troubleshoot" == item_name): - $StoryworldTroubleshooting.popup() + $StoryworldTroubleshooting.popup_centered() + elif ("Check for Updates" == item_name): + $CheckForUpdates/UpdateScreen.refresh() + $CheckForUpdates.popup_centered() + +func _on_OpenSweepWeaveHomepage_pressed(): + #This button is part of the "About" popup. + OS.shell_open("https://www.sweepweave.org") func _on_OpenPatreonButton_pressed(): - #This button is in the "About" popup. + #This button is part of the "About" popup. OS.shell_open("https://www.patreon.com/sasha_fenn") func _on_ConfirmNewStoryworld_confirmed(): @@ -278,11 +286,10 @@ func _on_ConfirmNewStoryworld_confirmed(): func _on_ConfirmOpenWhenUnsaved_confirmed(): $LoadFileDialog.invalidate() - $LoadFileDialog.popup() + $LoadFileDialog.popup_centered() func _on_LoadFileDialog_file_selected(path): current_project_path = path - print("Opening: " + path) var file = File.new() file.open(path, 1) var json_string = file.get_as_text().replacen("var storyworld_data = ", "") @@ -296,7 +303,6 @@ func _on_SaveAsFileDialog_file_selected(path): func _on_CompileFileDialog_file_selected(path): storyworld.compile_to_html(path) if (open_after_compiling): - print("Opening file in webbrowser for playtesting: " + path) OS.shell_open("file:///" + path) @@ -349,13 +355,13 @@ func _on_ImportFromStoryworldFileDialog_file_selected(path): $ConfirmImport/Margin/StoryworldMergingScreen.file_paths = [path] $ConfirmImport/Margin/StoryworldMergingScreen.clear_data() $ConfirmImport/Margin/StoryworldMergingScreen.load_content_from_files() - $ConfirmImport.popup() + $ConfirmImport.popup_centered() func _on_ImportFromStoryworldFileDialog_files_selected(paths): $ConfirmImport/Margin/StoryworldMergingScreen.file_paths = paths $ConfirmImport/Margin/StoryworldMergingScreen.clear_data() $ConfirmImport/Margin/StoryworldMergingScreen.load_content_from_files() - $ConfirmImport.popup() + $ConfirmImport.popup_centered() func _on_ConfirmImport_confirmed(): storyworld.import_characters($ConfirmImport/Margin/StoryworldMergingScreen.get_selected_characters()) @@ -364,22 +370,26 @@ func _on_ConfirmImport_confirmed(): $Background/VBC/EditorTabs/Encounters.refresh_encounter_list() func display_encounter(encounter): - $Background/VBC/EditorTabs/Encounters.load_Encounter(encounter) if (null != encounter): + $Background/VBC/EditorTabs/Encounters.load_Encounter(encounter) $Background/VBC/EditorTabs.set_current_tab(1) +func display_encounter_by_id(id): + $Background/VBC/EditorTabs/Encounters.load_Encounter_by_id(id) + $Background/VBC/EditorTabs.set_current_tab(1) + func _on_About_confirmed(): #Used to bring up MIT License message. - $MITLicenseDialog.popup() + $MITLicenseDialog.popup_centered() func set_gui_theme(theme_name): match theme_name: "Clarity": $Background.set_texture(clarity_gradient_header) - $Background.set_theme(clarity_theme) + set_theme(clarity_theme) "Lapis Lazuli": $Background.set_texture(lapis_lazuli_gradient_header) - $Background.set_theme(lapis_lazuli_theme) + set_theme(lapis_lazuli_theme) $Background/VBC/EditorTabs/Overview.set_gui_theme(theme_name, theme_background_colors[theme_name]) $Background/VBC/EditorTabs/Encounters.set_gui_theme(theme_name, theme_background_colors[theme_name]) $Background/VBC/EditorTabs/Spools.set_gui_theme(theme_name, theme_background_colors[theme_name]) diff --git a/godot/GUI.tscn b/godot/GUI.tscn index d14df22..e51c167 100644 --- a/godot/GUI.tscn +++ b/godot/GUI.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=21 format=2] +[gd_scene load_steps=23 format=2] [ext_resource path="res://GUI.gd" type="Script" id=1] [ext_resource path="res://FileMenu.gd" type="Script" id=2] @@ -18,6 +18,8 @@ [ext_resource path="res://HelpMenu.gd" type="Script" id=16] [ext_resource path="res://custom_resources/ball_of_yarn.png" type="Texture" id=17] [ext_resource path="res://custom_resources/gradient_header_texture_clarity.tres" type="Texture" id=18] +[ext_resource path="res://UpdateScreen.tscn" type="PackedScene" id=19] +[ext_resource path="res://custom_resources/clarity.tres" type="Theme" id=20] [sub_resource type="Shader" id=1] code = "shader_type canvas_item @@ -30,6 +32,7 @@ shader = SubResource( 1 ) [node name="GUI" type="Control"] anchor_right = 1.0 anchor_bottom = 1.0 +theme = ExtResource( 20 ) script = ExtResource( 1 ) [node name="Background" type="TextureRect" parent="."] @@ -51,7 +54,7 @@ margin_bottom = 20.0 custom_constants/separation = 0 [node name="FileMenu" type="MenuButton" parent="Background/VBC/MenuBar"] -margin_right = 35.0 +margin_right = 37.0 margin_bottom = 20.0 size_flags_horizontal = 0 text = "File" @@ -61,8 +64,8 @@ switch_on_hover = true script = ExtResource( 2 ) [node name="ViewMenu" type="MenuButton" parent="Background/VBC/MenuBar"] -margin_left = 35.0 -margin_right = 77.0 +margin_left = 37.0 +margin_right = 81.0 margin_bottom = 20.0 text = "View" flat = false @@ -70,8 +73,8 @@ switch_on_hover = true script = ExtResource( 15 ) [node name="HelpMenu" type="MenuButton" parent="Background/VBC/MenuBar"] -margin_left = 77.0 -margin_right = 119.0 +margin_left = 81.0 +margin_right = 125.0 margin_bottom = 20.0 text = "Help" flat = false @@ -90,10 +93,10 @@ __meta__ = { } [node name="Overview" parent="Background/VBC/EditorTabs" instance=ExtResource( 10 )] -margin_left = 4.0 -margin_top = 32.0 -margin_right = -4.0 -margin_bottom = -4.0 +margin_left = 1.0 +margin_top = 29.0 +margin_right = -1.0 +margin_bottom = -1.0 [node name="Encounters" parent="Background/VBC/EditorTabs" instance=ExtResource( 3 )] visible = false @@ -185,18 +188,9 @@ margin_bottom = 70.0 dialog_text = "You have modified your project since you last saved. Do you wish to start a new project without saving your current one? Progress will be lost." dialog_autowrap = true -[node name="ImportXMLFileDialog" type="FileDialog" parent="."] -margin_right = 315.0 -margin_bottom = 320.0 -window_title = "Import Project from XML" -resizable = true -mode_overrides_title = false -mode = 0 -access = 2 - [node name="About" type="ConfirmationDialog" parent="."] -margin_right = 400.0 -margin_bottom = 350.0 +margin_right = 450.0 +margin_bottom = 450.0 rect_min_size = Vector2( 200, 256 ) size_flags_vertical = 3 window_title = "About" @@ -205,8 +199,8 @@ resizable = true [node name="VBC" type="VBoxContainer" parent="About"] margin_left = 8.0 margin_top = 8.0 -margin_right = 392.0 -margin_bottom = 314.0 +margin_right = 442.0 +margin_bottom = 416.0 size_flags_vertical = 0 [node name="VersionMessage" type="Label" parent="About/VBC"] @@ -235,7 +229,7 @@ focus_mode = 2 size_flags_horizontal = 3 size_flags_vertical = 3 text = "An interactive storyworld creation kit, created by Sasha Fenn. Published under an MIT License. -Made in Godot 3.5.1. +Made in Godot 3.5.2. You can contact me by email at sasha@emptiestvoid.com." selection_enabled = true @@ -254,12 +248,22 @@ Felipe Vega Patrick Dugan Pamela Beck -If you would like to help support me, you can find me at:" +If you would like to help support me as well, you can find me at my patreon page via the link below." -[node name="OpenPatreonButton" type="Button" parent="About/VBC"] +[node name="LinkBar" type="HBoxContainer" parent="About/VBC"] +margin_right = 40.0 +margin_bottom = 40.0 +alignment = 1 + +[node name="OpenSweepWeaveHomepage" type="Button" parent="About/VBC/LinkBar"] +margin_right = 4.0 +margin_bottom = 18.0 +text = "SweepWeave Homepage" + +[node name="OpenPatreon" type="Button" parent="About/VBC/LinkBar"] margin_right = 84.0 margin_bottom = 20.0 -text = "My Patreon" +text = "Sasha's Patreon" [node name="ImportFromStoryworldFileDialog" type="FileDialog" parent="."] margin_right = 512.0 @@ -286,13 +290,13 @@ resizable = true margin_left = 8.0 margin_top = 8.0 margin_right = 542.0 -margin_bottom = 476.0 +margin_bottom = 478.0 [node name="StoryworldMergingScreen" parent="ConfirmImport/Margin" instance=ExtResource( 4 )] anchor_right = 0.0 anchor_bottom = 0.0 margin_right = 534.0 -margin_bottom = 468.0 +margin_bottom = 470.0 [node name="StoryworldTroubleshooting" type="AcceptDialog" parent="."] margin_right = 700.0 @@ -305,7 +309,7 @@ resizable = true margin_left = 8.0 margin_top = 8.0 margin_right = -8.0 -margin_bottom = -36.0 +margin_bottom = -34.0 [node name="Summary" type="AcceptDialog" parent="."] margin_right = 610.0 @@ -318,7 +322,7 @@ resizable = true margin_left = 8.0 margin_top = 8.0 margin_right = 602.0 -margin_bottom = 314.0 +margin_bottom = 316.0 [node name="MITLicenseDialog" type="AcceptDialog" parent="."] margin_right = 600.0 @@ -332,7 +336,7 @@ dialog_autowrap = true margin_left = 8.0 margin_top = 8.0 margin_right = 592.0 -margin_bottom = 364.0 +margin_bottom = 366.0 size_flags_horizontal = 3 size_flags_vertical = 3 text = "MIT License @@ -345,15 +349,28 @@ The above copyright notice and this permission notice shall be included in all c THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE." +[node name="CheckForUpdates" type="AcceptDialog" parent="."] +margin_right = 270.0 +margin_bottom = 200.0 +rect_min_size = Vector2( 256, 128 ) +window_title = "Updates" +resizable = true + +[node name="UpdateScreen" parent="CheckForUpdates" instance=ExtResource( 19 )] +margin_left = 8.0 +margin_top = 8.0 +margin_right = -8.0 +margin_bottom = -34.0 + [connection signal="file_selected" from="LoadFileDialog" to="." method="_on_LoadFileDialog_file_selected"] [connection signal="file_selected" from="SaveAsFileDialog" to="." method="_on_SaveAsFileDialog_file_selected"] [connection signal="file_selected" from="CompileFileDialog" to="." method="_on_CompileFileDialog_file_selected"] [connection signal="confirmed" from="ConfirmOpenWhenUnsaved" to="." method="_on_ConfirmOpenWhenUnsaved_confirmed"] [connection signal="confirmed" from="ConfirmQuit" to="." method="_on_ConfirmQuit_confirmed"] [connection signal="confirmed" from="ConfirmNewStoryworld" to="." method="_on_ConfirmNewStoryworld_confirmed"] -[connection signal="file_selected" from="ImportXMLFileDialog" to="." method="_on_ImportXMLFileDialog_file_selected"] [connection signal="confirmed" from="About" to="." method="_on_About_confirmed"] -[connection signal="pressed" from="About/VBC/OpenPatreonButton" to="." method="_on_OpenPatreonButton_pressed"] +[connection signal="pressed" from="About/VBC/LinkBar/OpenSweepWeaveHomepage" to="." method="_on_OpenSweepWeaveHomepage_pressed"] +[connection signal="pressed" from="About/VBC/LinkBar/OpenPatreon" to="." method="_on_OpenPatreonButton_pressed"] [connection signal="file_selected" from="ImportFromStoryworldFileDialog" to="." method="_on_ImportFromStoryworldFileDialog_file_selected"] [connection signal="files_selected" from="ImportFromStoryworldFileDialog" to="." method="_on_ImportFromStoryworldFileDialog_files_selected"] [connection signal="confirmed" from="ConfirmImport" to="." method="_on_ConfirmImport_confirmed"] diff --git a/godot/HelpMenu.gd b/godot/HelpMenu.gd index 605e1f0..a2f651f 100644 --- a/godot/HelpMenu.gd +++ b/godot/HelpMenu.gd @@ -3,3 +3,4 @@ extends MenuButton func _ready(): get_popup().add_item("About") get_popup().add_item("Validate and Troubleshoot") + get_popup().add_item("Check for Updates") diff --git a/godot/Option.gd b/godot/Option.gd index e13fe7d..469f86e 100644 --- a/godot/Option.gd +++ b/godot/Option.gd @@ -44,6 +44,15 @@ func get_truncated_text(maximum_output_length = 20): else: return text.left(maximum_output_length - 3) + "..." +func get_listable_text(maximum_output_length = 50): + var text = get_text() + if ("" == text): + return "[Blank Option]" + elif (maximum_output_length >= text.length()): + return text + else: + return text.left(maximum_output_length - 3) + "..." + func has_search_text(searchterm): if (text_script.has_search_text(searchterm)): return true diff --git a/godot/PlayScreen.gd b/godot/PlayScreen.gd index dfd7cc8..dadf11b 100644 --- a/godot/PlayScreen.gd +++ b/godot/PlayScreen.gd @@ -6,6 +6,8 @@ var page_to_display = null #Display options: var display_spoolbook = true +signal encounter_edit_button_pressed(id) + func reset_rehearsal(): if (null == rehearsal): rehearsal = Rehearsal.new(reference_storyworld) @@ -125,10 +127,12 @@ func refresh_encountertitle(): if (null != page_to_display.turn): display_turn = " (Turn: " + str(page_to_display.turn) + ")" if (null == page_to_display.encounter): - $Layout/L2/ColorRect/VBC/EncounterTitle.text = "(The End.)" + display_turn + $Layout/L2/ColorRect/VBC/TitleBar/Edit_Button.visible = false + $Layout/L2/ColorRect/VBC/TitleBar/EncounterTitle.text = "(The End.)" + display_turn else: - $Layout/L2/ColorRect/VBC/EncounterTitle.text = page_to_display.encounter.title + display_turn - return $Layout/L2/ColorRect/VBC/EncounterTitle.text + $Layout/L2/ColorRect/VBC/TitleBar/Edit_Button.visible = true + $Layout/L2/ColorRect/VBC/TitleBar/EncounterTitle.text = page_to_display.encounter.title + display_turn + return $Layout/L2/ColorRect/VBC/TitleBar/EncounterTitle.text func refresh_maintext(): var text = "" @@ -190,7 +194,7 @@ func load_options_script_report(): visible_entry.set_text(1, str(option_visible)) open_entry.set_text(0, "Performability") open_entry.set_text(1, str(option_open)) - $OptionScriptReportWindow.popup() + $OptionScriptReportWindow.popup_centered() func report_encounter_scripts(entry): #Used by load_encounter_selection_report() to fill table. @@ -286,7 +290,7 @@ func load_encounter_selection_report(): else: text += "The End." $EncounterScriptReportWindow/VBC/Background/ConsequenceReport.append_bbcode(text) - $EncounterScriptReportWindow.popup() + $EncounterScriptReportWindow.popup_centered() func refresh_reaction_inclinations(option = null): $Layout/L2/VBC/Reaction_Inclinations.clear() @@ -319,8 +323,6 @@ func refresh_reaction_inclinations(option = null): var inclination = reaction.calculate_desirability(page_to_display, true) reaction_entry.set_text(1, str(inclination)) -signal encounter_loaded(id) - func load_Page(page): page_to_display = page rehearsal.step_playthrough(page) @@ -336,8 +338,6 @@ func load_Page(page): $Layout/L2/VBC/Resulting_Reaction.text = "" $Layout/L2/VBC/Resulting_Encounter.visible = false $Layout/L2/VBC/Resulting_Encounter.text = "" - if (null != page and null != page.encounter and page.encounter is Encounter): - emit_signal("encounter_loaded", page.encounter.id) # Called when the node enters the scene tree for the first time. func _ready(): @@ -359,10 +359,11 @@ func _ready(): $EncounterScriptReportWindow/VBC/ScriptDisplay.set_column_min_width(1, 1) func clear(): - $Layout/L2/ColorRect/VBC/Play_Button.text = "Start" + $Layout/L2/ColorRect/VBC/TitleBar/Play_Button.text = "Start" $Layout/VBC/Spoolbook.clear() $Layout/VBC/Historybook.clear() - $Layout/L2/ColorRect/VBC/EncounterTitle.text = "" + $Layout/L2/ColorRect/VBC/TitleBar/Edit_Button.visible = false + $Layout/L2/ColorRect/VBC/TitleBar/EncounterTitle.text = "" $Layout/L2/ColorRect/VBC/MainText.set_bbcode("") $Layout/L2/VBC/Castbook.clear() $Layout/L2/ColorRect/VBC/OptionsList.clear() @@ -376,11 +377,15 @@ func clear(): $Layout/L2/VBC/Resulting_Encounter.text = "" func _on_Play_Button_pressed(): - $Layout/L2/ColorRect/VBC/Play_Button.text = "Restart" + $Layout/L2/ColorRect/VBC/TitleBar/Play_Button.text = "Restart" reset_rehearsal() rehearsal.begin_playthrough() load_Page(rehearsal.current_page) +func _on_Edit_Button_pressed(): + if (null != page_to_display and null != page_to_display.encounter and page_to_display.encounter is Encounter): + emit_signal("encounter_edit_button_pressed", page_to_display.encounter.id) + func _on_OptionsList_item_selected(index): var option_page = $Layout/L2/ColorRect/VBC/OptionsList.get_item_metadata(index) if (TYPE_STRING == typeof(option_page)): @@ -425,7 +430,15 @@ func _on_EncounterSelectionReportButton_pressed(): #GUI Themes: +onready var edit_icon_light = preload("res://custom_resources/edit-3.svg") +onready var edit_icon_dark = preload("res://custom_resources/edit-3_dark.svg") + func set_gui_theme(theme_name, background_color): color = background_color $Layout/L2/ColorRect.color = background_color $EncounterScriptReportWindow/VBC/Background.color = background_color + match theme_name: + "Clarity": + $Layout/L2/ColorRect/VBC/TitleBar/Edit_Button.icon = edit_icon_dark + "Lapis Lazuli": + $Layout/L2/ColorRect/VBC/TitleBar/Edit_Button.icon = edit_icon_light diff --git a/godot/PlayScreen.tscn b/godot/PlayScreen.tscn index b749aa5..02716bd 100644 --- a/godot/PlayScreen.tscn +++ b/godot/PlayScreen.tscn @@ -1,7 +1,8 @@ -[gd_scene load_steps=3 format=2] +[gd_scene load_steps=4 format=2] [ext_resource path="res://PlayScreen.gd" type="Script" id=1] [ext_resource path="res://ScriptDisplay.tscn" type="PackedScene" id=2] +[ext_resource path="res://custom_resources/edit-3.svg" type="Texture" id=3] [node name="Background" type="ColorRect"] anchor_right = 1.0 @@ -75,22 +76,32 @@ anchor_bottom = 1.0 size_flags_horizontal = 3 alignment = 1 -[node name="Play_Button" type="Button" parent="Layout/L2/ColorRect/VBC"] +[node name="TitleBar" type="HBoxContainer" parent="Layout/L2/ColorRect/VBC"] +margin_right = 562.0 +margin_bottom = 20.0 + +[node name="Play_Button" type="Button" parent="Layout/L2/ColorRect/VBC/TitleBar"] margin_right = 41.0 margin_bottom = 20.0 size_flags_horizontal = 0 -size_flags_vertical = 0 text = "Start" -[node name="EncounterTitle" type="Label" parent="Layout/L2/ColorRect/VBC"] -margin_top = 24.0 -margin_right = 562.0 -margin_bottom = 38.0 +[node name="Edit_Button" type="Button" parent="Layout/L2/ColorRect/VBC/TitleBar"] +visible = false +margin_right = 36.0 +margin_bottom = 30.0 +icon = ExtResource( 3 ) + +[node name="EncounterTitle" type="Label" parent="Layout/L2/ColorRect/VBC/TitleBar"] +margin_left = 45.0 +margin_top = 3.0 +margin_right = 45.0 +margin_bottom = 17.0 [node name="MainText" type="RichTextLabel" parent="Layout/L2/ColorRect/VBC"] -margin_top = 42.0 +margin_top = 24.0 margin_right = 562.0 -margin_bottom = 502.0 +margin_bottom = 496.0 rect_min_size = Vector2( 128, 128 ) size_flags_horizontal = 3 size_flags_vertical = 3 @@ -117,7 +128,7 @@ margin_bottom = 20.0 text = "Option Script Reports" [node name="OptionsList" type="ItemList" parent="Layout/L2/ColorRect/VBC"] -margin_top = 506.0 +margin_top = 500.0 margin_right = 562.0 margin_bottom = 736.0 size_flags_horizontal = 3 @@ -177,6 +188,10 @@ resizable = true [node name="VBC" type="VBoxContainer" parent="EncounterScriptReportWindow"] anchor_right = 1.0 anchor_bottom = 1.0 +margin_left = 8.0 +margin_top = 8.0 +margin_right = -8.0 +margin_bottom = -36.0 [node name="Background" type="ColorRect" parent="EncounterScriptReportWindow/VBC"] margin_right = 512.0 @@ -219,7 +234,8 @@ columns = 2 select_mode = 1 [connection signal="item_activated" from="Layout/VBC/Historybook" to="." method="_on_Historybook_item_activated"] -[connection signal="pressed" from="Layout/L2/ColorRect/VBC/Play_Button" to="." method="_on_Play_Button_pressed"] +[connection signal="pressed" from="Layout/L2/ColorRect/VBC/TitleBar/Play_Button" to="." method="_on_Play_Button_pressed"] +[connection signal="pressed" from="Layout/L2/ColorRect/VBC/TitleBar/Edit_Button" to="." method="_on_Edit_Button_pressed"] [connection signal="pressed" from="Layout/L2/ColorRect/VBC/ScriptReportButtonsHBC/EncounterSelectionReportButton" to="." method="_on_EncounterSelectionReportButton_pressed"] [connection signal="pressed" from="Layout/L2/ColorRect/VBC/ScriptReportButtonsHBC/OptionScriptReportButton" to="." method="_on_OptionScriptReportButton_pressed"] [connection signal="item_activated" from="Layout/L2/ColorRect/VBC/OptionsList" to="." method="_on_OptionsList_item_activated"] diff --git a/godot/Reaction.gd b/godot/Reaction.gd index 17fa869..ffbd885 100644 --- a/godot/Reaction.gd +++ b/godot/Reaction.gd @@ -46,6 +46,15 @@ func get_truncated_text(maximum_output_length = 20): else: return text.left(maximum_output_length - 3) + "..." +func get_listable_text(maximum_output_length = 50): + var text = get_text() + if ("" == text): + return "[Blank Reaction]" + elif (maximum_output_length >= text.length()): + return text + else: + return text.left(maximum_output_length - 3) + "..." + func calculate_desirability(leaf, report): var result = null if (null != desirability_script and desirability_script is ScriptManager): diff --git a/godot/SWEffect.gd b/godot/SWEffect.gd index ac971c0..799e5c7 100644 --- a/godot/SWEffect.gd +++ b/godot/SWEffect.gd @@ -1,6 +1,7 @@ extends Object class_name SWEffect +var cause = null #This could be, for example, a reaction. var effect_type = "Generic Effect" var assignee = null var assignment_script = null @@ -24,3 +25,24 @@ func clear(): func remap(to_storyworld): pass + +func data_to_string(): + var result = "Set a variable to: " + if (assignment_script is ScriptManager): + result += assignment_script.data_to_string() + else: + result += "[invalid script]" + result += "." + return result + +func get_listable_text(maximum_output_length = 50): + var text = data_to_string() + if (maximum_output_length >= text.length()): + return text + else: + return text.left(maximum_output_length - 3) + "..." + +func get_index(): + if (null != cause): + return cause.after_effects.find(self) + return -1 diff --git a/godot/ScriptEditScreen.gd b/godot/ScriptEditScreen.gd index 79e9b73..2ce340d 100644 --- a/godot/ScriptEditScreen.gd +++ b/godot/ScriptEditScreen.gd @@ -222,7 +222,7 @@ func _on_AvailableOperatorList_item_activated(index): $EventSelectionDialog/EventSelectionInterface.storyworld = storyworld $EventSelectionDialog/EventSelectionInterface.reset() $EventSelectionDialog/EventSelectionInterface.refresh() - $EventSelectionDialog.popup() + $EventSelectionDialog.popup_centered() "Spool Status": if (!storyworld.spools.empty()): new_element = SpoolStatusPointer.new(storyworld.spools.front(), false) #Second value, (negated,) being false means that the spool being active causes the pointer to return true. diff --git a/godot/SettingsEditScreen.gd b/godot/SettingsEditScreen.gd index 8b34234..7e31ef6 100644 --- a/godot/SettingsEditScreen.gd +++ b/godot/SettingsEditScreen.gd @@ -53,7 +53,7 @@ func set_gui_theme(theme_name, background_color): pass func _on_IFIDResetButton_pressed(): - $ConfirmIFIDReset.popup() + $ConfirmIFIDReset.popup_centered() func _on_ConfirmIFIDReset_confirmed(): storyworld.ifid = IFIDGenerator.IFID_from_creation_time(storyworld.creation_time) diff --git a/godot/SettingsEditScreen.tscn b/godot/SettingsEditScreen.tscn index 7f73017..d7fbba3 100644 --- a/godot/SettingsEditScreen.tscn +++ b/godot/SettingsEditScreen.tscn @@ -51,6 +51,7 @@ margin_bottom = 114.0 autowrap = true [node name="HBC1" type="HBoxContainer" parent="VBC"] +visible = false margin_top = 118.0 margin_right = 317.0 margin_bottom = 138.0 @@ -66,9 +67,9 @@ margin_bottom = 20.0 text = "Create new IFID" [node name="HBC2" type="HBoxContainer" parent="VBC"] -margin_top = 142.0 +margin_top = 118.0 margin_right = 317.0 -margin_bottom = 182.0 +margin_bottom = 158.0 [node name="DBMLabel" type="Label" parent="VBC/HBC2"] margin_top = 13.0 @@ -82,9 +83,9 @@ margin_right = 279.0 margin_bottom = 40.0 [node name="HBC3" type="HBoxContainer" parent="VBC"] -margin_top = 186.0 +margin_top = 162.0 margin_right = 317.0 -margin_bottom = 226.0 +margin_bottom = 202.0 [node name="DisplayModeLabel" type="Label" parent="VBC/HBC3"] margin_top = 13.0 diff --git a/godot/SingleBNumberBlueprintEditPanel.gd b/godot/SingleBNumberBlueprintEditPanel.gd index 02e242b..005b3e6 100644 --- a/godot/SingleBNumberBlueprintEditPanel.gd +++ b/godot/SingleBNumberBlueprintEditPanel.gd @@ -136,7 +136,7 @@ func _on_AddCharacterButton_pressed(): $SelectNewAffectedCharacterWindow/PossibleNewAffectedCharactersList.add_item(character.char_name) $SelectNewAffectedCharacterWindow/PossibleNewAffectedCharactersList.set_item_metadata(item_index, character) item_index += 1 - $SelectNewAffectedCharacterWindow.popup() + $SelectNewAffectedCharacterWindow.popup_centered() func _on_SelectNewAffectedCharacterWindow_confirmed(): var selected_indices = $SelectNewAffectedCharacterWindow/PossibleNewAffectedCharactersList.get_selected_items() @@ -176,7 +176,7 @@ func _on_DeleteCharacterButton_pressed(): new_label = Label.new() new_label.text = character.char_name $ConfirmRemoveAffectedCharactersWindow/VBC.add_child(new_label) - $ConfirmRemoveAffectedCharactersWindow.popup() + $ConfirmRemoveAffectedCharactersWindow.popup_centered() func _on_ConfirmRemoveAffectedCharactersWindow_confirmed(): for character in characters_to_remove_from_those_affected: diff --git a/godot/Spool.gd b/godot/Spool.gd index f59f44b..abc2de7 100644 --- a/godot/Spool.gd +++ b/godot/Spool.gd @@ -3,6 +3,7 @@ class_name Spool #A group of encounters, with some associated scripts. #SweepWeave uses spools when deciding which encounter to present next. +var storyworld = null var id = "" var spool_name = "" var encounters = [] #A list of encounters. @@ -20,6 +21,20 @@ var is_active = true #This variable tracks whether or not the spool is currently func _init(): pass +func get_index(): + if (null != storyworld): + return storyworld.spools.find(self) + return -1 + +func get_listable_text(maximum_output_length = 50): + var text = spool_name + if ("" == text): + return "[Untitled Spool]" + elif (maximum_output_length >= text.length()): + return text + else: + return text.left(maximum_output_length - 3) + "..." + func log_update(): modified_time = OS.get_unix_time() diff --git a/godot/SpoolEditScreen.gd b/godot/SpoolEditScreen.gd index 0a22c48..c4e9828 100644 --- a/godot/SpoolEditScreen.gd +++ b/godot/SpoolEditScreen.gd @@ -19,7 +19,7 @@ func refresh(): else: current_spool = null $Background/HBC/Column1/Spools.clear() - $Background/HBC/Column1/Spools.list_to_display.clear() + $Background/HBC/Column1/Spools.items_to_list.clear() for child in $Background/HBC/Column2.get_children(): if ($Background/HBC/Column2/NoSpoolSelected == child or $Background/HBC/Column2/NoSpoolMargin == child): child.visible = true @@ -29,23 +29,9 @@ func refresh(): func refresh_spools_list(): $Background/HBC/Column1/Spools.clear() - $Background/HBC/Column1/Spools.list_to_display.clear() + $Background/HBC/Column1/Spools.items_to_list.clear() if (null != storyworld): - for spool in storyworld.spools: - var display_text = spool.spool_name - if ("" == display_text): - display_text = "[Untitled Spool]" - var entry = {"text": display_text, "metadata": spool} - $Background/HBC/Column1/Spools.list_to_display.append(entry) - $Background/HBC/Column1/Spools.refresh() - -func add_spool_to_list(spool): - if (null != storyworld): - var display_text = spool.spool_name - if ("" == display_text): - display_text = "[Untitled Spool]" - var entry = {"text": display_text, "metadata": spool} - $Background/HBC/Column1/Spools.list_to_display.append(entry) + $Background/HBC/Column1/Spools.items_to_list = storyworld.spools.duplicate() $Background/HBC/Column1/Spools.refresh() func display_spool(spool:Spool): @@ -56,16 +42,11 @@ func display_spool(spool:Spool): else: child.visible = true $Background/HBC/Column2/Encounters_on_current_spool.clear() - $Background/HBC/Column2/Encounters_on_current_spool.list_to_display.clear() + $Background/HBC/Column2/Encounters_on_current_spool.items_to_list.clear() if (null != spool and spool is Spool): $Background/HBC/Column2/HBC/SpoolNameEdit.text = spool.spool_name $Background/HBC/Column2/HBC/SpoolStartsActiveCheckBox.pressed = spool.starts_active - for encounter in spool.encounters: - var display_text = encounter.title - if ("" == display_text): - display_text = "[Untitled Encounter]" - var entry = {"text": display_text, "metadata": encounter} - $Background/HBC/Column2/Encounters_on_current_spool.list_to_display.append(entry) + $Background/HBC/Column2/Encounters_on_current_spool.items_to_list = spool.encounters.duplicate() $Background/HBC/Column2/Encounters_on_current_spool.refresh() func load_and_focus_first_spool(): @@ -92,12 +73,13 @@ func create_new_spool(): func _on_AddButton_pressed(): current_spool = create_new_spool() - add_spool_to_list(current_spool) + $Background/HBC/Column1/Spools.list_item(current_spool) display_spool(current_spool) + $Background/HBC/Column1/Spools.deselect_all() $Background/HBC/Column1/Spools.select_last_item() -func _on_Spools_item_selected(): - display_spool($Background/HBC/Column1/Spools.get_selected_metadata()) +func _on_Spools_multi_selected(item, column, selected): + display_spool($Background/HBC/Column1/Spools.get_first_selected_metadata()) func _on_SpoolNameEdit_text_changed(new_text): current_spool.spool_name = new_text @@ -125,14 +107,14 @@ func add_encounter_to_current_spool(event_pointer): func _on_DeleteButton_pressed(): if (1 == storyworld.spools.size()): - $CannotDeleteSpoolNotification.popup() + $CannotDeleteSpoolNotification.popup_centered() return - spool_to_delete = $Background/HBC/Column1/Spools.get_selected_metadata() + spool_to_delete = $Background/HBC/Column1/Spools.get_first_selected_metadata() if (null != spool_to_delete): var dialog_text = 'Are you sure you wish to delete the following spool?' dialog_text += " (" + spool_to_delete.spool_name + ")" $SpoolDeletionConfirmationDialog.dialog_text = dialog_text - $SpoolDeletionConfirmationDialog.popup() + $SpoolDeletionConfirmationDialog.popup_centered() func _on_SpoolDeletionConfirmationDialog_confirmed(): if (null != spool_to_delete): @@ -174,7 +156,7 @@ func _on_AddEncounterButton_pressed(): add_encounter_to_current_spool(selected_event) func _on_RemoveEncounterButton_pressed(): - var encounter_to_remove = $Background/HBC/Column2/Encounters_on_current_spool.get_selected_metadata() + var encounter_to_remove = $Background/HBC/Column2/Encounters_on_current_spool.get_first_selected_metadata() if (null != encounter_to_remove and null != current_spool): #Remove encounter from spool. current_spool.encounters.erase(encounter_to_remove) diff --git a/godot/SpoolEditScreen.tscn b/godot/SpoolEditScreen.tscn index 9b726eb..74f71c4 100644 --- a/godot/SpoolEditScreen.tscn +++ b/godot/SpoolEditScreen.tscn @@ -154,7 +154,7 @@ dialog_text = "Storyworlds require at least one spool." [connection signal="pressed" from="Background/HBC/Column1/HBC/AddButton" to="." method="_on_AddButton_pressed"] [connection signal="pressed" from="Background/HBC/Column1/HBC/DeleteButton" to="." method="_on_DeleteButton_pressed"] -[connection signal="item_selected" from="Background/HBC/Column1/Spools" to="." method="_on_Spools_item_selected"] +[connection signal="multi_selected" from="Background/HBC/Column1/Spools" to="." method="_on_Spools_multi_selected"] [connection signal="text_changed" from="Background/HBC/Column2/HBC/SpoolNameEdit" to="." method="_on_SpoolNameEdit_text_changed"] [connection signal="pressed" from="Background/HBC/Column2/HBC/SpoolStartsActiveCheckBox" to="." method="_on_SpoolStartsActiveCheckBox_pressed"] [connection signal="pressed" from="Background/HBC/Column2/HBC2/AddEncounterButton" to="." method="_on_AddEncounterButton_pressed"] diff --git a/godot/SpoolEffect.gd b/godot/SpoolEffect.gd index 0042ca3..394e9b1 100644 --- a/godot/SpoolEffect.gd +++ b/godot/SpoolEffect.gd @@ -42,6 +42,7 @@ func set_as_copy_of(original): assignment_script.set_as_copy_of(original.assignment_script) else: success = false + cause = original.cause return success func remap(storyworld): @@ -78,7 +79,7 @@ func compile(parent_storyworld, include_editor_only_variables = false): output["to"] = assignment_script.compile(parent_storyworld, include_editor_only_variables) return output -func load_from_json_v0_0_34_through_v0_0_37(storyworld, data_to_load): +func load_from_json_v0_0_34_through_v0_0_38(storyworld, data_to_load): clear() if (data_to_load.has_all(["Set", "to"])): if (TYPE_STRING == typeof(data_to_load["Set"]) and storyworld.spool_directory.has(data_to_load["Set"])): @@ -92,7 +93,7 @@ func load_from_json_v0_0_34_through_v0_0_37(storyworld, data_to_load): output_datatype = sw_script_data_types.BNUMBER elif (assignee.output_type == sw_script_data_types.BOOLEAN): output_datatype = sw_script_data_types.BOOLEAN - script.load_from_json_v0_0_34_through_v0_0_37(storyworld, data_to_load["to"], output_datatype) + script.load_from_json_v0_0_34_through_v0_0_38(storyworld, data_to_load["to"], output_datatype) assignment_script = script if (null != assignee and assignee is SpoolPointer and null != assignment_script and assignment_script is ScriptManager): return true diff --git a/godot/Storyworld.gd b/godot/Storyworld.gd index fd65e03..aee3d9f 100644 --- a/godot/Storyworld.gd +++ b/godot/Storyworld.gd @@ -100,12 +100,18 @@ func delete_authored_property(property): property.call_deferred("free") func init_classical_personality_model(): - var ap_names = ["Bad_Good", "False_Honest", "Timid_Dominant", "pBad_Good", "pFalse_Honest", "pTimid_Dominant"] + var ap_names = ["Bad_Good", "False_Honest", "Timid_Dominant"] for ap_name in ap_names: var new_index = unique_id_seeds["authored_property"] unique_id_seeds["authored_property"] += 1 var new_id = ap_name add_authored_property(BNumberBlueprint.new(self, new_index, new_id, ap_name, 0, 0)) + ap_names = ["pBad_Good", "pFalse_Honest", "pTimid_Dominant"] + for ap_name in ap_names: + var new_index = unique_id_seeds["authored_property"] + unique_id_seeds["authored_property"] += 1 + var new_id = ap_name + add_authored_property(BNumberBlueprint.new(self, new_index, new_id, ap_name, 1, 0)) func add_all_authored_properties_from(original): for property in original.authored_properties: @@ -773,7 +779,7 @@ func parse_reactions_data_v0_0_34_through_v0_0_37(reactions_data, option): reaction_directory[reaction_data["id"]] = reaction return result -func load_from_json_v0_0_34_through_v0_0_37(data_to_load): +func load_from_json_v0_0_34_through_v0_0_38(data_to_load): #Load characters. for entry in data_to_load.characters: if (entry.has_all(["name", "pronoun", "bnumber_properties", "id", "creation_index", "creation_time", "modified_time"])): @@ -830,41 +836,41 @@ func load_from_json_v0_0_34_through_v0_0_37(data_to_load): #Parse scripts: for encounter in encounters: var new_script = ScriptManager.new(null) - new_script.load_from_json_v0_0_34_through_v0_0_37(self, encounter.text_script, sw_script_data_types.STRING) + new_script.load_from_json_v0_0_34_through_v0_0_38(self, encounter.text_script, sw_script_data_types.STRING) encounter.text_script = new_script new_script = ScriptManager.new(null) - new_script.load_from_json_v0_0_34_through_v0_0_37(self, encounter.acceptability_script, sw_script_data_types.BOOLEAN) + new_script.load_from_json_v0_0_34_through_v0_0_38(self, encounter.acceptability_script, sw_script_data_types.BOOLEAN) encounter.acceptability_script = new_script new_script = ScriptManager.new(null) - new_script.load_from_json_v0_0_34_through_v0_0_37(self, encounter.desirability_script, sw_script_data_types.BNUMBER) + new_script.load_from_json_v0_0_34_through_v0_0_38(self, encounter.desirability_script, sw_script_data_types.BNUMBER) encounter.desirability_script = new_script for option in encounter.options: new_script = ScriptManager.new(null) - new_script.load_from_json_v0_0_34_through_v0_0_37(self, option.text_script, sw_script_data_types.STRING) + new_script.load_from_json_v0_0_34_through_v0_0_38(self, option.text_script, sw_script_data_types.STRING) option.text_script = new_script new_script = ScriptManager.new(null) - new_script.load_from_json_v0_0_34_through_v0_0_37(self, option.visibility_script, sw_script_data_types.BOOLEAN) + new_script.load_from_json_v0_0_34_through_v0_0_38(self, option.visibility_script, sw_script_data_types.BOOLEAN) option.visibility_script = new_script new_script = ScriptManager.new(null) - new_script.load_from_json_v0_0_34_through_v0_0_37(self, option.performability_script, sw_script_data_types.BOOLEAN) + new_script.load_from_json_v0_0_34_through_v0_0_38(self, option.performability_script, sw_script_data_types.BOOLEAN) option.performability_script = new_script for reaction in option.reactions: new_script = ScriptManager.new(null) - new_script.load_from_json_v0_0_34_through_v0_0_37(self, reaction.text_script, sw_script_data_types.STRING) + new_script.load_from_json_v0_0_34_through_v0_0_38(self, reaction.text_script, sw_script_data_types.STRING) reaction.text_script = new_script new_script = ScriptManager.new(null) - new_script.load_from_json_v0_0_34_through_v0_0_37(self, reaction.desirability_script, sw_script_data_types.BNUMBER) + new_script.load_from_json_v0_0_34_through_v0_0_38(self, reaction.desirability_script, sw_script_data_types.BNUMBER) reaction.desirability_script = new_script var parsed_effects = [] for effect_data in reaction.after_effects: if ("Bounded Number Effect" == effect_data["effect_type"] and effect_data["Set"].has_all(["pointer_type", "character", "coefficient", "keyring"]) and "Bounded Number Pointer" == effect_data["Set"]["pointer_type"] and TYPE_STRING == typeof(effect_data["Set"]["character"]) and effect_data["to"].has("script_element_type")): var new_effect = BNumberEffect.new() - var effect_is_valid = new_effect.load_from_json_v0_0_34_through_v0_0_37(self, effect_data) + var effect_is_valid = new_effect.load_from_json_v0_0_34_through_v0_0_38(self, effect_data) if (effect_is_valid): parsed_effects.append(new_effect) elif ("Spool Effect" == effect_data["effect_type"] and TYPE_STRING == typeof(effect_data["Set"])): var new_effect = SpoolEffect.new() - var effect_is_valid = new_effect.load_from_json_v0_0_34_through_v0_0_37(self, effect_data) + var effect_is_valid = new_effect.load_from_json_v0_0_34_through_v0_0_38(self, effect_data) if (effect_is_valid): parsed_effects.append(new_effect) reaction.after_effects.clear() @@ -941,9 +947,9 @@ func load_from_json(file_text): clear() load_from_json_v0_0_21_through_v0_0_29(data_to_load) return "Passed." - elif (0 == int(version[0]) and 0 == int(version[1]) and 34 <= int(version[2]) and 37 >= int(version[2])): + elif (0 == int(version[0]) and 0 == int(version[1]) and 34 <= int(version[2]) and 38 >= int(version[2])): clear() - load_from_json_v0_0_34_through_v0_0_37(data_to_load) + load_from_json_v0_0_34_through_v0_0_38(data_to_load) return "Passed." else: print ("Cannot load project file. The project appears to have been made using an unrecognized version of SweepWeave.") @@ -973,7 +979,7 @@ func save_project(file_path, save_as = false): for entry in encounters: file_data["encounters"].append(entry.compile(self, true)) # Save spools: - spools.sort_custom(SpoolSorter, "sort_created") +# spools.sort_custom(SpoolSorter, "sort_created") file_data["spools"] = [] for entry in spools: file_data["spools"].append(entry.compile(self, true)) @@ -1011,7 +1017,7 @@ func compile_to_html(path): for entry in encounters: file_data["encounters"].append(entry.compile(self, false)) # Compile spools: - spools.sort_custom(SpoolSorter, "sort_created") +# spools.sort_custom(SpoolSorter, "sort_created") file_data["spools"] = [] for entry in spools: file_data["spools"].append(entry.compile(self, false)) @@ -1025,7 +1031,7 @@ func compile_to_html(path): file_text += JSON.print(file_data, "\t") else: file_text += JSON.print(file_data) - var compiler = Compiler.new(file_text, storyworld_title, storyworld_author, ifid) + var compiler = Compiler.new(file_text, storyworld_title, storyworld_author, ifid, storyworld_debug_mode_on) var file = File.new() file.open(path, File.WRITE) file.store_string(compiler.output) diff --git a/godot/StoryworldValidationInterface.gd b/godot/StoryworldValidationInterface.gd index aea3901..3f2db0e 100644 --- a/godot/StoryworldValidationInterface.gd +++ b/godot/StoryworldValidationInterface.gd @@ -354,4 +354,4 @@ func _on_OpenLinkedScriptButton_pressed(): $ScriptEditWindow/ScriptEditScreen.script_to_edit = current_error_report.reported_script $ScriptEditWindow/ScriptEditScreen.allow_root_character_editing = true $ScriptEditWindow/ScriptEditScreen.refresh_script_display() - $ScriptEditWindow.popup() + $ScriptEditWindow.popup_centered() diff --git a/godot/StoryworldValidationInterface.tscn b/godot/StoryworldValidationInterface.tscn index 4fb7260..271c1f5 100644 --- a/godot/StoryworldValidationInterface.tscn +++ b/godot/StoryworldValidationInterface.tscn @@ -12,7 +12,7 @@ script = ExtResource( 1 ) [node name="ColorRect" type="ColorRect" parent="."] anchor_right = 1.0 anchor_bottom = 1.0 -color = Color( 0, 0.0627451, 0.12549, 1 ) +color = Color( 1, 1, 1, 0 ) [node name="HBC" type="HBoxContainer" parent="ColorRect"] anchor_right = 1.0 @@ -24,14 +24,14 @@ margin_bottom = 736.0 size_flags_horizontal = 3 [node name="Label" type="Label" parent="ColorRect/HBC/VBC"] +visible = false margin_right = 681.0 margin_bottom = 14.0 text = "Storyworld Validation and Error Checking:" [node name="ValidateButton" type="Button" parent="ColorRect/HBC/VBC"] -margin_top = 18.0 margin_right = 134.0 -margin_bottom = 38.0 +margin_bottom = 20.0 size_flags_horizontal = 0 text = "Validate storyworld" @@ -52,9 +52,9 @@ size_flags_horizontal = 3 size_flags_vertical = 3 [node name="StoryworldValidationOverview" type="RichTextLabel" parent="ColorRect/HBC/VBC"] -margin_top = 42.0 +margin_top = 24.0 margin_right = 681.0 -margin_bottom = 182.0 +margin_bottom = 164.0 rect_min_size = Vector2( 0, 140 ) [node name="VBC2" type="VBoxContainer" parent="ColorRect/HBC"] diff --git a/godot/UpdateScreen.gd b/godot/UpdateScreen.gd new file mode 100644 index 0000000..d774afe --- /dev/null +++ b/godot/UpdateScreen.gd @@ -0,0 +1,41 @@ +extends Control + +var sweepweave_version_number = "" +var station = "https://www.sweepweave.org/sw_broadcast/" +var user_agent = "" + +func _ready(): + pass + +func refresh(): + $VBC/WebText.clear() + $VBC/WebText.append_bbcode("Checking for updates...") + user_agent = "user-agent: (" + OS.get_name() + ") SweepWeave/" + sweepweave_version_number + $HTTPRequest.request("https://www.sweepweave.org/sw_broadcast/sweepweave_version_report.json", [user_agent]) + +func _on_HTTPRequest_request_completed(result, response_code, headers, body): + var report = null + if (result == HTTPRequest.RESULT_SUCCESS): + report = JSON.parse(body.get_string_from_utf8()).result + $VBC/WebText.clear() + if (null == report): + if ("https://www.sweepweave.org/sw_broadcast/" == station): + print("Error: Failed to obtain sweepweave version report from www.sweepweave.org. Checking www.emptiestvoid.com.") + station = "https://www.emptiestvoid.com/sw_broadcast/" + $HTTPRequest.request("https://www.emptiestvoid.com/sw_broadcast/sweepweave_version_report.json", [user_agent]) + elif ("https://www.emptiestvoid.com/sw_broadcast/" == station): + $VBC/WebText.append_bbcode("Failed to obtain sweepweave version report. Please try again later, or visit www.sweepweave.org for news regarding updates to SweepWeave.") + print("Error: Failed to obtain sweepweave version report from www.emptiestvoid.com.") + station = "https://www.sweepweave.org/sw_broadcast/" + else: + station = "https://www.sweepweave.org/sw_broadcast/" + if (report.has("latest_stable_version")): + if (sweepweave_version_number == report["latest_stable_version"]): + $VBC/WebText.append_bbcode("You currently have the latest stable version of SweepWeave.") + else: + $VBC/WebText.append_bbcode("Latest stable version: " + report["latest_stable_version"]) + else: + $VBC/WebText.append_bbcode("Error: Could not determine latest stable version number.") + +func _on_DownloadButton_pressed(): + OS.shell_open("https://www.patreon.com/sasha_fenn") diff --git a/godot/UpdateScreen.tscn b/godot/UpdateScreen.tscn new file mode 100644 index 0000000..ae47bf2 --- /dev/null +++ b/godot/UpdateScreen.tscn @@ -0,0 +1,47 @@ +[gd_scene load_steps=2 format=2] + +[ext_resource path="res://UpdateScreen.gd" type="Script" id=1] + +[node name="VBC" type="Control"] +anchor_right = 1.0 +anchor_bottom = 1.0 +size_flags_vertical = 0 +script = ExtResource( 1 ) + +[node name="VBC" type="VBoxContainer" parent="."] +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_left = 3.0 +margin_right = -3.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="VersionMessage" type="Label" parent="VBC"] +margin_right = 1360.0 +margin_bottom = 14.0 +align = 1 + +[node name="HSeparator" type="HSeparator" parent="VBC"] +margin_top = 18.0 +margin_right = 1360.0 +margin_bottom = 22.0 + +[node name="WebText" type="RichTextLabel" parent="VBC"] +margin_top = 26.0 +margin_right = 1360.0 +margin_bottom = 712.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +size_flags_stretch_ratio = 1.5 +bbcode_enabled = true + +[node name="DownloadButton" type="Button" parent="VBC"] +margin_top = 716.0 +margin_right = 1360.0 +margin_bottom = 736.0 +text = "Open download page." + +[node name="HTTPRequest" type="HTTPRequest" parent="."] + +[connection signal="pressed" from="VBC/DownloadButton" to="." method="_on_DownloadButton_pressed"] +[connection signal="request_completed" from="HTTPRequest" to="." method="_on_HTTPRequest_request_completed"] diff --git a/godot/custom_resources/clarity.tres b/godot/custom_resources/clarity.tres index 77d60a2..74394e8 100644 --- a/godot/custom_resources/clarity.tres +++ b/godot/custom_resources/clarity.tres @@ -1,4 +1,4 @@ -[gd_resource type="Theme" load_steps=45 format=2] +[gd_resource type="Theme" load_steps=46 format=2] [ext_resource path="res://custom_resources/caret-right.svg" type="Texture" id=1] [ext_resource path="res://custom_resources/caret-down.svg" type="Texture" id=2] @@ -425,6 +425,20 @@ shadow_color = Color( 0.737255, 0.196078, 0.196078, 0.6 ) color = Color( 0.0980392, 0.392157, 0.235294, 1 ) vertical = true +[sub_resource type="StyleBoxFlat" id=40] +bg_color = Color( 0.882353, 0.882353, 0.882353, 1 ) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +border_color = Color( 0.0588235, 0.0588235, 0.0588235, 1 ) +corner_radius_top_left = 2 +corner_radius_top_right = 2 +corner_radius_bottom_right = 2 +corner_radius_bottom_left = 2 +corner_detail = 4 +expand_margin_top = 25.0 + [resource] resource_name = "Lapis Lazuli" Button/colors/font_color = Color( 0, 0, 0, 1 ) @@ -507,3 +521,4 @@ Tree/styles/title_button_hover = SubResource( 27 ) Tree/styles/title_button_normal = SubResource( 17 ) Tree/styles/title_button_pressed = SubResource( 28 ) VSeparator/styles/separator = SubResource( 19 ) +WindowDialog/styles/panel = SubResource( 40 ) diff --git a/godot/custom_resources/encounter_engine.html b/godot/custom_resources/encounter_engine.html index 49c23c4..e5a4a56 100644 --- a/godot/custom_resources/encounter_engine.html +++ b/godot/custom_resources/encounter_engine.html @@ -35,6 +35,36 @@ transition: max-height 0.5s ease-out; background-color: Thistle; } + +#popupBackground { + position: fixed; + z-index: 98; + top: 0; left: 0; + width: 100vw; height: 100vh; + align-items: center; justify-content: center; + background: rgba(0, 0, 0, 0.25); + display: flex; + opacity: 0; visibility: hidden; + transition: opacity 0.2s; +} + +#popupBackground.show { + opacity: 1; visibility: visible; +} + +#popupDialog { + position: relative; + z-index: 99; + min-width: 256px; max-width: 512px; + align-items: center; justify-content: center; + padding: 5px; + background: #fff; + border-radius: 10px; +} + +#popupText { + padding: 5px; +} + +
+
+
+ +
+
+
@@ -1083,13 +1044,19 @@ element.style.maxHeight = element.scrollHeight + "px"; } } - - - \ No newline at end of file diff --git a/godot/custom_resources/lapis_lazuli.tres b/godot/custom_resources/lapis_lazuli.tres index ec67b5d..441e447 100644 --- a/godot/custom_resources/lapis_lazuli.tres +++ b/godot/custom_resources/lapis_lazuli.tres @@ -1,4 +1,4 @@ -[gd_resource type="Theme" load_steps=30 format=2] +[gd_resource type="Theme" load_steps=31 format=2] [ext_resource path="res://custom_resources/NotoMono-Regular.tres" type="DynamicFont" id=1] [ext_resource path="res://custom_resources/NotoSerif-Bold.tres" type="DynamicFont" id=2] @@ -279,6 +279,21 @@ shadow_color = Color( 0.737255, 0.196078, 0.196078, 0.6 ) color = Color( 0.0980392, 0.392157, 0.235294, 1 ) vertical = true +[sub_resource type="StyleBoxFlat" id=22] +bg_color = Color( 0, 0.0627451, 0.12549, 1 ) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +border_color = Color( 0.0980392, 0.392157, 0.235294, 1 ) +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 +corner_detail = 4 +expand_margin_top = 25.0 +shadow_color = Color( 0.737255, 0.196078, 0.196078, 0.6 ) + [resource] resource_name = "Lapis Lazuli" Button/styles/disabled = SubResource( 1 ) @@ -323,3 +338,5 @@ Tree/constants/draw_relationship_lines = 1 Tree/styles/bg = SubResource( 5 ) Tree/styles/title_button_normal = SubResource( 17 ) VSeparator/styles/separator = SubResource( 19 ) +WindowDialog/colors/title_color = Color( 1, 1, 1, 1 ) +WindowDialog/styles/panel = SubResource( 22 ) diff --git a/godot/export_presets.cfg b/godot/export_presets.cfg index 98d3a32..e7c67ef 100644 --- a/godot/export_presets.cfg +++ b/godot/export_presets.cfg @@ -81,7 +81,7 @@ custom_features="" export_filter="all_resources" include_filter="*.html, *.json" exclude_filter="" -export_path="../Internal_TestBed/SweepWeave_Win_0_0_37.exe" +export_path="../Internal_TestBed/SweepWeave_Win_0_0_38.exe" script_export_mode=1 script_encryption_key="" @@ -107,8 +107,8 @@ codesign/description="" codesign/custom_options=PoolStringArray( ) application/modify_resources=true application/icon="res://custom_resources/ball_of_yarn.ico" -application/file_version="0.0.37.0" -application/product_version="0.0.37.0" +application/file_version="0.0.38.0" +application/product_version="0.0.38.0" application/company_name="Neon Hopscotch" application/product_name="SweepWeave" application/file_description="An application for creating storylet-based interactive storyworlds. Made with Godot Engine by Sasha Fenn." diff --git a/godot/project.godot b/godot/project.godot index 42c0c76..c73264c 100644 --- a/godot/project.godot +++ b/godot/project.godot @@ -12,7 +12,7 @@ _global_script_classes=[ { "base": "SWOperator", "class": "AbsoluteValueOperator", "language": "GDScript", -"path": "res://AbsoluteValueOperator.gd" +"path": "res://sw_scripting/AbsoluteValueOperator.gd" }, { "base": "Object", "class": "Actor", @@ -22,17 +22,17 @@ _global_script_classes=[ { "base": "SWOperator", "class": "ArithmeticComparator", "language": "GDScript", -"path": "res://ArithmeticComparator.gd" +"path": "res://sw_scripting/ArithmeticComparator.gd" }, { "base": "SWOperator", "class": "ArithmeticMeanOperator", "language": "GDScript", -"path": "res://ArithmeticMeanOperator.gd" +"path": "res://sw_scripting/ArithmeticMeanOperator.gd" }, { "base": "SWOperator", "class": "ArithmeticNegationOperator", "language": "GDScript", -"path": "res://ArithmeticNegationOperator.gd" +"path": "res://sw_scripting/ArithmeticNegationOperator.gd" }, { "base": "Object", "class": "AuthoredPropertySorter", @@ -47,7 +47,7 @@ _global_script_classes=[ { "base": "SWPointer", "class": "BNumberConstant", "language": "GDScript", -"path": "res://BNumberConstant.gd" +"path": "res://sw_scripting/BNumberConstant.gd" }, { "base": "SWEffect", "class": "BNumberEffect", @@ -57,27 +57,27 @@ _global_script_classes=[ { "base": "SWPointer", "class": "BNumberPointer", "language": "GDScript", -"path": "res://BNumberPointer.gd" +"path": "res://sw_scripting/BNumberPointer.gd" }, { "base": "SWOperator", "class": "BSumOperator", "language": "GDScript", -"path": "res://BSumOperator.gd" +"path": "res://sw_scripting/BSumOperator.gd" }, { "base": "SWOperator", "class": "BlendOperator", "language": "GDScript", -"path": "res://BlendOperator.gd" +"path": "res://sw_scripting/BlendOperator.gd" }, { "base": "SWOperator", "class": "BooleanComparator", "language": "GDScript", -"path": "res://BooleanComparator.gd" +"path": "res://sw_scripting/BooleanComparator.gd" }, { "base": "SWPointer", "class": "BooleanConstant", "language": "GDScript", -"path": "res://BooleanConstant.gd" +"path": "res://sw_scripting/BooleanConstant.gd" }, { "base": "Object", "class": "CharacterSorter", @@ -85,6 +85,11 @@ _global_script_classes=[ { "path": "res://CharacterSorter.gd" }, { "base": "Object", +"class": "Clipboard", +"language": "GDScript", +"path": "res://Clipboard.gd" +}, { +"base": "Object", "class": "Compiler", "language": "GDScript", "path": "res://Compiler.gd" @@ -92,7 +97,7 @@ _global_script_classes=[ { "base": "SWOperator", "class": "Desideratum", "language": "GDScript", -"path": "res://Desideratum.gd" +"path": "res://sw_scripting/Desideratum.gd" }, { "base": "Object", "class": "DocChapter", @@ -127,7 +132,7 @@ _global_script_classes=[ { "base": "SWPointer", "class": "EventPointer", "language": "GDScript", -"path": "res://EventPointer.gd" +"path": "res://sw_scripting/EventPointer.gd" }, { "base": "Object", "class": "HB_Record", @@ -147,7 +152,7 @@ _global_script_classes=[ { "base": "SWOperator", "class": "NudgeOperator", "language": "GDScript", -"path": "res://NudgeOperator.gd" +"path": "res://sw_scripting/NudgeOperator.gd" }, { "base": "Object", "class": "Option", @@ -172,47 +177,47 @@ _global_script_classes=[ { "base": "SWOperator", "class": "SWEqualsOperator", "language": "GDScript", -"path": "res://SWEqualsOperator.gd" +"path": "res://sw_scripting/SWEqualsOperator.gd" }, { "base": "SWOperator", "class": "SWIfOperator", "language": "GDScript", -"path": "res://SWIfOperator.gd" +"path": "res://sw_scripting/SWIfOperator.gd" }, { "base": "SWOperator", "class": "SWMaxOperator", "language": "GDScript", -"path": "res://SWMaxOperator.gd" +"path": "res://sw_scripting/SWMaxOperator.gd" }, { "base": "SWOperator", "class": "SWMinOperator", "language": "GDScript", -"path": "res://SWMinOperator.gd" +"path": "res://sw_scripting/SWMinOperator.gd" }, { "base": "SWOperator", "class": "SWNotOperator", "language": "GDScript", -"path": "res://SWNotOperator.gd" +"path": "res://sw_scripting/SWNotOperator.gd" }, { "base": "SWScriptElement", "class": "SWOperator", "language": "GDScript", -"path": "res://SWOperator.gd" +"path": "res://sw_scripting/SWOperator.gd" }, { "base": "SWScriptElement", "class": "SWPointer", "language": "GDScript", -"path": "res://SWPointer.gd" +"path": "res://sw_scripting/SWPointer.gd" }, { "base": "Object", "class": "SWScriptElement", "language": "GDScript", -"path": "res://SWScriptElement.gd" +"path": "res://sw_scripting/SWScriptElement.gd" }, { "base": "Object", "class": "ScriptManager", "language": "GDScript", -"path": "res://ScriptManager.gd" +"path": "res://sw_scripting/ScriptManager.gd" }, { "base": "Object", "class": "Spool", @@ -227,7 +232,7 @@ _global_script_classes=[ { "base": "SWPointer", "class": "SpoolPointer", "language": "GDScript", -"path": "res://SpoolPointer.gd" +"path": "res://sw_scripting/SpoolPointer.gd" }, { "base": "Object", "class": "SpoolSorter", @@ -237,7 +242,7 @@ _global_script_classes=[ { "base": "SWPointer", "class": "SpoolStatusPointer", "language": "GDScript", -"path": "res://SpoolStatusPointer.gd" +"path": "res://sw_scripting/SpoolStatusPointer.gd" }, { "base": "Object", "class": "Storyworld", @@ -247,17 +252,17 @@ _global_script_classes=[ { "base": "SWOperator", "class": "StringConcatenationOperator", "language": "GDScript", -"path": "res://StringConcatenationOperator.gd" +"path": "res://sw_scripting/StringConcatenationOperator.gd" }, { "base": "SWPointer", "class": "StringConstant", "language": "GDScript", -"path": "res://StringConstant.gd" +"path": "res://sw_scripting/StringConstant.gd" }, { "base": "SWOperator", "class": "StringFormatOperator", "language": "GDScript", -"path": "res://StringFormatOperator.gd" +"path": "res://sw_scripting/StringFormatOperator.gd" }, { "base": "Object", "class": "UUID", @@ -280,6 +285,7 @@ _global_script_class_icons={ "BooleanComparator": "", "BooleanConstant": "", "CharacterSorter": "", +"Clipboard": "", "Compiler": "", "Desideratum": "", "DocChapter": "", diff --git a/godot/AbsoluteValueOperator.gd b/godot/sw_scripting/AbsoluteValueOperator.gd similarity index 100% rename from godot/AbsoluteValueOperator.gd rename to godot/sw_scripting/AbsoluteValueOperator.gd diff --git a/godot/ArithmeticComparator.gd b/godot/sw_scripting/ArithmeticComparator.gd similarity index 100% rename from godot/ArithmeticComparator.gd rename to godot/sw_scripting/ArithmeticComparator.gd diff --git a/godot/ArithmeticMeanOperator.gd b/godot/sw_scripting/ArithmeticMeanOperator.gd similarity index 100% rename from godot/ArithmeticMeanOperator.gd rename to godot/sw_scripting/ArithmeticMeanOperator.gd diff --git a/godot/ArithmeticNegationOperator.gd b/godot/sw_scripting/ArithmeticNegationOperator.gd similarity index 100% rename from godot/ArithmeticNegationOperator.gd rename to godot/sw_scripting/ArithmeticNegationOperator.gd diff --git a/godot/BNumberConstant.gd b/godot/sw_scripting/BNumberConstant.gd similarity index 100% rename from godot/BNumberConstant.gd rename to godot/sw_scripting/BNumberConstant.gd diff --git a/godot/BNumberPointer.gd b/godot/sw_scripting/BNumberPointer.gd similarity index 100% rename from godot/BNumberPointer.gd rename to godot/sw_scripting/BNumberPointer.gd diff --git a/godot/BSumOperator.gd b/godot/sw_scripting/BSumOperator.gd similarity index 100% rename from godot/BSumOperator.gd rename to godot/sw_scripting/BSumOperator.gd diff --git a/godot/BlendOperator.gd b/godot/sw_scripting/BlendOperator.gd similarity index 100% rename from godot/BlendOperator.gd rename to godot/sw_scripting/BlendOperator.gd diff --git a/godot/BooleanComparator.gd b/godot/sw_scripting/BooleanComparator.gd similarity index 100% rename from godot/BooleanComparator.gd rename to godot/sw_scripting/BooleanComparator.gd diff --git a/godot/BooleanConstant.gd b/godot/sw_scripting/BooleanConstant.gd similarity index 100% rename from godot/BooleanConstant.gd rename to godot/sw_scripting/BooleanConstant.gd diff --git a/godot/Desideratum.gd b/godot/sw_scripting/Desideratum.gd similarity index 100% rename from godot/Desideratum.gd rename to godot/sw_scripting/Desideratum.gd diff --git a/godot/EventPointer.gd b/godot/sw_scripting/EventPointer.gd similarity index 100% rename from godot/EventPointer.gd rename to godot/sw_scripting/EventPointer.gd diff --git a/godot/NudgeOperator.gd b/godot/sw_scripting/NudgeOperator.gd similarity index 100% rename from godot/NudgeOperator.gd rename to godot/sw_scripting/NudgeOperator.gd diff --git a/godot/SWEqualsOperator.gd b/godot/sw_scripting/SWEqualsOperator.gd similarity index 100% rename from godot/SWEqualsOperator.gd rename to godot/sw_scripting/SWEqualsOperator.gd diff --git a/godot/SWIfOperator.gd b/godot/sw_scripting/SWIfOperator.gd similarity index 100% rename from godot/SWIfOperator.gd rename to godot/sw_scripting/SWIfOperator.gd diff --git a/godot/SWMaxOperator.gd b/godot/sw_scripting/SWMaxOperator.gd similarity index 100% rename from godot/SWMaxOperator.gd rename to godot/sw_scripting/SWMaxOperator.gd diff --git a/godot/SWMinOperator.gd b/godot/sw_scripting/SWMinOperator.gd similarity index 100% rename from godot/SWMinOperator.gd rename to godot/sw_scripting/SWMinOperator.gd diff --git a/godot/SWNotOperator.gd b/godot/sw_scripting/SWNotOperator.gd similarity index 100% rename from godot/SWNotOperator.gd rename to godot/sw_scripting/SWNotOperator.gd diff --git a/godot/SWOperator.gd b/godot/sw_scripting/SWOperator.gd similarity index 100% rename from godot/SWOperator.gd rename to godot/sw_scripting/SWOperator.gd diff --git a/godot/SWPointer.gd b/godot/sw_scripting/SWPointer.gd similarity index 100% rename from godot/SWPointer.gd rename to godot/sw_scripting/SWPointer.gd diff --git a/godot/SWScriptElement.gd b/godot/sw_scripting/SWScriptElement.gd similarity index 100% rename from godot/SWScriptElement.gd rename to godot/sw_scripting/SWScriptElement.gd diff --git a/godot/ScriptManager.gd b/godot/sw_scripting/ScriptManager.gd similarity index 99% rename from godot/ScriptManager.gd rename to godot/sw_scripting/ScriptManager.gd index e5a61be..ff991fd 100644 --- a/godot/ScriptManager.gd +++ b/godot/sw_scripting/ScriptManager.gd @@ -685,7 +685,7 @@ func load_from_json_v0_0_21_through_v0_0_29(storyworld, data_to_load, expected_o else: set_contents(parsed_script) -func recursive_load_from_json_v0_0_34_through_v0_0_37(storyworld, data_to_load): +func recursive_load_from_json_v0_0_34_through_v0_0_38(storyworld, data_to_load): var element = null if (TYPE_BOOL == typeof(data_to_load)): #Data should be either a boolean value, (true or false,) or a dictionary. @@ -723,7 +723,7 @@ func recursive_load_from_json_v0_0_34_through_v0_0_37(storyworld, data_to_load): #Parse operands: var operands = [] for operand in data_to_load["operands"]: - var parsed_operand = recursive_load_from_json_v0_0_34_through_v0_0_37(storyworld, operand) + var parsed_operand = recursive_load_from_json_v0_0_34_through_v0_0_38(storyworld, operand) if (null != parsed_operand and parsed_operand is SWScriptElement): operands.append(parsed_operand) #Create operator: @@ -769,8 +769,8 @@ func recursive_load_from_json_v0_0_34_through_v0_0_37(storyworld, data_to_load): element = NudgeOperator.new(operands.pop_front(), operands.pop_front()) return proofread(element) -func load_from_json_v0_0_34_through_v0_0_37(storyworld, data_to_load, expected_output_datatype): - var parsed_script = recursive_load_from_json_v0_0_34_through_v0_0_37(storyworld, data_to_load) +func load_from_json_v0_0_34_through_v0_0_38(storyworld, data_to_load, expected_output_datatype): + var parsed_script = recursive_load_from_json_v0_0_34_through_v0_0_38(storyworld, data_to_load) if (null == parsed_script): if (sw_script_data_types.BNUMBER == expected_output_datatype): # print ("Warning, script has null or invalid contents. Setting script contents to bounded number constant to match expected output datatype.") diff --git a/godot/SpoolPointer.gd b/godot/sw_scripting/SpoolPointer.gd similarity index 100% rename from godot/SpoolPointer.gd rename to godot/sw_scripting/SpoolPointer.gd diff --git a/godot/SpoolStatusPointer.gd b/godot/sw_scripting/SpoolStatusPointer.gd similarity index 100% rename from godot/SpoolStatusPointer.gd rename to godot/sw_scripting/SpoolStatusPointer.gd diff --git a/godot/StringConcatenationOperator.gd b/godot/sw_scripting/StringConcatenationOperator.gd similarity index 100% rename from godot/StringConcatenationOperator.gd rename to godot/sw_scripting/StringConcatenationOperator.gd diff --git a/godot/StringConstant.gd b/godot/sw_scripting/StringConstant.gd similarity index 100% rename from godot/StringConstant.gd rename to godot/sw_scripting/StringConstant.gd diff --git a/godot/StringFormatOperator.gd b/godot/sw_scripting/StringFormatOperator.gd similarity index 100% rename from godot/StringFormatOperator.gd rename to godot/sw_scripting/StringFormatOperator.gd