Refactoring

This commit is contained in:
2025-03-31 13:35:32 +02:00
parent 36506e1490
commit 7ccaac4b3c
5 changed files with 264 additions and 235 deletions

2
.gitignore vendored
View File

@@ -27,3 +27,5 @@ go.work.sum
# env file # env file
.env .env
unreal-pm

40
log.go Normal file
View File

@@ -0,0 +1,40 @@
package main
import (
"fmt"
"strings"
"fyne.io/fyne/v2/widget"
)
type Logger struct {
logText *widget.Entry
logBuffer []string
logMaxLines int
}
var globalLogger *Logger;
func InitLogger(text *widget.Entry, maxLines int) {
globalLogger = &Logger{
logText: text,
logMaxLines: logMaxLines,
}
}
func Log(line string) {
if globalLogger == nil {
fmt.Println("Global Logger is nil")
return
}
globalLogger.log(line)
}
func (l *Logger) log(line string) {
l.logBuffer = append(l.logBuffer, line)
if len(l.logBuffer) > l.logMaxLines {
l.logBuffer = l.logBuffer[1:]
}
l.logText.SetText(strings.Join(l.logBuffer, "\n"))
}

243
main.go
View File

@@ -1,266 +1,39 @@
package main package main
import ( import (
"bufio"
"encoding/json"
"fmt" "fmt"
"io"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"fyne.io/fyne/v2" "fyne.io/fyne/v2"
"fyne.io/fyne/v2/app" "fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container" "fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/layout"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget" "fyne.io/fyne/v2/widget"
) )
type Project struct {
EnginePath string `json:"enginePath"`
ProjectPath string `json:"projectPath"`
ProjectName string `json:"projectName"`
Version string `json:"engineVersion"`
}
const projectsFilePath = "projects.json" const projectsFilePath = "projects.json"
var projectList *fyne.Container
var logText *widget.Entry
var scrollContainer *container.Scroll
var logBuffer []string
var logMaxLines = 7 var logMaxLines = 7
type hoverableButton struct {
widget.Button
onMouseIn func()
onMouseOut func()
}
func (h *hoverableButton) MouseIn() {
if h.onMouseIn != nil {
h.onMouseIn()
}
}
func (h *hoverableButton) MouseOut() {
if h.onMouseOut != nil {
h.onMouseOut()
}
}
func loadProjects() ([]Project, error) {
file, err := os.ReadFile(projectsFilePath)
if err != nil {
return nil, err
}
var projects []Project
if err := json.Unmarshal(file, &projects); err != nil {
return nil, err
}
return projects, nil
}
func removeDir(path string) {
err := os.RemoveAll(path)
if err != nil {
log("Can't remove content at " + path)
} else {
log("Removed " + path)
}
}
func cleanUnrealProject(project Project) {
dirs := []string {
"Binaries",
"DerivedDataCache",
"Intermediate",
"Saved",
"Script",
}
for _, dir := range dirs {
fullPath := filepath.Join(project.ProjectPath, dir)
removeDir(fullPath)
}
pluginsPath := filepath.Join(project.ProjectPath, "Plugins")
entries, err := os.ReadDir(pluginsPath)
if err != nil {
return
}
for _, entry := range entries {
if !entry.IsDir() {
continue
}
pluginDir := filepath.Join(pluginsPath, entry.Name())
removeDir(filepath.Join(pluginDir, "Binaries"))
removeDir(filepath.Join(pluginDir, "Intermediate"))
}
}
func generateUnrealSolution(project Project) {
var buildCmd string
switch runtime.GOOS {
case "linux":
buildCmd = project.EnginePath + "/Engine/Build/BatchFiles/Linux/GenerateProjectFiles.sh";
case "darwin":
buildCmd = project.EnginePath + "/Engine/Build/BatchFiles/Mac/GenerateProjectFiles.sh"
default:
fmt.Println("Generate Project is not yet supported on Windows")
return
}
projectCmd := project.ProjectPath + "/" + project.ProjectName + ".uproject"
cmd := exec.Command(buildCmd, projectCmd, "-game")
logToOutput(cmd)
}
func buildUnrealSolution(project Project) {
switch runtime.GOOS {
case "linux":
cmd := exec.Command("make", "-C", project.ProjectPath, project.ProjectName)
logToOutput(cmd)
default:
fmt.Println("Build Project is not yet supported on Windows")
return
}
}
func runUnrealProject(project Project) {
var buildCmd string
switch runtime.GOOS {
case "linux":
buildCmd = project.EnginePath + "/Engine/Binaries/Linux/UnrealEditor"
case "darwin":
buildCmd = project.EnginePath + "/Engine/Binaries/Mac/UnrealEditor.app/Contents/MacOS/UnrealEditor"
default:
buildCmd = project.EnginePath + "/Engine/Binaries/Win64/UnrealEditor.exe"
}
projectCmd := project.ProjectPath + "/" + project.ProjectName + ".uproject"
cmd := exec.Command(buildCmd, projectCmd)
logToOutput(cmd)
}
func logToOutput(cmd *exec.Cmd) {
stdout, err := cmd.StdoutPipe()
if err != nil {
fmt.Println("Error during pipe stdout creation")
}
stderr, err := cmd.StderrPipe()
if err != nil {
fmt.Println("Error during pipe stderr creation")
}
if err := cmd.Start(); err != nil {
fmt.Println("Error while loading command")
}
readPipe := func(reader io.ReadCloser) {
scanner := bufio.NewScanner(reader)
for scanner.Scan() {
line := scanner.Text()
log(line)
}
}
go readPipe(stdout)
go readPipe(stderr)
if err := cmd.Wait(); err != nil {
fmt.Println("Error")
}
}
func log(line string) {
logBuffer = append(logBuffer, line)
if len(logBuffer) > logMaxLines {
logBuffer = logBuffer[1:]
}
logText.SetText(strings.Join(logBuffer, "\n"))
}
func newProjectRow(project Project) fyne.CanvasObject {
projectName := project.ProjectName
iconPath := filepath.Join(project.ProjectPath, projectName+".png")
var projectIcon fyne.Resource
if _, err := os.Stat(iconPath); err == nil {
icon, err := fyne.LoadResourceFromPath(iconPath)
if err == nil {
projectIcon = icon
}
}
if projectIcon == nil {
projectIcon = theme.FileIcon()
}
icon := canvas.NewImageFromResource(projectIcon)
icon.SetMinSize(fyne.NewSize(48, 48))
nameLabel := widget.NewLabel(projectName + " / Unreal Engine " + project.Version)
nameLabel.Alignment = fyne.TextAlignLeading
// Crée les boutons masqués par défaut
clearButton := widget.NewButton("Clean", func() {
cleanUnrealProject(project)
})
generateBtn := widget.NewButton("Generate", func() {
generateUnrealSolution(project)
})
buildBtn := widget.NewButton("Build", func() {
buildUnrealSolution(project)
})
launchBtn := widget.NewButton("Run", func() {
runUnrealProject(project)
})
buttons := container.NewHBox(clearButton, generateBtn, buildBtn, launchBtn)
// Conteneur principal
row := container.NewHBox(
icon,
nameLabel,
layout.NewSpacer(),
buttons,
)
return row
}
func main() { func main() {
myApp := app.New() myApp := app.New()
myWindow := myApp.NewWindow("Unreal Project Launcher") myWindow := myApp.NewWindow("Unreal Project Launcher")
myWindow.Resize(fyne.NewSize(730, 460)) myWindow.Resize(fyne.NewSize(730, 460))
projects, err := loadProjects() projects, err := LoadProjects(projectsFilePath)
if err != nil { if err != nil {
fmt.Println("Error while loading projects") fmt.Println("Error while loading projects")
} }
logText = widget.NewMultiLineEntry() logText := widget.NewMultiLineEntry()
logText.SetMinRowsVisible(logMaxLines); logText.SetMinRowsVisible(logMaxLines);
InitLogger(logText, logMaxLines)
var projectList *fyne.Container
reloadUI := func() { reloadUI := func() {
projectList.RemoveAll() projectList.RemoveAll()
for _, project := range projects { for _, project := range projects {
row := newProjectRow(project) row := NewProjectRow(project)
projectList.Add(row) projectList.Add(row)
} }
} }
@@ -268,7 +41,7 @@ func main() {
projectList = container.NewVBox() projectList = container.NewVBox()
reloadUI() reloadUI()
scrollContainer = container.NewVScroll(projectList) scrollContainer := container.NewVScroll(projectList)
mainContainer := container.NewBorder(nil, logText, nil, nil, scrollContainer) mainContainer := container.NewBorder(nil, logText, nil, nil, scrollContainer)
myWindow.SetContent(mainContainer) myWindow.SetContent(mainContainer)

61
ui.go Normal file
View File

@@ -0,0 +1,61 @@
package main
import (
"os"
"path/filepath"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/layout"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
)
func NewProjectRow(project Project) fyne.CanvasObject {
projectName := project.ProjectName
iconPath := filepath.Join(project.ProjectPath, projectName+".png")
var projectIcon fyne.Resource
if _, err := os.Stat(iconPath); err == nil {
icon, err := fyne.LoadResourceFromPath(iconPath)
if err == nil {
projectIcon = icon
}
}
if projectIcon == nil {
projectIcon = theme.FileIcon()
}
icon := canvas.NewImageFromResource(projectIcon)
icon.SetMinSize(fyne.NewSize(48, 48))
nameLabel := widget.NewLabel(projectName + " / Unreal Engine " + project.Version)
nameLabel.Alignment = fyne.TextAlignLeading
// Crée les boutons masqués par défaut
clearButton := widget.NewButton("Clean", func() {
CleanUnrealProject(project)
})
generateBtn := widget.NewButton("Generate", func() {
GenerateUnrealSolution(project)
})
buildBtn := widget.NewButton("Build", func() {
BuildUnrealSolution(project)
})
launchBtn := widget.NewButton("Run", func() {
RunUnrealProject(project)
})
buttons := container.NewHBox(clearButton, generateBtn, buildBtn, launchBtn)
// Conteneur principal
row := container.NewHBox(
icon,
nameLabel,
layout.NewSpacer(),
buttons,
)
return row
}

153
utils.go Normal file
View File

@@ -0,0 +1,153 @@
package main
import (
"bufio"
"encoding/json"
"fmt"
"io"
"os"
"os/exec"
"path/filepath"
"runtime"
)
type Project struct {
EnginePath string `json:"enginePath"`
ProjectPath string `json:"projectPath"`
ProjectName string `json:"projectName"`
Version string `json:"engineVersion"`
}
func LoadProjects(projectFilePath string) ([]Project, error) {
file, err := os.ReadFile(projectsFilePath)
if err != nil {
return nil, err
}
var projects []Project
if err := json.Unmarshal(file, &projects); err != nil {
return nil, err
}
return projects, nil
}
func removeDir(path string) {
err := os.RemoveAll(path)
if err != nil {
Log("Can't remove content at " + path)
} else {
Log("Removed " + path)
}
}
func CleanUnrealProject(project Project) {
dirs := []string {
"Binaries",
"DerivedDataCache",
"Intermediate",
"Saved",
"Script",
}
for _, dir := range dirs {
fullPath := filepath.Join(project.ProjectPath, dir)
removeDir(fullPath)
}
pluginsPath := filepath.Join(project.ProjectPath, "Plugins")
entries, err := os.ReadDir(pluginsPath)
if err != nil {
return
}
for _, entry := range entries {
if !entry.IsDir() {
continue
}
pluginDir := filepath.Join(pluginsPath, entry.Name())
removeDir(filepath.Join(pluginDir, "Binaries"))
removeDir(filepath.Join(pluginDir, "Intermediate"))
}
}
func GenerateUnrealSolution(project Project) {
var buildCmd string
switch runtime.GOOS {
case "linux":
buildCmd = project.EnginePath + "/Engine/Build/BatchFiles/Linux/GenerateProjectFiles.sh";
case "darwin":
buildCmd = project.EnginePath + "/Engine/Build/BatchFiles/Mac/GenerateProjectFiles.sh"
default:
fmt.Println("Generate Project is not yet supported on Windows")
return
}
projectCmd := project.ProjectPath + "/" + project.ProjectName + ".uproject"
cmd := exec.Command(buildCmd, projectCmd, "-game")
logToOutput(cmd)
}
func BuildUnrealSolution(project Project) {
switch runtime.GOOS {
case "linux":
cmd := exec.Command("make", "-C", project.ProjectPath, project.ProjectName)
logToOutput(cmd)
default:
fmt.Println("Build Project is not yet supported on Windows")
return
}
}
func RunUnrealProject(project Project) {
var buildCmd string
switch runtime.GOOS {
case "linux":
buildCmd = project.EnginePath + "/Engine/Binaries/Linux/UnrealEditor"
case "darwin":
buildCmd = project.EnginePath + "/Engine/Binaries/Mac/UnrealEditor.app/Contents/MacOS/UnrealEditor"
default:
buildCmd = project.EnginePath + "/Engine/Binaries/Win64/UnrealEditor.exe"
}
projectCmd := project.ProjectPath + "/" + project.ProjectName + ".uproject"
cmd := exec.Command(buildCmd, projectCmd)
logToOutput(cmd)
}
func logToOutput(cmd *exec.Cmd) {
stdout, err := cmd.StdoutPipe()
if err != nil {
fmt.Println("Error during pipe stdout creation")
}
stderr, err := cmd.StderrPipe()
if err != nil {
fmt.Println("Error during pipe stderr creation")
}
if err := cmd.Start(); err != nil {
fmt.Println("Error while loading command")
}
readPipe := func(reader io.ReadCloser) {
scanner := bufio.NewScanner(reader)
for scanner.Scan() {
line := scanner.Text()
Log(line)
}
}
go readPipe(stdout)
go readPipe(stderr)
if err := cmd.Wait(); err != nil {
fmt.Println("Error")
}
}