Enhance UI with RichText labels and add Metal HUD checkbox functionality
This commit is contained in:
93
main.go
93
main.go
@@ -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
|
||||||
|
Reference in New Issue
Block a user