Skip to content

Commit

Permalink
Add configuration to GSS Mod Manager
Browse files Browse the repository at this point in the history
- Changed `GraphicsAPI` to `dx11` in `UE4SS-settings.ini` (bundled)
- Added configuration to GSS Mod Manager:
  - Check for updates (on/off)
  - Launch GSS with GUI console (on/off)
- Made GSS Mod Manager responsive when notepad with the config is opened
- Added the update body to the update pop-up
  • Loading branch information
nieboczek committed Nov 9, 2024
1 parent ab9497f commit 389d3e6
Show file tree
Hide file tree
Showing 4 changed files with 182 additions and 28 deletions.
6 changes: 3 additions & 3 deletions scenes/config_field_container.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ line_spacing = -6.0
font_color = Color(0.753984, 0.753984, 0.753984, 1)

[node name="ConfigFieldContainer" type="VBoxContainer"]
custom_minimum_size = Vector2(600, 61)
offset_right = 42.0
offset_bottom = 34.0
custom_minimum_size = Vector2(600, 69)
offset_right = 600.0
offset_bottom = 69.0
theme = ExtResource("1_1skrl")
script = ExtResource("1_2i062")

Expand Down
83 changes: 74 additions & 9 deletions scenes/mod_manager.tscn
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
[gd_scene load_steps=7 format=3 uid="uid://c6570n2s1k1wv"]
[gd_scene load_steps=9 format=3 uid="uid://c6570n2s1k1wv"]

[ext_resource type="Theme" uid="uid://dged4041swr1" path="res://theme.tres" id="1_1wikn"]
[ext_resource type="Script" path="res://scripts/mod_manager.gd" id="2_37t4h"]
[ext_resource type="Script" path="res://scripts/path_container.gd" id="3_a8731"]
[ext_resource type="Script" path="res://scripts/mod_loader_container.gd" id="4_vi72b"]
[ext_resource type="Script" path="res://scripts/mod_list_container.gd" id="5_pbjar"]
[ext_resource type="StyleBox" uid="uid://dl64sodill7qu" path="res://panel_style_box.tres" id="6_7hd73"]
[ext_resource type="Script" path="res://scripts/mod_manager_config_container.gd" id="7_wuify"]

[sub_resource type="LabelSettings" id="LabelSettings_g2u8q"]
line_spacing = -6.0
font_color = Color(0.753984, 0.753984, 0.753984, 1)

[node name="ModManager" type="Control"]
layout_mode = 3
Expand Down Expand Up @@ -136,12 +141,59 @@ layout_mode = 2
visible = false
layout_mode = 2
size_flags_vertical = 3
theme_override_constants/separation = 24
script = ExtResource("7_wuify")

[node name="CheckForUpdates" type="VBoxContainer" parent="PanelMarginContainer/PanelContainer/MarginContainer/ConfigContainer/ModManagerConfigContainer"]
layout_mode = 2

[node name="OptionsContainer" type="HBoxContainer" parent="PanelMarginContainer/PanelContainer/MarginContainer/ConfigContainer/ModManagerConfigContainer/CheckForUpdates"]
layout_mode = 2

[node name="Label" type="Label" parent="PanelMarginContainer/PanelContainer/MarginContainer/ConfigContainer/ModManagerConfigContainer/CheckForUpdates/OptionsContainer"]
layout_mode = 2
text = "Check for updates"

[node name="CheckBox" type="CheckBox" parent="PanelMarginContainer/PanelContainer/MarginContainer/ConfigContainer/ModManagerConfigContainer/CheckForUpdates/OptionsContainer"]
layout_mode = 2
size_flags_horizontal = 3
button_pressed = true

[node name="ResetToDefault" type="Button" parent="PanelMarginContainer/PanelContainer/MarginContainer/ConfigContainer/ModManagerConfigContainer/CheckForUpdates/OptionsContainer"]
layout_mode = 2
text = "Reset to default"

