Enhance UI with RichText labels and add Metal HUD checkbox functionality

This commit is contained in:
aomizu
2025-05-17 22:04:53 +09:00
parent c24fdfcb71
commit 3452b8f58d

93
main.go
View File

@@ -14,6 +14,7 @@ import (
"fyne.io/fyne/v2/app" "fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container" "fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/dialog" "fyne.io/fyne/v2/dialog"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget" "fyne.io/fyne/v2/widget"
) )
@@ -24,7 +25,7 @@ var (
turtlewowPath string turtlewowPath string
patchesAppliedTurtleWoW = false patchesAppliedTurtleWoW = false
patchesAppliedCrossOver = false patchesAppliedCrossOver = false
enableMetalHud = true // Default to enabled
) )
// Helper function to check if a path exists // Helper function to check if a path exists
@@ -130,14 +131,25 @@ func main() {
myApp := app.NewWithID("com.example.turtlesilicon") myApp := app.NewWithID("com.example.turtlesilicon")
myWindow := myApp.NewWindow("TurtleSilicon Patcher") myWindow := myApp.NewWindow("TurtleSilicon Patcher")
myWindow.Resize(fyne.NewSize(650, 450)) // Slightly wider for clarity myWindow.Resize(fyne.NewSize(650, 450)) // Slightly wider for clarity
myWindow.SetFixedSize(true)
// --- Path Labels --- // --- Path Labels ---
crossoverPathLabel := widget.NewLabel("CrossOver Path: Not set") crossoverPathLabel := widget.NewRichText() // Changed to RichText
turtlewowPathLabel := widget.NewLabel("TurtleWoW Path: Not set") turtlewowPathLabel := widget.NewRichText() // Changed to RichText
// --- Status Labels --- // --- Status Labels (Changed to RichText for color) ---
turtlewowStatusLabel := widget.NewLabel("TurtleWoW Patch Status: Not Applied") var turtlewowStatusLabel *widget.RichText
crossoverStatusLabel := widget.NewLabel("CrossOver Patch Status: Not Applied") var crossoverStatusLabel *widget.RichText
turtlewowStatusLabel = widget.NewRichText()
crossoverStatusLabel = widget.NewRichText()
// --- Checkbox for Metal HUD ---
metalHudCheckbox := widget.NewCheck("Enable Metal Hud (show FPS)", func(checked bool) {
enableMetalHud = checked
log.Printf("Metal HUD enabled: %v", enableMetalHud)
})
metalHudCheckbox.SetChecked(enableMetalHud) // Set initial state
// --- Buttons (declared here to be accessible in updateAllStatuses) --- // --- Buttons (declared here to be accessible in updateAllStatuses) ---
var launchButton *widget.Button var launchButton *widget.Button
@@ -148,25 +160,28 @@ func main() {
updateAllStatuses := func() { updateAllStatuses := func() {
// Update Crossover Path and Status // Update Crossover Path and Status
if crossoverPath == "" { if crossoverPath == "" {
crossoverPathLabel.SetText("CrossOver Path: Not set") crossoverPathLabel.Segments = []widget.RichTextSegment{&widget.TextSegment{Text: "Not set", Style: widget.RichTextStyle{ColorName: theme.ColorNameError}}}
crossoverPathLabel.Refresh()
patchesAppliedCrossOver = false // Reset if path is cleared patchesAppliedCrossOver = false // Reset if path is cleared
} else { } else {
crossoverPathLabel.SetText("CrossOver Path: " + crossoverPath) crossoverPathLabel.Segments = []widget.RichTextSegment{&widget.TextSegment{Text: crossoverPath, Style: widget.RichTextStyle{ColorName: theme.ColorNameSuccess}}}
crossoverPathLabel.Refresh()
wineloader2Path := filepath.Join(crossoverPath, "Contents", "SharedSupport", "CrossOver", "CrossOver-Hosted Application", "wineloader2") wineloader2Path := filepath.Join(crossoverPath, "Contents", "SharedSupport", "CrossOver", "CrossOver-Hosted Application", "wineloader2")
if pathExists(wineloader2Path) { if pathExists(wineloader2Path) {
patchesAppliedCrossOver = true patchesAppliedCrossOver = true
} else { } else {
// patchesAppliedCrossOver = false // Only set to false if not already true from a patch action this session // patchesAppliedCrossOver = false // Only set to false if not already true from a patch action this session
// This will be set to true by the patch function upon success
} }
} }
if patchesAppliedCrossOver { if patchesAppliedCrossOver {
crossoverStatusLabel.SetText("CrossOver Patch Status: Applied") crossoverStatusLabel.Segments = []widget.RichTextSegment{&widget.TextSegment{Text: "Patched", Style: widget.RichTextStyle{ColorName: theme.ColorNameSuccess}}} // Changed to ColorNameSuccess
crossoverStatusLabel.Refresh()
if patchCrossOverButton != nil { if patchCrossOverButton != nil {
patchCrossOverButton.Disable() patchCrossOverButton.Disable()
} }
} else { } else {
crossoverStatusLabel.SetText("CrossOver Patch Status: Not Applied") crossoverStatusLabel.Segments = []widget.RichTextSegment{&widget.TextSegment{Text: "Not patched", Style: widget.RichTextStyle{ColorName: theme.ColorNameError}}}
crossoverStatusLabel.Refresh()
if patchCrossOverButton != nil { if patchCrossOverButton != nil {
if crossoverPath != "" { if crossoverPath != "" {
patchCrossOverButton.Enable() patchCrossOverButton.Enable()
@@ -178,26 +193,34 @@ func main() {
// Update TurtleWoW Path and Status // Update TurtleWoW Path and Status
if turtlewowPath == "" { if turtlewowPath == "" {
turtlewowPathLabel.SetText("TurtleWoW Path: Not set") turtlewowPathLabel.Segments = []widget.RichTextSegment{&widget.TextSegment{Text: "Not set", Style: widget.RichTextStyle{ColorName: theme.ColorNameError}}}
turtlewowPathLabel.Refresh()
patchesAppliedTurtleWoW = false // Reset if path is cleared patchesAppliedTurtleWoW = false // Reset if path is cleared
} else { } else {
turtlewowPathLabel.SetText("TurtleWoW Path: " + turtlewowPath) turtlewowPathLabel.Segments = []widget.RichTextSegment{&widget.TextSegment{Text: turtlewowPath, Style: widget.RichTextStyle{ColorName: theme.ColorNameSuccess}}}
turtlewowPathLabel.Refresh()
winerosettaDllPath := filepath.Join(turtlewowPath, "winerosetta.dll") winerosettaDllPath := filepath.Join(turtlewowPath, "winerosetta.dll")
d3d9DllPath := filepath.Join(turtlewowPath, "d3d9.dll") d3d9DllPath := filepath.Join(turtlewowPath, "d3d9.dll")
rosettaX87DirPath := filepath.Join(turtlewowPath, "rosettax87") rosettaX87DirPath := filepath.Join(turtlewowPath, "rosettax87")
if pathExists(winerosettaDllPath) && pathExists(d3d9DllPath) && dirExists(rosettaX87DirPath) { // Check for libRuntimeRosettax87 as well
rosettaX87ExePath := filepath.Join(rosettaX87DirPath, "rosettax87")
libRuntimeRosettaX87Path := filepath.Join(rosettaX87DirPath, "libRuntimeRosettax87")
if pathExists(winerosettaDllPath) && pathExists(d3d9DllPath) && dirExists(rosettaX87DirPath) && pathExists(rosettaX87ExePath) && pathExists(libRuntimeRosettaX87Path) {
patchesAppliedTurtleWoW = true patchesAppliedTurtleWoW = true
} else { } else {
// patchesAppliedTurtleWoW = false // Similar to crossover, only set by patch success or initial check // patchesAppliedTurtleWoW = false
} }
} }
if patchesAppliedTurtleWoW { if patchesAppliedTurtleWoW {
turtlewowStatusLabel.SetText("TurtleWoW Patch Status: Applied") turtlewowStatusLabel.Segments = []widget.RichTextSegment{&widget.TextSegment{Text: "Patched", Style: widget.RichTextStyle{ColorName: theme.ColorNameSuccess}}} // Changed to ColorNameSuccess
turtlewowStatusLabel.Refresh()
if patchTurtleWoWButton != nil { if patchTurtleWoWButton != nil {
patchTurtleWoWButton.Disable() patchTurtleWoWButton.Disable()
} }
} else { } else {
turtlewowStatusLabel.SetText("TurtleWoW Patch Status: Not Applied") turtlewowStatusLabel.Segments = []widget.RichTextSegment{&widget.TextSegment{Text: "Not patched", Style: widget.RichTextStyle{ColorName: theme.ColorNameError}}}
turtlewowStatusLabel.Refresh()
if patchTurtleWoWButton != nil { if patchTurtleWoWButton != nil {
if turtlewowPath != "" { if turtlewowPath != "" {
patchTurtleWoWButton.Enable() patchTurtleWoWButton.Enable()
@@ -427,21 +450,6 @@ func main() {
return return
} }
// Set execute permissions for the wineloader2 copy
log.Printf("Setting execute permission for %s", wineloaderCopy)
if err := os.Chmod(wineloaderCopy, 0755); err != nil {
errMsg := fmt.Sprintf("failed to set execute permission for %s: %v", wineloaderCopy, err)
dialog.ShowError(fmt.Errorf(errMsg), myWindow)
log.Println(errMsg)
patchesAppliedCrossOver = false
// Attempt to clean up the copied file if chmod fails
if err := os.Remove(wineloaderCopy); err != nil {
log.Printf("Warning: failed to cleanup wineloader2 after chmod failure: %v", err)
}
updateAllStatuses()
return
}
// 2. Execute codesign --remove-signature // 2. Execute codesign --remove-signature
log.Printf("Executing: codesign --remove-signature %s", wineloaderCopy) log.Printf("Executing: codesign --remove-signature %s", wineloaderCopy)
cmd := exec.Command("codesign", "--remove-signature", wineloaderCopy) cmd := exec.Command("codesign", "--remove-signature", wineloaderCopy)
@@ -531,8 +539,8 @@ func main() {
"The rosetta x87 terminal has been initiated.\n\n"+ "The rosetta x87 terminal has been initiated.\n\n"+
"1. Please enter your sudo password in that new terminal window.\n"+ "1. Please enter your sudo password in that new terminal window.\n"+
"2. Wait for rosetta x87 to fully start.\n\n"+ "2. Wait for rosetta x87 to fully start.\n\n"+
"Click OK here once rosetta x87 is running and you have entered the password.\n"+ "Click Yes once rosetta x87 is running and you have entered the password.\n"+
"Click Cancel to abort launching WoW.", "Click No to abort launching WoW.",
func(confirmed bool) { func(confirmed bool) {
if confirmed { if confirmed {
log.Println("User confirmed rosetta x87 is running. Proceeding to launch WoW.") log.Println("User confirmed rosetta x87 is running. Proceeding to launch WoW.")
@@ -542,14 +550,16 @@ func main() {
return return
} }
// Paths required for the new command (already defined in launchGameFunc scope): // Determine MTL_HUD_ENABLED value based on checkbox
// rosettaExecutable := filepath.Join(turtlewowPath, "rosettax87", "rosettax87") mtlHudValue := "0"
// wineloader2Path := filepath.Join(crossoverPath, "Contents", "SharedSupport", "CrossOver", "CrossOver-Hosted Application", "wineloader2") if enableMetalHud {
// turtlewowExePath := filepath.Join(turtlewowPath, "WoW.exe") mtlHudValue = "1"
}
// Construct the new shell command // Construct the new shell command
shellCmd := fmt.Sprintf(`cd %s && WINEDLLOVERRIDES="d3d9=n,b" MTL_HUD_ENABLED=1 %s %s %s`, shellCmd := fmt.Sprintf(`cd %s && WINEDLLOVERRIDES="d3d9=n,b" MTL_HUD_ENABLED=%s %s %s %s`,
quotePathForShell(turtlewowPath), // Added cd to turtlewowPath quotePathForShell(turtlewowPath), // Added cd to turtlewowPath
mtlHudValue, // Use dynamic value
quotePathForShell(rosettaExecutable), quotePathForShell(rosettaExecutable),
quotePathForShell(wineloader2Path), quotePathForShell(wineloader2Path),
quotePathForShell(turtlewowExePath)) // turtlewowExePath is defined at the start of launchGameFunc quotePathForShell(turtlewowExePath)) // turtlewowExePath is defined at the start of launchGameFunc
@@ -566,7 +576,7 @@ func main() {
} }
log.Println("Launch commands executed. Check the new terminal windows.") log.Println("Launch commands executed. Check the new terminal windows.")
dialog.ShowInformation("Launched", "World of Warcraft launch sequence initiated. Check the new terminal windows.", myWindow) dialog.ShowInformation("Launched", "World of Warcraft is starting. Enjoy.", myWindow)
} else { } else {
log.Println("User cancelled WoW launch after rosetta x87 initiation.") log.Println("User cancelled WoW launch after rosetta x87 initiation.")
dialog.ShowInformation("Cancelled", "WoW launch was cancelled.", myWindow) dialog.ShowInformation("Cancelled", "WoW launch was cancelled.", myWindow)
@@ -613,7 +623,8 @@ func main() {
myWindow.SetContent(container.NewVBox( myWindow.SetContent(container.NewVBox(
pathSelectionForm, pathSelectionForm,
patchOperationsLayout, patchOperationsLayout,
launchButton, metalHudCheckbox, // Added Metal HUD checkbox
container.NewPadded(launchButton), // Added padding to launchButton
)) ))
updateAllStatuses() // Initial UI state update, including button states updateAllStatuses() // Initial UI state update, including button states