added a apply recommended graphics settings button to options

This commit is contained in:
aomizu
2025-06-14 14:28:50 +09:00
parent 68cfe61064
commit c0daa300bf
7 changed files with 263 additions and 1 deletions

View File

@@ -3,4 +3,4 @@
Name = "TurtleSilicon"
ID = "com.tairasu.turtlesilicon"
Version = "1.2.2"
Build = 52
Build = 57

View File

@@ -91,6 +91,7 @@ If you prefer to run the application directly from source code:
1. Set "Terrain distance" as low as possible. This reduces the overhead stress on the CPU
2. Turn Vertex Animation Shaders on. Otherwise you get graphic glitches on custom models.
3. Set Multisampling to 24-bit color 24-bit depth **2x** to make portraits load
4. Add `SET shadowLOD "0"` to your Config.wtf inside the WTF directory
## Build Instructions

135
pkg/launcher/recommended.go Normal file
View File

@@ -0,0 +1,135 @@
package launcher
import (
"fmt"
"os"
"path/filepath"
"regexp"
"strings"
"turtlesilicon/pkg/debug"
"turtlesilicon/pkg/paths"
)
// RecommendedSettings contains the recommended graphics settings for optimal performance
var RecommendedSettings = map[string]string{
"farclip": "177",
"M2UseShaders": "1",
"gxColorBits": "24",
"gxDepthBits": "24",
"gxMultisampleQuality": "0.000000",
"gxMultisample": "2",
"shadowLOD": "0",
}
// CheckRecommendedSettings reads the Config.wtf file and checks if all recommended settings are applied
// Returns true if all settings are correctly applied, false otherwise
func CheckRecommendedSettings() bool {
if paths.TurtlewowPath == "" {
debug.Printf("TurtleWoW path not set, cannot check Config.wtf")
return false
}
configPath := filepath.Join(paths.TurtlewowPath, "WTF", "Config.wtf")
if _, err := os.Stat(configPath); os.IsNotExist(err) {
debug.Printf("Config.wtf not found at %s", configPath)
return false
}
content, err := os.ReadFile(configPath)
if err != nil {
debug.Printf("Failed to read Config.wtf: %v", err)
return false
}
configText := string(content)
// Check each recommended setting
for setting, expectedValue := range RecommendedSettings {
if !isSettingCorrect(configText, setting, expectedValue) {
debug.Printf("Setting %s not found or incorrect in Config.wtf", setting)
return false
}
}
debug.Printf("All recommended settings are correctly applied")
return true
}
// isSettingCorrect checks if a specific setting has the correct value in the config text
func isSettingCorrect(configText, setting, expectedValue string) bool {
// Create regex pattern to match the setting
pattern := fmt.Sprintf(`SET\s+%s\s+"([^"]*)"`, regexp.QuoteMeta(setting))
re := regexp.MustCompile(pattern)
matches := re.FindStringSubmatch(configText)
if len(matches) < 2 {
return false
}
currentValue := matches[1]
return currentValue == expectedValue
}
// ApplyRecommendedSettings applies all recommended graphics settings to Config.wtf
func ApplyRecommendedSettings() error {
if paths.TurtlewowPath == "" {
return fmt.Errorf("TurtleWoW path not set")
}
configPath := filepath.Join(paths.TurtlewowPath, "WTF", "Config.wtf")
// Create WTF directory if it doesn't exist
wtfDir := filepath.Dir(configPath)
if err := os.MkdirAll(wtfDir, 0755); err != nil {
return fmt.Errorf("failed to create WTF directory: %v", err)
}
var configText string
// Read existing config if it exists
if content, err := os.ReadFile(configPath); err == nil {
configText = string(content)
} else {
debug.Printf("Config.wtf not found, creating new file")
configText = ""
}
// Apply each recommended setting
for setting, value := range RecommendedSettings {
configText = updateOrAddSetting(configText, setting, value)
}
// Write the updated config back to file
if err := os.WriteFile(configPath, []byte(configText), 0644); err != nil {
return fmt.Errorf("failed to write Config.wtf: %v", err)
}
debug.Printf("Successfully applied recommended settings to Config.wtf")
return nil
}
// updateOrAddSetting updates an existing setting or adds a new one if it doesn't exist
func updateOrAddSetting(configText, setting, value string) string {
// Create regex pattern to match the setting
pattern := fmt.Sprintf(`SET\s+%s\s+"[^"]*"`, regexp.QuoteMeta(setting))
re := regexp.MustCompile(pattern)
newSetting := fmt.Sprintf(`SET %s "%s"`, setting, value)
if re.MatchString(configText) {
// Replace existing setting
configText = re.ReplaceAllString(configText, newSetting)
debug.Printf("Updated setting %s to %s", setting, value)
} else {
// Add new setting
if configText != "" && !strings.HasSuffix(configText, "\n") {
configText += "\n"
}
configText += newSetting + "\n"
debug.Printf("Added new setting %s with value %s", setting, value)
}
return configText
}

View File