[node name="DescriptionLabel" type="Label" parent="PanelMarginContainer/PanelContainer/MarginContainer/ConfigContainer/ModManagerConfigContainer/CheckForUpdates"]
layout_mode = 2
theme_override_colors/font_color = Color(0.712129, 0.712129, 0.712129, 1)
theme_override_font_sizes/font_size = 16
text = "Should GSS Mod Manager check for updates when started?"
label_settings = SubResource("LabelSettings_g2u8q")

[node name="NoticeLabel" type="Label" parent="PanelMarginContainer/PanelContainer/MarginContainer/ConfigContainer/ModManagerConfigContainer"]
[node name="LaunchGSSWithGUIConsole" type="VBoxContainer" parent="PanelMarginContainer/PanelContainer/MarginContainer/ConfigContainer/ModManagerConfigContainer"]
layout_mode = 2
text = "Nothing to configure here right now!

TODO: Add configuration"
[node name="OptionsContainer" type="HBoxContainer" parent="PanelMarginContainer/PanelContainer/MarginContainer/ConfigContainer/ModManagerConfigContainer/LaunchGSSWithGUIConsole"]
layout_mode = 2

[node name="Label" type="Label" parent="PanelMarginContainer/PanelContainer/MarginContainer/ConfigContainer/ModManagerConfigContainer/LaunchGSSWithGUIConsole/OptionsContainer"]
layout_mode = 2
text = "Launch GSS with GUI console"

[node name="CheckBox" type="CheckBox" parent="PanelMarginContainer/PanelContainer/MarginContainer/ConfigContainer/ModManagerConfigContainer/LaunchGSSWithGUIConsole/OptionsContainer"]
layout_mode = 2
size_flags_horizontal = 3

[node name="ResetToDefault" type="Button" parent="PanelMarginContainer/PanelContainer/MarginContainer/ConfigContainer/ModManagerConfigContainer/LaunchGSSWithGUIConsole/OptionsContainer"]
layout_mode = 2
text = "Reset to default"

[node name="DescriptionLabel" type="Label" parent="PanelMarginContainer/PanelContainer/MarginContainer/ConfigContainer/ModManagerConfigContainer/LaunchGSSWithGUIConsole"]
layout_mode = 2
theme_override_colors/font_color = Color(0.712129, 0.712129, 0.712129, 1)
theme_override_font_sizes/font_size = 16
text = "Should Grocery Store Simulator launch with a debugging GUI console?"
label_settings = SubResource("LabelSettings_g2u8q")

[node name="ScrollContainer" type="ScrollContainer" parent="PanelMarginContainer/PanelContainer/MarginContainer/ConfigContainer"]
visible = false
Expand Down Expand Up @@ -190,22 +242,31 @@ theme_override_styles/panel = ExtResource("6_7hd73")

[node name="MainContainer" type="VBoxContainer" parent="PopupMarginContainer/PanelContainer"]
layout_mode = 2
theme_override_constants/separation = 20
alignment = 1

[node name="UpdateLabel" type="Label" parent="PopupMarginContainer/PanelContainer/MainContainer"]
layout_mode = 2
text = "A new version of GSS Mod Manager is avaliable!
(current: ; latest: )"
(current: ; latest: )
Update description:"
horizontal_alignment = 1

[node name="DescriptionMargin" type="MarginContainer" parent="PopupMarginContainer/PanelContainer/MainContainer"]
layout_mode = 2
theme_override_constants/margin_left = 16
theme_override_constants/margin_right = 16
theme_override_constants/margin_bottom = 24

[node name="UpdateDescriptionLabel" type="Label" parent="PopupMarginContainer/PanelContainer/MainContainer/DescriptionMargin"]
layout_mode = 2

[node name="ControlsContainer" type="HBoxContainer" parent="PopupMarginContainer/PanelContainer/MainContainer"]
layout_mode = 2
alignment = 1

[node name="OpenLinkButton" type="Button" parent="PopupMarginContainer/PanelContainer/MainContainer/ControlsContainer"]
[node name="OpenUpdateLinkButton" type="Button" parent="PopupMarginContainer/PanelContainer/MainContainer/ControlsContainer"]
layout_mode = 2
text = "Open link"
text = "Open update link"

