added a apply recommended graphics settings button to options
This commit is contained in:
@@ -3,4 +3,4 @@
|
|||||||
Name = "TurtleSilicon"
|
Name = "TurtleSilicon"
|
||||||
ID = "com.tairasu.turtlesilicon"
|
ID = "com.tairasu.turtlesilicon"
|
||||||
Version = "1.2.2"
|
Version = "1.2.2"
|
||||||
Build = 52
|
Build = 57
|
||||||
|
@@ -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
|
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.
|
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
|
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
|
## Build Instructions
|
||||||
|
|
||||||
|
135
pkg/launcher/recommended.go
Normal file
135
pkg/launcher/recommended.go
Normal 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
|
||||||
|
}
|
@@ -1,6 +1,7 @@
|
|||||||
package ui
|
package ui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -13,6 +14,7 @@ import (
|
|||||||
|
|
||||||
"fyne.io/fyne/v2"
|
"fyne.io/fyne/v2"
|
||||||
"fyne.io/fyne/v2/container"
|
"fyne.io/fyne/v2/container"
|
||||||
|
"fyne.io/fyne/v2/dialog"
|
||||||
"fyne.io/fyne/v2/widget"
|
"fyne.io/fyne/v2/widget"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -47,6 +49,35 @@ func createOptionsComponents() {
|
|||||||
vanillaTweaksCheckbox.SetChecked(prefs.EnableVanillaTweaks)
|
vanillaTweaksCheckbox.SetChecked(prefs.EnableVanillaTweaks)
|
||||||
launcher.EnableVanillaTweaks = 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
|
// Create Wine registry Option-as-Alt buttons and status
|
||||||
createWineRegistryComponents()
|
createWineRegistryComponents()
|
||||||
|
|
||||||
@@ -350,3 +381,84 @@ func stopPulsingEffect() {
|
|||||||
pulsingTicker = nil
|
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()
|
||||||
|
}
|
||||||
|
@@ -15,6 +15,9 @@ func showOptionsPopup() {
|
|||||||
// Create options content with better organization and smaller titles
|
// Create options content with better organization and smaller titles
|
||||||
optionsTitle := widget.NewLabel("Options")
|
optionsTitle := widget.NewLabel("Options")
|
||||||
optionsTitle.TextStyle = fyne.TextStyle{Bold: true}
|
optionsTitle.TextStyle = fyne.TextStyle{Bold: true}
|
||||||
|
// Create label for recommended settings
|
||||||
|
recommendedSettingsLabel := widget.NewLabel("Graphics settings:")
|
||||||
|
|
||||||
gameOptionsContainer := container.NewVBox(
|
gameOptionsContainer := container.NewVBox(
|
||||||
optionsTitle,
|
optionsTitle,
|
||||||
widget.NewSeparator(),
|
widget.NewSeparator(),
|
||||||
@@ -22,6 +25,8 @@ func showOptionsPopup() {
|
|||||||
showTerminalCheckbox,
|
showTerminalCheckbox,
|
||||||
vanillaTweaksCheckbox,
|
vanillaTweaksCheckbox,
|
||||||
widget.NewSeparator(),
|
widget.NewSeparator(),
|
||||||
|
container.NewBorder(nil, nil, recommendedSettingsLabel, container.NewHBox(applyRecommendedSettingsButton, recommendedSettingsHelpButton), nil),
|
||||||
|
widget.NewSeparator(),
|
||||||
container.NewBorder(nil, nil, nil, container.NewHBox(enableOptionAsAltButton, disableOptionAsAltButton), optionAsAltStatusLabel),
|
container.NewBorder(nil, nil, nil, container.NewHBox(enableOptionAsAltButton, disableOptionAsAltButton), optionAsAltStatusLabel),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -30,6 +30,11 @@ func UpdateAllStatuses() {
|
|||||||
if optionAsAltStatusLabel != nil {
|
if optionAsAltStatusLabel != nil {
|
||||||
updateWineRegistryStatus()
|
updateWineRegistryStatus()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update recommended settings button if component is initialized
|
||||||
|
if applyRecommendedSettingsButton != nil {
|
||||||
|
updateRecommendedSettingsButton()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// updateCrossoverStatus updates CrossOver path and patch status
|
// updateCrossoverStatus updates CrossOver path and patch status
|
||||||
|
@@ -32,6 +32,10 @@ var (
|
|||||||
showTerminalCheckbox *widget.Check
|
showTerminalCheckbox *widget.Check
|
||||||
vanillaTweaksCheckbox *widget.Check
|
vanillaTweaksCheckbox *widget.Check
|
||||||
|
|
||||||
|
// Recommended settings button
|
||||||
|
applyRecommendedSettingsButton *widget.Button
|
||||||
|
recommendedSettingsHelpButton *widget.Button
|
||||||
|
|
||||||
// Wine registry buttons and status
|
// Wine registry buttons and status
|
||||||
enableOptionAsAltButton *widget.Button
|
enableOptionAsAltButton *widget.Button
|
||||||
disableOptionAsAltButton *widget.Button
|
disableOptionAsAltButton *widget.Button
|
||||||
|
Reference in New Issue
Block a user