@@ -1,6 +1,7 @@
package ui
import (
"fmt"
"net/url"
"strings"
"time"
@@ -13,6 +14,7 @@ import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/dialog"
"fyne.io/fyne/v2/widget"
)
@@ -47,6 +49,35 @@ func createOptionsComponents() {
vanillaTweaksCheckbox.SetChecked(prefs.EnableVanillaTweaks)
launcher.EnableVanillaTweaks = prefs.EnableVanillaTweaks
// Create recommended settings button with help icon
applyRecommendedSettingsButton = widget.NewButton("Apply recommended settings", func() {
err := launcher.ApplyRecommendedSettings()
if err != nil {
debug.Printf("Failed to apply recommended settings: %v", err)
// Show error dialog if we have a window reference
if currentWindow != nil {
dialog.ShowError(fmt.Errorf("failed to apply recommended settings: %v", err), currentWindow)
}
} else {
debug.Printf("Successfully applied recommended settings")
// Show success dialog if we have a window reference
if currentWindow != nil {
dialog.ShowInformation("Success", "Recommended graphics settings have been applied to Config.wtf", currentWindow)
}
// Update button state
updateRecommendedSettingsButton()
}
})
applyRecommendedSettingsButton.Importance = widget.MediumImportance
// Create help button for recommended settings
recommendedSettingsHelpButton = widget.NewButton("?", func() {
showRecommendedSettingsHelpPopup()
})
recommendedSettingsHelpButton.Importance = widget.MediumImportance
// Initialize button state
updateRecommendedSettingsButton()
// Create Wine registry Option-as-Alt buttons and status
createWineRegistryComponents()
@@ -350,3 +381,84 @@ func stopPulsingEffect() {
pulsingTicker = nil
}
}
// updateRecommendedSettingsButton updates the state of the recommended settings button
func updateRecommendedSettingsButton() {
if applyRecommendedSettingsButton == nil {
return
}
// Check if all recommended settings are already applied
if launcher.CheckRecommendedSettings() {
applyRecommendedSettingsButton.Disable()
applyRecommendedSettingsButton.SetText("Settings applied")
} else {
applyRecommendedSettingsButton.Enable()
applyRecommendedSettingsButton.SetText("Apply recommended settings")
}
// Help button should always be enabled
if recommendedSettingsHelpButton != nil {
recommendedSettingsHelpButton.Enable()
}
}
// showRecommendedSettingsHelpPopup shows a popup explaining the recommended graphics settings
func showRecommendedSettingsHelpPopup() {
if currentWindow == nil {
return
}
// Create help content
helpTitle := widget.NewRichTextFromMarkdown("# 📋 Recommended Graphics Settings")
// Create individual setting labels for better formatting
settingsTitle := widget.NewLabel("The following settings will be applied to your Config.wtf file:")
settingsTitle.TextStyle = fyne.TextStyle{Bold: true}
setting1 := widget.NewLabel("• Terrain Distance (farclip): 177 - Reduces CPU overhead - more fps")
setting2 := widget.NewLabel("• Vertex Animation Shaders (M2UseShaders): Enabled - Prevents graphic glitches")
setting3 := widget.NewLabel("• Multisampling (gxMultisample): 2x - Makes portraits load properly")
setting4 := widget.NewLabel("• Shadow LOD (shadowLOD): 0 - 10% fps increase")
settingsContainer := container.NewVBox(
settingsTitle,
widget.NewSeparator(),
setting1,
setting2,
setting3,
setting4,
widget.NewSeparator(),
)
// Create OK button
okButton := widget.NewButton("OK", func() {
// This will be set when the popup is created
})
okButton.Importance = widget.MediumImportance
// Create help content container
helpContentContainer := container.NewVBox(
container.NewCenter(helpTitle),
widget.NewSeparator(),
settingsContainer,
widget.NewSeparator(),
container.NewCenter(okButton),
)
// Calculate popup size
windowSize := currentWindow.Content().Size()
popupWidth := windowSize.Width * 3 / 4
popupHeight := windowSize.Height * 3 / 4
// Create the help popup
helpPopup := widget.NewModalPopUp(container.NewPadded(helpContentContainer), currentWindow.Canvas())
helpPopup.Resize(fyne.NewSize(popupWidth, popupHeight))
// Set the OK button action to hide the help popup
okButton.OnTapped = func() {
helpPopup.Hide()
}
helpPopup.Show()
}

View File

@@ -15,6 +15,9 @@ func showOptionsPopup() {
// Create options content with better organization and smaller titles
optionsTitle := widget.NewLabel("Options")
optionsTitle.TextStyle = fyne.TextStyle{Bold: true}
// Create label for recommended settings
recommendedSettingsLabel := widget.NewLabel("Graphics settings:")
gameOptionsContainer := container.NewVBox(
optionsTitle,
widget.NewSeparator(),
@@ -22,6 +25,8 @@ func showOptionsPopup() {
showTerminalCheckbox,
vanillaTweaksCheckbox,
widget.NewSeparator(),
container.NewBorder(nil, nil, recommendedSettingsLabel, container.NewHBox(applyRecommendedSettingsButton, recommendedSettingsHelpButton), nil),
widget.NewSeparator(),
container.NewBorder(nil, nil, nil, container.NewHBox(enableOptionAsAltButton, disableOptionAsAltButton), optionAsAltStatusLabel),
)

View File

@@ -30,6 +30,11 @@ func UpdateAllStatuses() {
if optionAsAltStatusLabel != nil {
updateWineRegistryStatus()
}
// Update recommended settings button if component is initialized
if applyRecommendedSettingsButton != nil {
updateRecommendedSettingsButton()
}
}
// updateCrossoverStatus updates CrossOver path and patch status

View File

@@ -32,6 +32,10 @@ var (
showTerminalCheckbox *widget.Check
vanillaTweaksCheckbox *widget.Check
// Recommended settings button
applyRecommendedSettingsButton *widget.Button
recommendedSettingsHelpButton *widget.Button
// Wine registry buttons and status
enableOptionAsAltButton *widget.Button
disableOptionAsAltButton *widget.Button