[node name="CloseButton" type="Button" parent="PopupMarginContainer/PanelContainer/MainContainer/ControlsContainer"]
layout_mode = 2
Expand All @@ -229,10 +290,14 @@ use_native_dialog = true
[connection signal="pressed" from="MarginContainer/MainContainer/ModListContainer/RefreshButton" to="MarginContainer/MainContainer/ModListContainer" method="_on_refresh_button_pressed"]
[connection signal="pressed" from="MarginContainer/MainContainer/ModListContainer/InstallModButton" to="MarginContainer/MainContainer/ModListContainer" method="_on_install_mod_button_pressed"]
[connection signal="pressed" from="MarginContainer/MainContainer/ModManagerContainer/ConfigureButton" to="." method="_on_configure_button_pressed"]
[connection signal="toggled" from="PanelMarginContainer/PanelContainer/MarginContainer/ConfigContainer/ModManagerConfigContainer/CheckForUpdates/OptionsContainer/CheckBox" to="PanelMarginContainer/PanelContainer/MarginContainer/ConfigContainer/ModManagerConfigContainer" method="_on_check_for_updates_toggled"]
[connection signal="pressed" from="PanelMarginContainer/PanelContainer/MarginContainer/ConfigContainer/ModManagerConfigContainer/CheckForUpdates/OptionsContainer/ResetToDefault" to="PanelMarginContainer/PanelContainer/MarginContainer/ConfigContainer/ModManagerConfigContainer" method="_on_reset_check_for_updates_pressed"]
[connection signal="toggled" from="PanelMarginContainer/PanelContainer/MarginContainer/ConfigContainer/ModManagerConfigContainer/LaunchGSSWithGUIConsole/OptionsContainer/CheckBox" to="PanelMarginContainer/PanelContainer/MarginContainer/ConfigContainer/ModManagerConfigContainer" method="_on_launch_gss_with_gui_console_toggled"]
[connection signal="pressed" from="PanelMarginContainer/PanelContainer/MarginContainer/ConfigContainer/ModManagerConfigContainer/LaunchGSSWithGUIConsole/OptionsContainer/ResetToDefault" to="PanelMarginContainer/PanelContainer/MarginContainer/ConfigContainer/ModManagerConfigContainer" method="_on_reset_launch_gss_with_gui_console_pressed"]
[connection signal="pressed" from="PanelMarginContainer/PanelContainer/MarginContainer/ConfigContainer/ConfigControls/SaveButton" to="." method="_on_save_config_button_pressed"]
[connection signal="pressed" from="PanelMarginContainer/PanelContainer/MarginContainer/ConfigContainer/ConfigControls/CancelButton" to="." method="_on_cancel_config_button_pressed"]
[connection signal="pressed" from="PanelMarginContainer/PanelContainer/MarginContainer/ConfigContainer/ConfigControls/CopyLogButton" to="." method="_on_copy_log_button_pressed"]
[connection signal="pressed" from="PopupMarginContainer/PanelContainer/MainContainer/ControlsContainer/OpenLinkButton" to="." method="_on_open_link_button_pressed"]
[connection signal="pressed" from="PopupMarginContainer/PanelContainer/MainContainer/ControlsContainer/OpenUpdateLinkButton" to="." method="_on_open_update_link_button_pressed"]
[connection signal="pressed" from="PopupMarginContainer/PanelContainer/MainContainer/ControlsContainer/CloseButton" to="." method="_on_update_close_button_pressed"]
[connection signal="dir_selected" from="FileDialog" to="." method="_on_file_dialog_gss_path_selected"]
[connection signal="file_selected" from="FileDialog" to="MarginContainer/MainContainer/ModListContainer" method="_on_file_dialog_mod_selected"]
Expand Down
38 changes: 22 additions & 16 deletions scripts/mod_manager.gd
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class_name ModManager extends Control
@onready var mod_config_container = $PanelMarginContainer/PanelContainer/MarginContainer/ConfigContainer/ScrollContainer/ModConfigContainer
@onready var mod_config_scroll_container = $PanelMarginContainer/PanelContainer/MarginContainer/ConfigContainer/ScrollContainer
@onready var copy_log_button = $PanelMarginContainer/PanelContainer/MarginContainer/ConfigContainer/ConfigControls/CopyLogButton
@onready var update_description_label = $PopupMarginContainer/PanelContainer/MainContainer/DescriptionMargin/UpdateDescriptionLabel
@onready var update_label = $PopupMarginContainer/PanelContainer/MainContainer/UpdateLabel
@onready var popup = $PopupMarginContainer
@onready var mod_containers: Control = main.get_node("MarginContainer/ScrollContainer/ModContainers")
Expand Down Expand Up @@ -40,7 +41,7 @@ const BUILTIN_MODS: Array[String] = [
"CheatManagerEnablerMod", "ConsoleCommandsMod", "ConsoleEnablerMod",
"jsbLuaProfilerMod", "Keybinds", "LineTraceMod", "SplitScreenMod"
]
const VERSION: String = "v0.5.0"
const VERSION: String = "v0.6.0"

