Skill v1.0.1
Automated scan100/10013 files
version: "1.0.1" name: godot-platform-desktop description: "Expert blueprint for desktop platforms (Windows/Linux/macOS) covering keyboard/mouse controls, settings menus, window management (fullscreen, resolution), keybind remapping, and Steam integration. Use when targeting PC platforms or implementing desktop-specific features. Keywords desktop, Windows, Linux, macOS, settings, keybinds, ConfigFile, DisplayServer, Steam, fullscreen."
Platform: Desktop
Settings flexibility, window management, and kb/mouse precision define desktop gaming.
NEVER Do (Expert Desktop Rules)
Window & Display
- NEVER hardcode resolution or fullscreen modes — A 1920x1080 fullscreen on a 4K monitor is blurry. Always provide a settings menu with a resolution dropdown and a mode toggle.
- NEVER ignore DPI scale factors — Manually centering windows without
DisplayServer.screen_get_scale()results in incorrect positioning on HiDPI displays. - NEVER skip a borderless window option — Exclusive fullscreen can break multi-monitor focus. Offer
WINDOW_MODE_FULLSCREEN(borderless).
Input & Persistence
- NEVER use `keycode` for movement rebinds — Use
physical_keycodeto ensure WASD works correctly across international keyboard layouts (AZERTY/Dvorak). - NEVER save settings or user data to `res://` — Filesystem is read-only in exported releases. Always use
user://. - NEVER skip `NOTIFICATION_WM_CLOSE_REQUEST` — Failing to handle quit signals causes data loss. Intercept and flush and ConfigFile data before
get_tree().quit().
Performance & Integration
- NEVER run utility tools at max framerate — Enable
OS.low_processor_usage_modeto prevent high GPU heat in static desktop apps. - NEVER call proprietary SDKs (Steam/Epic) directly — Always wrap in
Engine.has_singleton()to prevent crashes in non-store builds. - NEVER block the main thread with massive I/O — Deserializing 100MB+ configs stalls the engine. Offload to
WorkerThreadPool.
Available Scripts
MANDATORY: Read the appropriate script before implementing the corresponding pattern.
desktop_window_manager.gd
Expert DPI-aware multi-monitor window positioning using DisplayServer.
desktop_settings_persistent.gd
Production settings persistence using ConfigFile for persistent INI data.
physical_input_rebinder.gd
Expert positional rebind system using physical_keycode for AZERTY/Dvorak.
platform_sdk_wrapper.gd
Safe PC SDK singleton wrapper (Steamworks/Epic) with crash guards.
native_dialog_helper.gd
Expert native OS file dialogs and system alerts logic.
secondary_window_spawner.gd
True multi-window management for secondary Viewports/Windows.
graceful_shutdown_handler.gd
Safe close-request interceptor for data flushing and exit guards.
low_processor_eco_mode.gd
Eco mode optimization for desktop tools and launchers.
desktop_performance_monitor.gd
OS-level hardware detection for dynamic graphics presets.
native_shell_executor.gd
Expert native shell command execution and output capture.
# settings.gdextends Controlfunc _ready() -> void:load_settings()apply_settings()func load_settings() -> void:var config := ConfigFile.new()config.load("user://settings.cfg")$Graphics/ResolutionDropdown.selected = config.get_value("graphics", "resolution", 0)$Graphics/FullscreenCheck.button_pressed = config.get_value("graphics", "fullscreen", false)$Audio/MasterSlider.value = config.get_value("audio", "master_volume", 1.0)func save_settings() -> void:var config := ConfigFile.new()config.set_value("graphics", "resolution", $Graphics/ResolutionDropdown.selected)config.set_value("graphics", "fullscreen", $Graphics/FullscreenCheck.button_pressed)config.set_value("audio", "master_volume", $Audio/MasterSlider.value)config.save("user://settings.cfg")func apply_settings() -> void:# Resolutionvar resolutions := [Vector2i(1920, 1080), Vector2i(2560, 1440), Vector2i(3840, 2160)]var resolution := resolutions[$Graphics/ResolutionDropdown.selected]get_window().size = resolution# Fullscreenif $Graphics/FullscreenCheck.button_pressed:DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN)else:DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)# AudioAudioServer.set_bus_volume_db(0, linear_to_db($Audio/MasterSlider.value))
Keyboard Remapping
# Allow players to rebind keysfunc rebind_action(action: String, new_key: Key) -> void:# Remove existingInputMap.action_erase_events(action)# Add newvar event := InputEventKey.new()event.keycode = new_keyInputMap.action_add_event(action, event)# Savesave_input_map()
Window Management
# Toggle fullscreenfunc toggle_fullscreen() -> void:if DisplayServer.window_get_mode() == DisplayServer.WINDOW_MODE_FULLSCREEN:DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)else:DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN)
Steam Integration (if using)
# Using GodotSteam pluginvar steam_id: intfunc _ready() -> void:if Steam.isSteamRunning():steam_id = Steam.getSteamID()Steam.achievement_progress.connect(_on_achievement_progress)func unlock_achievement(name: String) -> void:Steam.setAchievement(name)Steam.storeStats()
Best Practices
- Settings - Extensive graphics/audio options
- Keybinds - Allow remapping
- Alt+F4 - Support quit shortcuts
- Save Location - Use
user://directory
Expert Techniques & Optimizations
1. Alt-Tab-Pause (Stuck Input Guard)
When a game loses focus, the OS may intercept "key up" events, leaving Godot's Input state stuck. Use NOTIFICATION_APPLICATION_FOCUS_OUT to pause the game and reset input logic.
func _notification(what: int) -> void:match what:NOTIFICATION_APPLICATION_FOCUS_OUT:get_tree().paused = true# Optional: Manually release critical actionsInput.action_release("move_forward")NOTIFICATION_APPLICATION_FOCUS_IN:get_tree().paused = false
2. Social Integrations (GDExtension)
For Discord-RPC or Vapor network pipes, use GDExtension to bind native shared libraries (.dll, .so, .dylib) to Godot at runtime. This keeps the engine core small while enabling expert-level social features.
# Logic assuming a 'SocialIntegration' GDExtension is loadedfunc _init_social() -> void:if ClassDB.class_exists("SocialIntegration"):var social = ClassDB.instantiate("SocialIntegration")social.set_activity("In Menu", "Level 1")
3. Desktop-Launcher Template
Use a dedicated Godot project as a lightweight launcher. It reads/writes user://settings.cfg and spawns the main game using OS.create_process().
func _on_play_pressed() -> void:var exe_path := OS.get_executable_path()var args := PackedStringArray(["--main-pack", "game_data.pck"])var pid := OS.create_process(exe_path, args)if pid > 0:get_tree().quit()
Reference
- Related:
godot-export-builds,godot-save-load-systems
Related
- Master Skill: godot-master