alter vatter

This commit is contained in:
2026-07-29 18:50:14 +02:00
parent 59a9516d99
commit 9824b30435
53 changed files with 1054 additions and 69 deletions

View File

@@ -0,0 +1,66 @@
@tool
class_name EditorSettingsUtil
# this is rider own setting, not a part of Godot settings
const EXTERNAL_EDITOR_SETTING: String = "text_editor/external/editor"
# this is Godot setting
const EXEC_PATH_SETTING: String = "text_editor/external/exec_path"
static func set_external_editor_path(path: String) -> void:
var editor_settings := EditorInterface.get_editor_settings()
editor_settings.set_setting(EXEC_PATH_SETTING, path)
static func get_external_editor_path() -> String:
var editor_settings := EditorInterface.get_editor_settings()
if editor_settings.has_setting(EXEC_PATH_SETTING):
return editor_settings.get_setting(EXEC_PATH_SETTING)
else:
return ""
# Returns the current dropdown index, 0 if the setting doesn't exist.
static func get_rider_selector_index() -> int:
var editor_settings := EditorInterface.get_editor_settings()
if not editor_settings.has_setting(EXTERNAL_EDITOR_SETTING):
return 0
return editor_settings.get_setting(EXTERNAL_EDITOR_SETTING)
static func erase_rider_external_editor_setting() -> void:
var editor_settings := EditorInterface.get_editor_settings()
if editor_settings.has_setting(EXTERNAL_EDITOR_SETTING):
editor_settings.erase(EXTERNAL_EDITOR_SETTING)
# Register a single-entry enum so the persisted int doesn't render as a raw
# number while async detection is in progress. register_rider_installations
# replaces this once detection finishes.
static func show_rider_searching_state() -> void:
# Order matters: `set` must come before `add_property_info` — the latter
# errors with `!props.has(pinfo.name)` if the property isn't in `props` yet.
var editor_settings := EditorInterface.get_editor_settings()
editor_settings.set(EXTERNAL_EDITOR_SETTING, 0)
editor_settings.add_property_info({
"name": EXTERNAL_EDITOR_SETTING,
"type": TYPE_INT,
"hint": PROPERTY_HINT_ENUM,
"hint_string": "Searching — reopen Settings to see the update",
})
# Register the dropdown with one entry per detected installation (plus a "-"
# placeholder at index 0) and select the given index.
static func register_rider_installations(installations: Array, selected_index: int) -> void:
var editor_settings := EditorInterface.get_editor_settings()
var entries: Array = ["-"]
for element in installations:
var display_name: String = element.get("display", "")
entries.append(_escape_enum_label(display_name))
editor_settings.set(EXTERNAL_EDITOR_SETTING, selected_index)
editor_settings.add_property_info({
"name": EXTERNAL_EDITOR_SETTING,
"type": TYPE_INT,
"hint": PROPERTY_HINT_ENUM,
"hint_string": ",".join(entries),
})
# Comma is the enum delimiter, colon introduces explicit value assignment.
static func _escape_enum_label(s: String) -> String:
return s.replace(",", "").replace(":", " -")

View File

@@ -0,0 +1 @@
uid://bdiu78ot0rrkc

View File

@@ -0,0 +1,23 @@
@tool
## Simple JSON helpers for editor/runtime use.
## Keeps file and JSON parsing concerns out of feature code.
class_name JsonUtils
static func load_from_file(path: String) -> Variant:
# Returns parsed JSON value (Dictionary/Array/etc.) or null on error.
var file := FileAccess.open(path, FileAccess.READ)
if file == null:
push_warning("JsonUtils: Failed to open file: %s" % path)
return null
var text := file.get_as_text()
file.close()
var data: Variant = JSON.parse_string(text)
if data == null:
push_warning("JsonUtils: Invalid JSON in file: %s" % path)
return null
return data
static func load_dict_from_file(path: String) -> Dictionary:
# Returns Dictionary or empty {} on error.
var data := load_from_file(path) as Dictionary
return data

View File

@@ -0,0 +1 @@
uid://bci4kmk7h4j6a

View File

@@ -0,0 +1,68 @@
@tool
extends RefCounted
class_name RiderLocatorService
var _installations_found: Array = []
# we can keep a reference, it will be freed automatically, when the editor is closed
var _rider_locator: RefCounted = null
# Last value we wrote to / observed for the Rider selector dropdown
var _last_selected_index: int = 0
func start_search() -> void:
# use ClassDB to somehow still work without GDExtension part (in older Godot versions)
if not ClassDB.class_exists("RiderLocator"):
return
EditorSettingsUtil.show_rider_searching_state()
if _rider_locator == null:
_rider_locator = ClassDB.instantiate("RiderLocator")
_rider_locator.connect("installations_loaded", _on_installations_loaded)
_rider_locator.start_search()
func _on_installations_loaded(array: Array) -> void:
_installations_found = array
_update_selector()
func _update_selector() -> void:
if _installations_found.is_empty():
EditorSettingsUtil.erase_rider_external_editor_setting()
return
var index := _index_for_exec_path(_installations_found)
# Set _last_selected_index BEFORE register_rider_installations so the
# synchronous settings_changed handler sees a match and skips its work.
_last_selected_index = index
EditorSettingsUtil.register_rider_installations(_installations_found, index)
var settings_changed := EditorInterface.get_editor_settings().settings_changed
if not settings_changed.is_connected(_on_selection_changed):
settings_changed.connect(_on_selection_changed)
func _index_for_exec_path(installations: Array) -> int:
var current := EditorSettingsUtil.get_external_editor_path()
if current.is_empty():
return 0
for i in installations.size():
if installations[i].get("path", "") == current:
return i + 1
return 0
func _on_selection_changed() -> void:
var selected_index := EditorSettingsUtil.get_rider_selector_index()
# settings_changed fires for every editor setting, this helps to avoid updating on every other changes
if selected_index == _last_selected_index:
return
_last_selected_index = selected_index
# Index 0 is the placeholder, so the path is left untouched.
if selected_index == 0:
return
var installation_index := selected_index - 1
if installation_index >= 0 and installation_index < _installations_found.size():
var installation = _installations_found[installation_index]
var new_path: String = installation.get("path", "")
if not new_path.is_empty():
EditorSettingsUtil.set_external_editor_path(new_path)

View File

@@ -0,0 +1 @@
uid://cfsu1rbg0ypem

View File

@@ -0,0 +1,35 @@
@tool
extends RefCounted
class_name PresetApplier
var presets_path: String
func _init(p_path: String) -> void:
presets_path = p_path
func get_preset_key(is_active: bool) -> String:
return "on" if is_active else "off"
func apply_preset(editor_settings: EditorSettings, is_active: bool) -> void:
var data: Dictionary = JsonUtils.load_dict_from_file(presets_path)
if data.is_empty():
push_warning("Failed to load presets: %s" % presets_path)
return
var new_preset_key := get_preset_key(is_active)
var previous_preset_key := get_preset_key(not is_active)
if not data.has(new_preset_key):
push_warning("Preset '%s' not found in presets.json" % new_preset_key)
return
var new_preset := data[new_preset_key] as Dictionary
# Reset keys from previous preset that are missing in the new preset
if data.has(previous_preset_key):
var previous_preset := data[previous_preset_key] as Dictionary
for key in previous_preset:
if not new_preset.has(key):
editor_settings.set_setting(str(key), editor_settings.property_get_revert(str(key)))
# Apply the new preset
for key in new_preset:
editor_settings.set_setting(str(key), new_preset[key])

View File

@@ -0,0 +1 @@
uid://bjiaycxso8h8u