# NOTE: Things like installing the mod loader and installing mods only work in exported.

Expand Down Expand Up @@ -138,20 +139,19 @@ func _on_configure_mod(mod_name: String) -> void:
var fields = ConfigParser.parse(ue_root, mod_name)
if fields.is_empty():
var label = Label.new()
label.text = "Couldn't parse config, a new notepad window has been opened.\n" + \
"The Mod Manager will be unresponsive until you close notepad.\n\n" + \
"Config parser log (there's a Copy log button below, send to #support on Discord):\n" + \
ConfigParser.logs
label.text = \
"Couldn't parse config, a new notepad window has been opened.\n" + \
"Edit the config in notepad, then save and close notepad.\n\n" + \
"Config parser log (there's a Copy log button below, send to #support on Discord):\n" + \
ConfigParser.logs

copy_log_button.show()
mod_config_container.add_child(label)
config_panel.show()
mod_config_scroll_container.show()
main.hide()

# OS tries to execute notepad faster than the above takes effect
await get_tree().create_timer(0.01).timeout
OS.execute("notepad", [ue_root + "/Mods/%s/Scripts/config.lua" % mod_name])
OS.execute_with_pipe("notepad", [ue_root + "/Mods/%s/Scripts/config.lua" % mod_name])
else:
for field in fields:
var container = ConfigFieldContainer.with(field)
Expand Down Expand Up @@ -210,7 +210,7 @@ func _ready() -> void:
var err := config.load("user://config")
if err == ERR_FILE_NOT_FOUND:
path_container.detect_gss()
else:
elif err != OK:
error("Read user config", err)

var path: String = config.get_value("main", "gss_path")
Expand All @@ -219,9 +219,12 @@ func _ready() -> void:
else:
gss_path = path

error("Read mod manager config", mod_manager_config_container.load_from(ue_root, config))
mod_manager_label.text = "GSS Mod Manager " + VERSION
err = http.request("https://api.github.com/repos/nieboczek/gss-mod-manager/releases/latest")
error("Initiate HTTP request", err)

if mod_manager_config_container.check_for_updates:
err = http.request("https://api.github.com/repos/nieboczek/gss-mod-manager/releases/latest")
error("Initiate HTTP request", err)

## Returns a boolean that if is true, action didn't complete successfully
func error(action: String, err: Error) -> bool:
Expand All @@ -243,10 +246,12 @@ func _on_save_config_button_pressed() -> void:
configured_mod = ""
hide_config_ui()
else:
# Saving for Mod Manager config here
error("Save mod manager config", mod_manager_config_container.save(ue_root, config))
hide_config_ui()

func _on_cancel_config_button_pressed() -> void:
if configured_mod.is_empty():
mod_manager_config_container.cancel()
hide_config_ui()

func hide_config_ui() -> void:
Expand All @@ -260,19 +265,20 @@ func hide_config_ui() -> void:
mod_manager_config_container.hide()

func _on_copy_log_button_pressed() -> void:
# Does magic Discord formatting and copies to clipboard
DisplayServer.clipboard_set("Config parser log:\n```d\n%s```" % ConfigParser.logs)

func _on_http_request_completed(result: int, response_code: int, headers: PackedStringArray, body: PackedByteArray) -> void:
func _on_http_request_completed(result: int, _response_code: int, _headers: PackedStringArray, body: PackedByteArray) -> void:
if !error("Request update data", result):
var json = JSON.parse_string(body.get_string_from_utf8())
if json and json["tag_name"] != VERSION:
update_label.text = \
"A new version of GSS Mod Manager is avaliable!\n" + \
"(current: %s; latest: %s)" % [VERSION, json["tag_name"]]
"(current: %s; latest: %s)\n" % [VERSION, json["tag_name"]] + \
"Update description:"
update_description_label.text = json["body"]
popup.show()

func _on_open_link_button_pressed() -> void:
func _on_open_update_link_button_pressed() -> void:
OS.shell_open("https://github.com/nieboczek/gss-mod-manager/releases/latest")

func _on_update_close_button_pressed() -> void:
Expand Down
83 changes: 83 additions & 0 deletions scripts/mod_manager_config_container.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
extends VBoxContainer

@onready var check_for_updates_checkbox = $CheckForUpdates/OptionsContainer/CheckBox
@onready var launch_gss_with_gui_console_checkbox = $LaunchGSSWithGUIConsole/OptionsContainer/CheckBox

var changed_values: Dictionary = {}
var ue4ss_setting_lines: Array[String] = []
var check_for_updates: bool

func save(ue_root: String, config: ConfigFile) -> Error:
for value_name in changed_values:
var value = changed_values[value_name]
match value_name:
"check_for_updates": check_for_updates = value
"launch_gss_with_gui_console":
var err = save_launch_gss_with_gui_console(ue_root, value)
if err: return err
continue
_:
push_error("Unknown value name with no handler: " + value_name)
return ERR_METHOD_NOT_FOUND

config.set_value("main", value_name, value)

config.save("user://config")
return OK

func cancel() -> void:
changed_values = {}

func load_from(ue_root: String, config: ConfigFile) -> Error:
check_for_updates = config.get_value("main", "check_for_updates", true)
check_for_updates_checkbox.button_pressed = check_for_updates

var err = load_launch_gss_with_gui_console(ue_root)
if err: return err

return OK

func save_launch_gss_with_gui_console(ue_root: String, value: bool) -> Error:
var file = FileAccess.open(ue_root + "/UE4SS-settings.ini", FileAccess.WRITE)
if file:
for i in range(len(ue4ss_setting_lines)):
if ue4ss_setting_lines[i].begins_with("GuiConsoleVisible"):
ue4ss_setting_lines[i] = "GuiConsoleVisible = " + '1' if value else '0'

file.store_string(ue4ss_setting_lines[i])
if i < len(ue4ss_setting_lines) - 1:
file.store_string("\n")

file.close()
return OK
else:
return FileAccess.get_open_error()

func load_launch_gss_with_gui_console(ue_root: String) -> Error:
var file = FileAccess.open(ue_root + "/UE4SS-settings.ini", FileAccess.READ)
if file:
while not file.eof_reached():
ue4ss_setting_lines.append(file.get_line())
file.close()

for i in range(len(ue4ss_setting_lines)):
if ue4ss_setting_lines[i].begins_with("GuiConsoleVisible"):
launch_gss_with_gui_console_checkbox.button_pressed = \
ue4ss_setting_lines[i].replace("GuiConsoleVisible = ", "") == '1'
break

return OK
else:
return FileAccess.get_open_error()

func _on_check_for_updates_toggled(toggled_on: bool) -> void:
changed_values["check_for_updates"] = toggled_on

func _on_reset_check_for_updates_pressed() -> void:
changed_values["check_for_updates"] = true

func _on_launch_gss_with_gui_console_toggled(toggled_on: bool) -> void:
changed_values["launch_gss_with_gui_console"] = toggled_on

func _on_reset_launch_gss_with_gui_console_pressed() -> void:
changed_values["launch_gss_with_gui_console"] = false

0 comments on commit 389d3e6

Please sign in to comment.