diff --git a/Taskfile.yml b/Taskfile.yml
index f741f1a..a63c9a7 100644
--- a/Taskfile.yml
+++ b/Taskfile.yml
@@ -23,12 +23,30 @@ tasks:
resources:
desc: Compile resource file
cmds:
- - rsrc -manifest ./cmd/abyss-blackbox/main.manifest -ico ./trig_96x96.ico,./images/plus.ico,./images/switch-char.ico -o ./cmd/abyss-blackbox/rsrc.syso
+ - rsrc -manifest ./cmd/abyss-blackbox/main.manifest -ico ./trig_96x96.ico,./images/plus.ico,./images/switch-char.ico,./images/select-area.ico -o ./cmd/abyss-blackbox/rsrc.syso
+ debug:
+ desc: Builds artifacts for release
+ deps: [install-deps, resources]
+ cmds:
+ - go generate ./...
+ - go build -trimpath -ldflags "-s -w -X github.com/shivas/abyss-blackbox/internal/version.RecorderVersion={{.GIT_VERSION}} -X github.com/shivas/abyss-blackbox/internal/version.GoVersion={{.GO_VERSION}}" -o abyss-blackbox.exe ./cmd/abyss-blackbox
+ - go build -trimpath -ldflags="-s -w" ./cmd/extract/
+ vars:
+ GIT_VERSION:
+ sh: git describe --tags --always
+ GO_VERSION:
+ sh: go env GOVERSION
+
release:
desc: Builds artifacts for release
deps: [install-deps, resources]
cmds:
- go generate ./...
- - go build -trimpath -ldflags="-H windowsgui -s -w" -o abyss-blackbox.exe ./cmd/abyss-blackbox
+ - go build -trimpath -ldflags="-H windowsgui -s -w -X github.com/shivas/abyss-blackbox/internal/version.RecorderVersion={{.GIT_VERSION}} -X github.com/shivas/abyss-blackbox/internal/version.GoVersion={{.GO_VERSION}}" -o abyss-blackbox.exe ./cmd/abyss-blackbox
- go build -trimpath -ldflags="-s -w" ./cmd/extract/
+ vars:
+ GIT_VERSION:
+ sh: git describe --tags --always
+ GO_VERSION:
+ sh: go env GOVERSION
diff --git a/cmd/abyss-blackbox/main.go b/cmd/abyss-blackbox/main.go
index be381ec..5af760e 100644
--- a/cmd/abyss-blackbox/main.go
+++ b/cmd/abyss-blackbox/main.go
@@ -14,6 +14,7 @@ import (
"github.com/lxn/win"
"github.com/shivas/abyss-blackbox/combatlog"
"github.com/shivas/abyss-blackbox/internal/charmanager"
+ "github.com/shivas/abyss-blackbox/internal/config"
"github.com/shivas/abyss-blackbox/internal/mainwindow"
"github.com/shivas/abyss-blackbox/internal/uploader"
"github.com/shivas/abyss-blackbox/screen"
@@ -26,17 +27,10 @@ var recordingChannel chan *image.Paletted
var notificationChannel chan NotificationMessage
var recorder *Recorder
-const (
- hotkeyRecoder = iota + 1
- hotkeyWeather30
- hotkeyWeather50
- hotkeyWeather70
-)
-
func main() {
var err error
- currentSettings, err := readConfig()
+ currentSettings, err := config.Read()
if err != nil {
log.Fatal(err)
}
@@ -60,9 +54,6 @@ func main() {
comboModel = append(comboModel, &mainwindow.WindowComboBoxItem{WindowTitle: title, WindowHandle: handle})
}
- logFiles, _ := clr.GetLogFiles(time.Now(), time.Duration(24)*time.Hour)
- charMap := clr.MapCharactersToFiles(logFiles)
-
charManager := charmanager.New(func(s1, s2 string) {
notificationChannel <- NotificationMessage{Title: s1, Message: s2}
})
@@ -70,12 +61,10 @@ func main() {
actions := make(map[string]walk.EventHandler)
actions["add_character"] = charManager.EventHandlerCharAdd
- armw := mainwindow.NewAbyssRecorderWindow(currentSettings, drawStuff, comboModel, actions)
+ armw := mainwindow.NewAbyssRecorderWindow(currentSettings, drawStuff, comboModel, actions, clr)
_ = charManager.MainWindow(armw).LoadCache() // assign window to control widgets
charManager.RefreshUI()
- mainwindow.BuildSettingsWidget(charMap, armw.CombatLogCharacterGroup)
-
charManager.OnActivateCharacter =
func(char charmanager.Character) {
if char.CharacterID > 0 {
@@ -87,7 +76,7 @@ func main() {
currentSettings.ActiveCharacter = char.CharacterID
armw.AutoUploadCheckbox.SetEnabled(char.CharacterID > 0)
- _ = writeConfig(currentSettings)
+ _ = config.Write(currentSettings)
}
_ = charManager.SetActiveCharacter(currentSettings.ActiveCharacter)
@@ -96,21 +85,6 @@ func main() {
walk.MsgBox(armw.MainWindow, "No signed in EVE clients detected", "Please login with atleast one character and then restart this application", walk.MsgBoxIconWarning)
}
- armw.ChooseLogDirButton.Clicked().Attach(func() {
- fd := walk.FileDialog{}
- accepted, _ := fd.ShowBrowseFolder(armw.MainWindow)
- if accepted {
- _ = armw.EVEGameLogsFolderLabel.SetText(fd.FilePath)
- clr.SetLogFolder(fd.FilePath)
- logFiles, err = clr.GetLogFiles(time.Now(), time.Duration(24)*time.Hour)
- if err != nil {
- return
- }
- charMap := clr.MapCharactersToFiles(logFiles)
- mainwindow.BuildSettingsWidget(charMap, armw.CombatLogCharacterGroup)
- }
- })
-
notificationIcon := CreateNotificationIcon(armw.MainWindow)
defer func() {
@@ -146,21 +120,22 @@ func main() {
}
recorder.Start(charsChecked)
+
+ _ = armw.MainWindow.Menu().Actions().At(0).SetVisible(false)
armw.CombatLogCharacterGroup.SetEnabled(false)
armw.CaptureSettingsGroup.SetEnabled(false)
- armw.ChooseLogDirButton.SetEnabled(false)
- armw.LootRecordDiscriminatorEdit.SetEnabled(false)
armw.TestServer.SetEnabled(false)
+ _ = armw.Toolbar.Actions().At(3).SetEnabled(false)
_ = armw.RecordingButton.SetText("Stop recording")
} else {
filename, errr := recorder.Stop()
if errr != nil {
- walk.MsgBox(armw.MainWindow, "Error writing recording", err.Error(), walk.MsgBoxIconWarning)
+ walk.MsgBox(armw.MainWindow, "Error writing recording", errr.Error(), walk.MsgBoxIconWarning)
}
char := charManager.ActiveCharacter()
- if armw.AutoUploadCheckbox.Checked() && char != nil {
+ if armw.AutoUploadCheckbox.Checked() && char != nil && errr == nil {
go func(fn string, t string) {
uploadFile, uploadErr := uploader.Upload(fn, t)
if uploadErr != nil {
@@ -171,74 +146,42 @@ func main() {
}(filename, char.CharacterToken)
}
+ _ = armw.MainWindow.Menu().Actions().At(0).SetVisible(true)
armw.CombatLogCharacterGroup.SetEnabled(true)
armw.CaptureSettingsGroup.SetEnabled(true)
- armw.ChooseLogDirButton.SetEnabled(true)
armw.TestServer.SetEnabled(true)
- armw.LootRecordDiscriminatorEdit.SetEnabled(true)
+ _ = armw.Toolbar.Actions().At(3).SetEnabled(true)
_ = armw.RecordingButton.SetText("Start recording")
}
}
armw.RecordingButton.Clicked().Attach(recordingButtonHandler)
+ armw.PresetSaveButton.Clicked().Attach(func() {
+ p := config.Preset{X: currentSettings.X, Y: currentSettings.Y, H: currentSettings.H}
+ _, _ = mainwindow.RunNewPresetDialog(armw.MainWindow, p, currentSettings)
+ _ = config.Write(currentSettings)
+ armw.RefreshPresets(currentSettings)
+ })
+
+ armw.RefreshPresets(currentSettings)
+
armw.MainWindow.Hotkey().Attach(func(hkid int) {
switch hkid {
- case hotkeyRecoder:
+ case config.HotkeyRecoder:
recordingButtonHandler()
- case hotkeyWeather30:
+ case config.HotkeyWeather30:
recorder.GetWeatherStrengthListener(30)()
- case hotkeyWeather50:
+ case config.HotkeyWeather50:
recorder.GetWeatherStrengthListener(50)()
- case hotkeyWeather70:
+ case config.HotkeyWeather70:
recorder.GetWeatherStrengthListener(70)()
}
})
- walk.RegisterGlobalHotKey(armw.MainWindow, hotkeyRecoder, currentSettings.RecorderShortcut)
- walk.RegisterGlobalHotKey(armw.MainWindow, hotkeyWeather30, currentSettings.Weather30Shortcut)
- walk.RegisterGlobalHotKey(armw.MainWindow, hotkeyWeather50, currentSettings.Weather50Shortcut)
- walk.RegisterGlobalHotKey(armw.MainWindow, hotkeyWeather70, currentSettings.Weather70Shortcut)
-
- shortcutRecorderHandler := GetShortcutRecordingHandler(
- armw.RecorderShortcutEdit,
- armw.RecorderShortcutRecordButton,
- armw.MainWindow,
- hotkeyRecoder,
- currentSettings,
- currentSettings.RecorderShortcut,
- )
-
- shortcutWeather30Handler := GetShortcutRecordingHandler(
- armw.Weather30ShortcutEdit,
- armw.Weather30ShortcutRecordButton,
- armw.MainWindow,
- hotkeyWeather30,
- currentSettings,
- currentSettings.Weather30Shortcut,
- )
-
- shortcutWeather50Handler := GetShortcutRecordingHandler(
- armw.Weather50ShortcutEdit,
- armw.Weather50ShortcutRecordButton,
- armw.MainWindow,
- hotkeyWeather50,
- currentSettings,
- currentSettings.Weather50Shortcut,
- )
-
- shortcutWeather70Handler := GetShortcutRecordingHandler(
- armw.Weather70ShortcutEdit,
- armw.Weather70ShortcutRecordButton,
- armw.MainWindow,
- hotkeyWeather70,
- currentSettings,
- currentSettings.Weather70Shortcut,
- )
-
- armw.RecorderShortcutRecordButton.Clicked().Attach(shortcutRecorderHandler)
- armw.Weather30ShortcutRecordButton.Clicked().Attach(shortcutWeather30Handler)
- armw.Weather50ShortcutRecordButton.Clicked().Attach(shortcutWeather50Handler)
- armw.Weather70ShortcutRecordButton.Clicked().Attach(shortcutWeather70Handler)
+ walk.RegisterGlobalHotKey(armw.MainWindow, config.HotkeyRecoder, currentSettings.RecorderShortcut)
+ walk.RegisterGlobalHotKey(armw.MainWindow, config.HotkeyWeather30, currentSettings.Weather30Shortcut)
+ walk.RegisterGlobalHotKey(armw.MainWindow, config.HotkeyWeather50, currentSettings.Weather50Shortcut)
+ walk.RegisterGlobalHotKey(armw.MainWindow, config.HotkeyWeather70, currentSettings.Weather70Shortcut)
go func(cw *walk.CustomWidget) {
t := time.NewTicker(time.Second)
@@ -285,7 +228,7 @@ func main() {
walk.Clipboard().ContentsChanged().Attach(recorder.ClipboardListener)
defer func() {
- err = writeConfig(currentSettings)
+ err = config.Write(currentSettings)
if err != nil {
log.Fatalf("failed to save settings after main window close: %v", err)
}
diff --git a/cmd/abyss-blackbox/recorder.go b/cmd/abyss-blackbox/recorder.go
index bf13888..39a1b1c 100644
--- a/cmd/abyss-blackbox/recorder.go
+++ b/cmd/abyss-blackbox/recorder.go
@@ -15,6 +15,8 @@ import (
"github.com/lxn/walk"
"github.com/shivas/abyss-blackbox/combatlog"
"github.com/shivas/abyss-blackbox/encoding"
+ "github.com/shivas/abyss-blackbox/internal/config"
+ "github.com/shivas/abyss-blackbox/internal/version"
)
const (
@@ -28,7 +30,7 @@ type Recorder struct {
state int
frameChan chan *image.Paletted
loot chan string
- config *captureConfig
+ config *config.CaptureConfig
done chan bool
frames []*image.Paletted
delays []int
@@ -41,7 +43,7 @@ type Recorder struct {
}
// NewRecorder constructs Recorder
-func NewRecorder(frameChan chan *image.Paletted, c *captureConfig, nc chan NotificationMessage, clr *combatlog.Reader) *Recorder {
+func NewRecorder(frameChan chan *image.Paletted, c *config.CaptureConfig, nc chan NotificationMessage, clr *combatlog.Reader) *Recorder {
return &Recorder{
frameChan: frameChan,
loot: make(chan string, 2),
@@ -121,6 +123,10 @@ func (r *Recorder) StartLoop() {
if r.state == RecorderRunning { // append to buffer
r.frames = append(r.frames, frame)
r.delays = append(r.delays, 10)
+
+ if r.weatherStrength == 0 && (len(r.frames)%180 == 0) { // remind every 3 minutes skipping initial frame
+ r.notificationChannel <- NotificationMessage{"Reminder", "Please record weather strength!"}
+ }
}
r.Unlock()
default:
@@ -218,6 +224,14 @@ func (r *Recorder) Stop() (string, error) {
TestServer: r.config.TestServer,
WeatherStrength: int32(r.weatherStrength),
LootRecordDiscriminator: r.config.LootRecordDiscriminator,
+ RecorderVersion: version.RecorderVersion,
+ ManualAbyssTypeOverride: r.config.AbyssTypeOverride,
+ }
+
+ if r.config.AbyssTypeOverride {
+ abyssFile.AbyssShipType = encoding.AbyssRecording_AbyssShipType(r.config.AbyssShipType)
+ abyssFile.AbyssTier = int32(r.config.AbyssTier)
+ abyssFile.AbyssWheather = r.config.AbyssWeather
}
err = abyssFile.Encode(file)
diff --git a/cmd/abyss-blackbox/rsrc.syso b/cmd/abyss-blackbox/rsrc.syso
index 8a3d5f0..7d454d4 100644
Binary files a/cmd/abyss-blackbox/rsrc.syso and b/cmd/abyss-blackbox/rsrc.syso differ
diff --git a/cmd/abyss-blackbox/shortcuts.go b/cmd/abyss-blackbox/shortcuts.go
deleted file mode 100644
index 0573f00..0000000
--- a/cmd/abyss-blackbox/shortcuts.go
+++ /dev/null
@@ -1,37 +0,0 @@
-package main
-
-import (
- "github.com/lxn/walk"
- "github.com/lxn/win"
-)
-
-// GetShortcutRecordingHandler creates handler for shortcut recording.
-func GetShortcutRecordingHandler(
- e *walk.LineEdit,
- b *walk.PushButton,
- m *walk.MainWindow,
- id int,
- settings *captureConfig,
- shortcut walk.Shortcut,
-) func() {
- return func() {
- if !e.Enabled() { // start recording
- e.SetEnabled(true)
- _ = e.SetFocus()
- _ = b.SetText("Save")
-
- if !win.UnregisterHotKey(m.Handle(), id) {
- walk.MsgBox(m, "Failed unregistering hotkey", "failed unregistering key, please restart application", walk.MsgBoxIconWarning)
- return
- }
- } else { // persist new shortcut and rebind
- e.SetEnabled(false)
- _ = b.SetText("Record shortcut")
- if !walk.RegisterGlobalHotKey(m, id, shortcut) {
- walk.MsgBox(m, "Failed registering new hotkey", "failed registering new shortcut key, please restart application", walk.MsgBoxIconWarning)
- return
- }
- _ = writeConfig(settings)
- }
- }
-}
diff --git a/go.mod b/go.mod
index 16f32ae..909e359 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
module github.com/shivas/abyss-blackbox
-go 1.13
+go 1.16
require (
github.com/disintegration/gift v1.2.1
diff --git a/images/select-area.ico b/images/select-area.ico
new file mode 100644
index 0000000..503b922
Binary files /dev/null and b/images/select-area.ico differ
diff --git a/cmd/abyss-blackbox/config.go b/internal/config/config.go
similarity index 79%
rename from cmd/abyss-blackbox/config.go
rename to internal/config/config.go
index 11e4a2b..c4bef5c 100644
--- a/cmd/abyss-blackbox/config.go
+++ b/internal/config/config.go
@@ -1,4 +1,4 @@
-package main
+package config
import (
"encoding/json"
@@ -8,12 +8,23 @@ import (
"sync"
"github.com/lxn/walk"
- "github.com/shivas/abyss-blackbox/internal/mainwindow"
)
-type captureConfig struct {
+const (
+ HotkeyRecoder = iota + 1
+ HotkeyWeather30
+ HotkeyWeather50
+ HotkeyWeather70
+)
+
+type Preset struct {
+ X, Y, H int
+}
+
+type CaptureConfig struct {
sync.Mutex
X, Y, H int
+ Presets map[string]Preset
AppRoot string
Recordings string
FilterThreshold int
@@ -32,37 +43,41 @@ type captureConfig struct {
LootRecordDiscriminator string
ActiveCharacter int32
AutoUpload bool
+ AbyssTypeOverride bool
+ AbyssShipType int
+ AbyssTier int
+ AbyssWeather string
}
// SetRecorderShortcut satisfies ShortcutSetter interface.
-func (c *captureConfig) SetRecorderShortcut(shorcutType int, s walk.Shortcut) {
+func (c *CaptureConfig) SetRecorderShortcut(shorcutType int, s walk.Shortcut) {
switch shorcutType {
- case mainwindow.ShortcutRecorder:
+ case HotkeyRecoder:
c.RecorderShortcut = s
c.RecorderShortcutText = s.String()
- case mainwindow.ShortcutWeather30:
+ case HotkeyWeather30:
c.Weather30Shortcut = s
c.Weather30ShortcutText = s.String()
- case mainwindow.ShortcutWeather50:
+ case HotkeyWeather50:
c.Weather50Shortcut = s
c.Weather50ShortcutText = s.String()
- case mainwindow.ShortcutWeather70:
+ case HotkeyWeather70:
c.Weather70Shortcut = s
c.Weather70ShortcutText = s.String()
}
}
-// readConfig reads configuration from json file, or creates one if file doesn't exist
-func readConfig() (*captureConfig, error) {
+// Read reads configuration from json file, or creates one if file doesn't exist
+func Read() (*CaptureConfig, error) {
appDir, err := filepath.Abs(filepath.Dir(os.Args[0]))
if err != nil {
return nil, err
}
- var c *captureConfig
+ var c *CaptureConfig
load := true
settingsFilename := filepath.Join(appDir, "settings.json")
@@ -82,14 +97,16 @@ func readConfig() (*captureConfig, error) {
eveGameLogsFolder := filepath.Join(usr.HomeDir, "Documents", "EVE", "logs", "Gamelogs")
- c = &captureConfig{
+ c = &CaptureConfig{
AppRoot: appDir,
X: 10,
Y: 10,
H: 400,
+ Presets: make(map[string]Preset),
Recordings: filepath.Join(appDir, "recordings"),
FilterThreshold: 110,
FilteredPreview: false,
+ AbyssTypeOverride: false,
EVEGameLogsFolder: eveGameLogsFolder,
RecorderShortcutText: defaultRecorderShortcut.String(),
RecorderShortcut: defaultRecorderShortcut,
@@ -100,6 +117,9 @@ func readConfig() (*captureConfig, error) {
Weather70ShortcutText: defaultWeather70Shortcut.String(),
Weather70Shortcut: defaultWeather70Shortcut,
LootRecordDiscriminator: "Quafe",
+ AbyssShipType: 1,
+ AbyssTier: 0,
+ AbyssWeather: "Dark",
}
load = false
} else if err != nil {
@@ -141,13 +161,21 @@ func readConfig() (*captureConfig, error) {
if c.LootRecordDiscriminator == "" {
c.LootRecordDiscriminator = "Quafe"
}
+
+ if c.AbyssShipType == 0 {
+ c.AbyssShipType = 1
+ }
+
+ if c.AbyssWeather == "" {
+ c.AbyssWeather = "Dark"
+ }
}
return c, nil
}
-// writeConfig saves configuration to json file
-func writeConfig(c *captureConfig) error {
+// Write saves configuration to json file
+func Write(c *CaptureConfig) error {
settingsFilename := filepath.Join(c.AppRoot, "settings.json")
f, err := os.Create(settingsFilename)
diff --git a/internal/mainwindow/aboutdialog.go b/internal/mainwindow/aboutdialog.go
new file mode 100644
index 0000000..8f91071
--- /dev/null
+++ b/internal/mainwindow/aboutdialog.go
@@ -0,0 +1,92 @@
+package mainwindow
+
+import (
+ "bytes"
+
+ "github.com/lxn/walk"
+ . "github.com/lxn/walk/declarative" // nolint:stylecheck,revive // we needs side effects
+ "github.com/pkg/browser"
+
+ _ "embed"
+ "image"
+ _ "image/png"
+
+ "github.com/shivas/abyss-blackbox/internal/version"
+)
+
+//go:embed triglogo.png
+var logo []byte
+
+func RunAboutDialog(owner walk.Form) (int, error) {
+ var (
+ dlg *walk.Dialog
+ acceptPB *walk.PushButton
+ appLogo *walk.ImageView
+ )
+
+ png, _, _ := image.Decode(bytes.NewReader(logo))
+ img, _ := walk.NewBitmapFromImage(png)
+
+ return (Dialog{
+ AssignTo: &dlg,
+ Title: "About",
+ DefaultButton: &acceptPB,
+ Layout: VBox{},
+ Children: []Widget{
+ Composite{
+ Layout: HBox{},
+ Children: []Widget{
+ ImageView{
+ AssignTo: &appLogo,
+ Image: img,
+ },
+ Composite{
+ Layout: VBox{},
+ Children: []Widget{
+ TextLabel{
+ Text: "Version: " + version.RecorderVersion,
+ },
+ TextLabel{
+ Text: "Go: " + version.GoVersion,
+ },
+ LinkLabel{
+ Alignment: AlignHNearVCenter,
+ Text: `Telemetry site: https://abyssal.space`,
+ OnLinkActivated: func(link *walk.LinkLabelLink) {
+ _ = browser.OpenURL(link.URL())
+ },
+ },
+ LinkLabel{
+ Alignment: AlignHNearVCenter,
+ Text: `Recorder releases: https://github.com/shivas/abyss-blackbox`,
+ OnLinkActivated: func(link *walk.LinkLabelLink) {
+ _ = browser.OpenURL(link.URL())
+ },
+ },
+ LinkLabel{
+ Alignment: AlignHNearVCenter,
+ Text: `For help join Abyssal Lurkers Discord #abyss-telemetry channel.`,
+ OnLinkActivated: func(link *walk.LinkLabelLink) {
+ _ = browser.OpenURL(link.URL())
+ },
+ },
+ },
+ },
+ },
+ },
+ Composite{
+ Layout: HBox{},
+ Children: []Widget{
+ HSpacer{},
+ PushButton{
+ AssignTo: &acceptPB,
+ Text: "OK",
+ OnClicked: func() {
+ dlg.Accept()
+ },
+ },
+ },
+ },
+ },
+ }).Run(owner)
+}
diff --git a/internal/mainwindow/abysstypechooser.go b/internal/mainwindow/abysstypechooser.go
new file mode 100644
index 0000000..64c41ef
--- /dev/null
+++ b/internal/mainwindow/abysstypechooser.go
@@ -0,0 +1,132 @@
+package mainwindow
+
+import (
+ "bytes"
+ "embed"
+ "image"
+ _ "image/png"
+
+ "github.com/lxn/walk"
+ "github.com/shivas/abyss-blackbox/internal/config"
+)
+
+//go:embed images/*
+var abyssIcons embed.FS
+
+type AbyssTypeChooser struct {
+ toolbar *walk.ToolBar
+ cfg *config.CaptureConfig
+ shipTypes []abyssToolbarOption
+ tiers []abyssToolbarOption
+ weathers []abyssToolbarOption
+}
+
+type abyssToolbarOption struct {
+ Title string
+ Icon *walk.Icon
+}
+
+func NewAbyssTypeChooser(t *walk.ToolBar, c *config.CaptureConfig) *AbyssTypeChooser {
+ return &AbyssTypeChooser{toolbar: t, cfg: c}
+}
+
+func (a *AbyssTypeChooser) Init() {
+ a.shipTypes = make([]abyssToolbarOption, 0)
+ a.shipTypes = append(a.shipTypes,
+ abyssToolbarOption{Title: "Cruiser", Icon: embededIcon("images/Ship.png")},
+ abyssToolbarOption{Title: "Destroyers", Icon: embededIcon("images/Ship.png")},
+ abyssToolbarOption{Title: "Frigates", Icon: embededIcon("images/Ship.png")},
+ )
+
+ a.tiers = make([]abyssToolbarOption, 0)
+ a.tiers = append(a.tiers,
+ abyssToolbarOption{Title: "Tier 0", Icon: embededIcon("images/0.png")},
+ abyssToolbarOption{Title: "Tier 1", Icon: embededIcon("images/1.png")},
+ abyssToolbarOption{Title: "Tier 2", Icon: embededIcon("images/2.png")},
+ abyssToolbarOption{Title: "Tier 3", Icon: embededIcon("images/3.png")},
+ abyssToolbarOption{Title: "Tier 4", Icon: embededIcon("images/4.png")},
+ abyssToolbarOption{Title: "Tier 5", Icon: embededIcon("images/5.png")},
+ abyssToolbarOption{Title: "Tier 6", Icon: embededIcon("images/6.png")},
+ )
+
+ a.weathers = make([]abyssToolbarOption, 0)
+ a.weathers = append(a.weathers,
+ abyssToolbarOption{Title: "Dark", Icon: embededIcon("images/Dark.png")},
+ abyssToolbarOption{Title: "Electrical", Icon: embededIcon("images/Electrical.png")},
+ abyssToolbarOption{Title: "Exotic", Icon: embededIcon("images/Exotic.png")},
+ abyssToolbarOption{Title: "Firestorm", Icon: embededIcon("images/Firestorm.png")},
+ abyssToolbarOption{Title: "Gamma", Icon: embededIcon("images/Gamma.png")},
+ )
+
+ for i, s := range a.shipTypes {
+ s := s
+ shipType := i + 1
+ if shipType == a.cfg.AbyssShipType {
+ a.toolbar.Actions().At(0).SetText(s.Title)
+ a.toolbar.Actions().At(0).SetImage(s.Icon)
+ }
+ a.toolbar.Actions().At(0).Menu().Actions().At(i).SetText(s.Title)
+ a.toolbar.Actions().At(0).Menu().Actions().At(i).SetImage(s.Icon)
+ a.toolbar.Actions().At(0).Menu().Actions().At(i).Triggered().Attach(func() {
+ a.toolbar.Actions().At(0).SetText(s.Title)
+ a.toolbar.Actions().At(0).SetImage(s.Icon)
+ a.cfg.AbyssShipType = shipType
+ config.Write(a.cfg)
+ })
+ }
+
+ for i, s := range a.tiers {
+ s := s
+ tier := i
+ if i == a.cfg.AbyssTier {
+ a.toolbar.Actions().At(1).SetText(s.Title)
+ a.toolbar.Actions().At(1).SetImage(s.Icon)
+ }
+ a.toolbar.Actions().At(1).Menu().Actions().At(i).SetText(s.Title)
+ a.toolbar.Actions().At(1).Menu().Actions().At(i).SetImage(s.Icon)
+ a.toolbar.Actions().At(1).Menu().Actions().At(i).Triggered().Attach(func() {
+ a.toolbar.Actions().At(1).SetText(s.Title)
+ a.toolbar.Actions().At(1).SetImage(s.Icon)
+ a.cfg.AbyssTier = tier
+ config.Write(a.cfg)
+ })
+ }
+
+ for i, s := range a.weathers {
+ s := s
+ weather := s.Title
+
+ if weather == a.cfg.AbyssWeather {
+ a.toolbar.Actions().At(2).SetText(s.Title)
+ a.toolbar.Actions().At(2).SetImage(s.Icon)
+ }
+ a.toolbar.Actions().At(2).Menu().Actions().At(i).SetText(s.Title)
+ a.toolbar.Actions().At(2).Menu().Actions().At(i).SetImage(s.Icon)
+ a.toolbar.Actions().At(2).Menu().Actions().At(i).Triggered().Attach(func() {
+ a.toolbar.Actions().At(2).SetText(s.Title)
+ a.toolbar.Actions().At(2).SetImage(s.Icon)
+ a.cfg.AbyssWeather = s.Title
+ config.Write(a.cfg)
+ })
+
+ }
+}
+
+func embededIcon(name string) *walk.Icon {
+ data, err := abyssIcons.ReadFile(name)
+ if err != nil {
+ panic(err)
+ }
+
+ img, _, err := image.Decode(bytes.NewReader(data))
+ if err != nil {
+ panic(err)
+ }
+
+ icon, err := walk.NewIconFromImageForDPI(img, 92)
+ if err != nil {
+ panic(err)
+ }
+
+ return icon
+}
diff --git a/internal/mainwindow/characters.go b/internal/mainwindow/characters.go
deleted file mode 100644
index d44a69a..0000000
--- a/internal/mainwindow/characters.go
+++ /dev/null
@@ -1,21 +0,0 @@
-package mainwindow
-
-import (
- "github.com/lxn/walk"
- "github.com/shivas/abyss-blackbox/combatlog"
-)
-
-func BuildSettingsWidget(characters map[string]combatlog.CombatLogFile, parent walk.Container) {
- for i := 0; i < parent.Children().Len(); i++ {
- parent.Children().At(i).Dispose()
- }
-
- for charName := range characters {
- cb, _ := walk.NewCheckBox(parent)
- _ = cb.SetText(charName)
- _ = cb.SetMinMaxSize(walk.Size{Width: 400}, walk.Size{Width: 800})
- _ = cb.SetAlignment(walk.AlignHNearVCenter)
- cb.SetChecked(false)
- _ = parent.Children().Add(cb)
- }
-}
diff --git a/internal/mainwindow/images/0.png b/internal/mainwindow/images/0.png
new file mode 100644
index 0000000..180230a
Binary files /dev/null and b/internal/mainwindow/images/0.png differ
diff --git a/internal/mainwindow/images/1.png b/internal/mainwindow/images/1.png
new file mode 100644
index 0000000..73c1f4a
Binary files /dev/null and b/internal/mainwindow/images/1.png differ
diff --git a/internal/mainwindow/images/2.png b/internal/mainwindow/images/2.png
new file mode 100644
index 0000000..79445a6
Binary files /dev/null and b/internal/mainwindow/images/2.png differ
diff --git a/internal/mainwindow/images/3.png b/internal/mainwindow/images/3.png
new file mode 100644
index 0000000..5d4b30b
Binary files /dev/null and b/internal/mainwindow/images/3.png differ
diff --git a/internal/mainwindow/images/4.png b/internal/mainwindow/images/4.png
new file mode 100644
index 0000000..867bdf6
Binary files /dev/null and b/internal/mainwindow/images/4.png differ
diff --git a/internal/mainwindow/images/5.png b/internal/mainwindow/images/5.png
new file mode 100644
index 0000000..7365273
Binary files /dev/null and b/internal/mainwindow/images/5.png differ
diff --git a/internal/mainwindow/images/6.png b/internal/mainwindow/images/6.png
new file mode 100644
index 0000000..96926a2
Binary files /dev/null and b/internal/mainwindow/images/6.png differ
diff --git a/internal/mainwindow/images/Dark.png b/internal/mainwindow/images/Dark.png
new file mode 100644
index 0000000..ee4e264
Binary files /dev/null and b/internal/mainwindow/images/Dark.png differ
diff --git a/internal/mainwindow/images/Electrical.png b/internal/mainwindow/images/Electrical.png
new file mode 100644
index 0000000..fefb1f8
Binary files /dev/null and b/internal/mainwindow/images/Electrical.png differ
diff --git a/internal/mainwindow/images/Exotic.png b/internal/mainwindow/images/Exotic.png
new file mode 100644
index 0000000..1395ab9
Binary files /dev/null and b/internal/mainwindow/images/Exotic.png differ
diff --git a/internal/mainwindow/images/Firestorm.png b/internal/mainwindow/images/Firestorm.png
new file mode 100644
index 0000000..078e4dd
Binary files /dev/null and b/internal/mainwindow/images/Firestorm.png differ
diff --git a/internal/mainwindow/images/Gamma.png b/internal/mainwindow/images/Gamma.png
new file mode 100644
index 0000000..1b28bdb
Binary files /dev/null and b/internal/mainwindow/images/Gamma.png differ
diff --git a/internal/mainwindow/images/Ship.png b/internal/mainwindow/images/Ship.png
new file mode 100644
index 0000000..ea72638
Binary files /dev/null and b/internal/mainwindow/images/Ship.png differ
diff --git a/internal/mainwindow/mainwindow.go b/internal/mainwindow/mainwindow.go
index 7451b22..fec5565 100644
--- a/internal/mainwindow/mainwindow.go
+++ b/internal/mainwindow/mainwindow.go
@@ -7,18 +7,12 @@ import (
"github.com/lxn/walk"
. "github.com/lxn/walk/declarative" // nolint:stylecheck,revive // we needs side effects
+ "github.com/lxn/win"
+ "github.com/shivas/abyss-blackbox/combatlog"
+ "github.com/shivas/abyss-blackbox/internal/config"
)
-const (
- ShortcutRecorder = iota
- ShortcutWeather30
- ShortcutWeather50
- ShortcutWeather70
-)
-
-type ShortcutSetter interface {
- SetRecorderShortcut(int, walk.Shortcut)
-}
+const presetToolbarAction = 3
type WindowComboBoxItem struct {
WindowTitle string
@@ -26,47 +20,49 @@ type WindowComboBoxItem struct {
}
type AbyssRecorderWindow struct {
- MainWindow *walk.MainWindow
- FilteredPreview *walk.CheckBox
- DataBinder *walk.DataBinder
- CaptureWidget *walk.CustomWidget
- HSetting *walk.NumberEdit
- RecordingButton *walk.PushButton
- CaptureWindowComboBox *walk.ComboBox
- CombatLogCharacterGroup *walk.GroupBox
- CaptureSettingsGroup *walk.GroupBox
- EVEGameLogsFolderLabel *walk.TextLabel
- ChooseLogDirButton *walk.PushButton
- TestServer *walk.CheckBox
- RecorderShortcutEdit *walk.LineEdit
- RecorderShortcutRecordButton *walk.PushButton
- Weather30ShortcutEdit *walk.LineEdit
- Weather30ShortcutRecordButton *walk.PushButton
- Weather50ShortcutEdit *walk.LineEdit
- Weather50ShortcutRecordButton *walk.PushButton
- Weather70ShortcutEdit *walk.LineEdit
- Weather70ShortcutRecordButton *walk.PushButton
- LootRecordDiscriminatorEdit *walk.LineEdit
- CharacterSwitcherMenu *walk.Menu
- Toolbar *walk.ToolBar
- AutoUploadCheckbox *walk.CheckBox
+ MainWindow *walk.MainWindow
+ FilteredPreview *walk.CheckBox
+ DataBinder *walk.DataBinder
+ CaptureWidget *walk.CustomWidget
+ XSetting *walk.NumberEdit
+ YSetting *walk.NumberEdit
+ HSetting *walk.NumberEdit
+ RecordingButton *walk.PushButton
+ CaptureWindowComboBox *walk.ComboBox
+ CombatLogCharacterGroup *walk.GroupBox
+ CaptureSettingsGroup *walk.GroupBox
+ CapturePreviewGroupBox *walk.GroupBox
+ TestServer *walk.CheckBox
+ CharacterSwitcherMenu *walk.Menu
+ Toolbar *walk.ToolBar
+ AutoUploadCheckbox *walk.CheckBox
+ SettingsAction *walk.Action
+ PresetSwitcherMenu *walk.Menu
+ PresetSaveButton *walk.PushButton
+ PreviewScrollView *walk.ScrollView
+ AbyssTypeToolbar *walk.ToolBar
}
// NewAbyssRecorderWindow creates new main window of recorder.
-func NewAbyssRecorderWindow(config interface{}, customWidgetPaintFunc walk.PaintFunc, comboBoxModel []*WindowComboBoxItem, actions map[string]walk.EventHandler) *AbyssRecorderWindow {
+func NewAbyssRecorderWindow(
+ c interface{},
+ customWidgetPaintFunc walk.PaintFunc,
+ comboBoxModel []*WindowComboBoxItem,
+ actions map[string]walk.EventHandler,
+ clr *combatlog.Reader,
+) *AbyssRecorderWindow {
obj := AbyssRecorderWindow{}
if err := (MainWindow{
AssignTo: &obj.MainWindow,
Title: "Abyssal.Space Blackbox Recorder",
- MinSize: Size{Width: 320, Height: 240},
- Size: Size{Width: 400, Height: 600},
- Layout: HBox{MarginsZero: false},
+ MinSize: Size{Width: 480, Height: 480},
+ Size: Size{Width: 480, Height: 480},
+ Layout: HBox{MarginsZero: true, Alignment: AlignHNearVNear},
DataBinder: DataBinder{
- AssignTo: &obj.DataBinder,
- DataSource: config,
- AutoSubmit: true,
- AutoSubmitDelay: 1 * time.Second,
+ AssignTo: &obj.DataBinder,
+ DataSource: c,
+ AutoSubmit: true,
},
ToolBar: ToolBar{
ButtonStyle: ToolBarButtonImageBeforeText,
@@ -79,12 +75,32 @@ func NewAbyssRecorderWindow(config interface{}, customWidgetPaintFunc walk.Paint
Items: []MenuItem{},
Enabled: false,
},
- Separator{},
Action{
Text: "Add character",
Image: 14,
OnTriggered: actions["add_character"],
},
+ Separator{},
+ Menu{
+ Text: "Presets",
+ Image: 28,
+ AssignTo: &obj.PresetSwitcherMenu,
+ Items: []MenuItem{},
+ Enabled: false,
+ },
+ Separator{},
+ },
+ },
+ MenuItems: []MenuItem{
+ Action{
+ AssignTo: &obj.SettingsAction,
+ Text: "Settings",
+ },
+ Action{
+ Text: "About",
+ OnTriggered: func() {
+ _, _ = RunAboutDialog(obj.MainWindow)
+ },
},
},
Children: []Widget{
@@ -92,24 +108,20 @@ func NewAbyssRecorderWindow(config interface{}, customWidgetPaintFunc walk.Paint
Layout: HBox{},
Children: []Widget{
Composite{
- Layout: VBox{},
+ Layout: VBox{MarginsZero: true},
Alignment: AlignHNearVNear,
Children: []Widget{
GroupBox{
- Title: "Overview settings",
- Layout: VBox{},
+ Title: "Capture region",
+ Layout: VBox{SpacingZero: true},
+ AssignTo: &obj.CaptureSettingsGroup,
Children: []Widget{
- CheckBox{
- AssignTo: &obj.FilteredPreview,
- Text: "show filtered preview",
- Alignment: AlignHNearVNear,
- Checked: Bind("FilteredPreview"),
- },
- GroupBox{
- Title: "Capture region",
- Layout: HBox{},
- AssignTo: &obj.CaptureSettingsGroup,
+ Composite{
+ Layout: HBox{},
Children: []Widget{
+ TextLabel{
+ Text: "EVE window:",
+ },
ComboBox{
AssignTo: &obj.CaptureWindowComboBox,
Model: comboBoxModel,
@@ -119,17 +131,33 @@ func NewAbyssRecorderWindow(config interface{}, customWidgetPaintFunc walk.Paint
Value: Bind("EVEClientWindowTitle"),
Editable: false,
},
+ CheckBox{
+ AssignTo: &obj.FilteredPreview,
+ Text: "show filtered preview",
+ Alignment: AlignHNearVNear,
+ Checked: Bind("FilteredPreview"),
+ },
+ HSpacer{},
+ },
+ },
+ Composite{
+ Layout: HBox{},
+ Children: []Widget{
TextLabel{
Text: "X:",
},
NumberEdit{
- Value: Bind("X"),
+ AssignTo: &obj.XSetting,
+ MinSize: Size{Width: 50, Height: 10},
+ Value: Bind("X"),
},
TextLabel{
Text: "Y:",
},
NumberEdit{
- Value: Bind("Y"),
+ AssignTo: &obj.YSetting,
+ MinSize: Size{Width: 50, Height: 10},
+ Value: Bind("Y"),
},
TextLabel{
Text: "Height:",
@@ -137,6 +165,7 @@ func NewAbyssRecorderWindow(config interface{}, customWidgetPaintFunc walk.Paint
NumberEdit{
AssignTo: &obj.HSetting,
Value: Bind("H"),
+ MinSize: Size{Width: 50, Height: 10},
OnValueChanged: func() {
if obj.CaptureWidget != nil {
_ = obj.CaptureWidget.SetMinMaxSizePixels(walk.Size{Height: int(obj.HSetting.Value()), Width: 255}, walk.Size{})
@@ -144,207 +173,153 @@ func NewAbyssRecorderWindow(config interface{}, customWidgetPaintFunc walk.Paint
}
},
},
+ PushButton{
+ AssignTo: &obj.PresetSaveButton,
+ Text: "Save as preset",
+ },
+ HSpacer{},
},
},
},
},
- GroupBox{
- Title: "Server flag:",
- Layout: VBox{},
- Alignment: AlignHNearVNear,
- Children: []Widget{
- CheckBox{
- AssignTo: &obj.TestServer,
- Text: "Test Server (Singularity)",
- Alignment: AlignHNearVNear,
- Checked: Bind("TestServer"),
- },
- },
- },
- GroupBox{
- Title: "Loot recording settings:",
- Layout: VBox{},
- Alignment: AlignHNearVNear,
- Children: []Widget{
- TextLabel{
- Text: "Ship loot record discriminator item: (quantity in each ship should be different)",
- },
- LineEdit{
- Text: Bind("LootRecordDiscriminator"),
- AssignTo: &obj.LootRecordDiscriminatorEdit,
- OnEditingFinished: func() {
- _ = obj.DataBinder.Submit()
- },
- },
- },
- },
- GroupBox{
- Title: "Shortcut configuration:",
- Layout: VBox{},
+ Composite{
+ Layout: HBox{MarginsZero: true},
Alignment: AlignHNearVNear,
Children: []Widget{
- Composite{
- Layout: HBox{},
- Alignment: AlignHNearVNear,
- Children: []Widget{
- TextLabel{
- Text: "Start/Stop shortcut",
- },
- LineEdit{
- Text: Bind("RecorderShortcutText"),
- AssignTo: &obj.RecorderShortcutEdit,
- OnKeyPress: func(key walk.Key) {
- shortcut := walk.Shortcut{Modifiers: walk.ModifiersDown(), Key: key}
- _ = obj.RecorderShortcutEdit.SetText(shortcut.String())
- c, ok := config.(ShortcutSetter)
- if ok {
- c.SetRecorderShortcut(ShortcutRecorder, shortcut)
- }
- },
- Enabled: false,
- ReadOnly: true,
- },
- PushButton{
- AssignTo: &obj.RecorderShortcutRecordButton,
- MinSize: Size{Height: 20},
- Text: "Record shortcut",
- },
- },
- },
- Composite{
- Layout: HBox{},
- Alignment: AlignHNearVNear,
- Children: []Widget{
- TextLabel{
- Text: "Weather strength 30%",
- },
- LineEdit{
- Text: Bind("Weather30ShortcutText"),
- AssignTo: &obj.Weather30ShortcutEdit,
- OnKeyPress: func(key walk.Key) {
- shortcut := walk.Shortcut{Modifiers: walk.ModifiersDown(), Key: key}
- _ = obj.Weather30ShortcutEdit.SetText(shortcut.String())
- c, ok := config.(ShortcutSetter)
- if ok {
- c.SetRecorderShortcut(ShortcutWeather30, shortcut)
- }
- },
- Enabled: false,
- ReadOnly: true,
- },
- PushButton{
- AssignTo: &obj.Weather30ShortcutRecordButton,
- MinSize: Size{Height: 20},
- Text: "Record shortcut",
- },
- },
- },
- Composite{
- Layout: HBox{},
- Alignment: AlignHNearVNear,
+ GroupBox{
+ Title: "Manual abyss type override",
+ Checkable: true,
+ Checked: Bind("AbyssTypeOverride"),
+ Layout: VBox{},
+ AlwaysConsumeSpace: true,
+ Alignment: AlignHNearVNear,
Children: []Widget{
- TextLabel{
- Text: "Weather strength 50%",
- },
- LineEdit{
- Text: Bind("Weather50ShortcutText"),
- AssignTo: &obj.Weather50ShortcutEdit,
- OnKeyPress: func(key walk.Key) {
- shortcut := walk.Shortcut{Modifiers: walk.ModifiersDown(), Key: key}
- _ = obj.Weather50ShortcutEdit.SetText(shortcut.String())
- c, ok := config.(ShortcutSetter)
- if ok {
- c.SetRecorderShortcut(ShortcutWeather50, shortcut)
- }
+ ToolBar{
+ AssignTo: &obj.AbyssTypeToolbar,
+ ButtonStyle: ToolBarButtonImageBeforeText,
+ Items: []MenuItem{
+ Menu{
+ Text: "Ship",
+ Items: []MenuItem{
+ Action{
+ Text: "Cruiser",
+ },
+ Action{
+ Text: "Destroyers",
+ },
+ Action{
+ Text: "Frigates",
+ },
+ },
+ },
+ Menu{
+ Text: "Tier",
+ Items: []MenuItem{
+ Action{
+ Text: "T0",
+ },
+ Action{
+ Text: "T1",
+ },
+ Action{
+ Text: "T2",
+ },
+ Action{
+ Text: "T3",
+ },
+ Action{
+ Text: "T4",
+ },
+ Action{
+ Text: "T5",
+ },
+ Action{
+ Text: "T6",
+ },
+ },
+ },
+ Menu{
+ Text: "Weather",
+ Items: []MenuItem{
+ Action{
+ Text: "Gamma",
+ },
+ Action{
+ Text: "Exotic",
+ },
+ Action{
+ Text: "Dark",
+ },
+ Action{
+ Text: "Firestorm",
+ },
+ Action{
+ Text: "Electrical",
+ },
+ },
+ },
},
- Enabled: false,
- ReadOnly: true,
- },
- PushButton{
- AssignTo: &obj.Weather50ShortcutRecordButton,
- MinSize: Size{Height: 20},
- Text: "Record shortcut",
},
},
},
- Composite{
- Layout: HBox{},
+ HSpacer{},
+ GroupBox{
+ Title: "Server flag:",
+ Layout: VBox{},
Alignment: AlignHNearVNear,
Children: []Widget{
- TextLabel{
- Text: "Weather strength 70%",
- },
- LineEdit{
- Text: Bind("Weather70ShortcutText"),
- AssignTo: &obj.Weather70ShortcutEdit,
- OnKeyPress: func(key walk.Key) {
- shortcut := walk.Shortcut{Modifiers: walk.ModifiersDown(), Key: key}
- _ = obj.Weather70ShortcutEdit.SetText(shortcut.String())
- c, ok := config.(ShortcutSetter)
- if ok {
- c.SetRecorderShortcut(ShortcutWeather70, shortcut)
- }
- },
- Enabled: false,
- ReadOnly: true,
- },
- PushButton{
- AssignTo: &obj.Weather70ShortcutRecordButton,
- MinSize: Size{Height: 20},
- Text: "Record shortcut",
+ CheckBox{
+ AssignTo: &obj.TestServer,
+ Text: "Test Server (Singularity)",
+ Alignment: AlignHNearVNear,
+ Checked: Bind("TestServer"),
},
},
},
+ // HSpacer{},
},
+ },
+ GroupBox{
+ Title: "Capture combatlog of characters:",
+ Layout: VBox{},
+ Alignment: AlignHNearVNear,
+ AssignTo: &obj.CombatLogCharacterGroup,
+ Children: []Widget{},
AlwaysConsumeSpace: true,
MinSize: Size{Height: 20},
},
- GroupBox{
- Title: "Combat log capture",
- Layout: VBox{},
- Alignment: AlignHNearVNear,
- Children: []Widget{
- TextLabel{
- Text: Bind("EVEGameLogsFolder"),
- AssignTo: &obj.EVEGameLogsFolderLabel,
- },
- PushButton{
- Text: "Choose",
- AssignTo: &obj.ChooseLogDirButton,
- },
- GroupBox{
- Title: "Capture combatlog of characters:",
- Layout: VBox{},
- Alignment: AlignHNearVNear,
- AssignTo: &obj.CombatLogCharacterGroup,
- Children: []Widget{},
- AlwaysConsumeSpace: true,
- MinSize: Size{Height: 20},
- },
- CheckBox{
- Text: "Upload file after recording complete",
- AssignTo: &obj.AutoUploadCheckbox,
- Alignment: AlignHNearVCenter,
- Enabled: false,
- Checked: Bind("AutoUpload"),
- ToolTipText: "Automatically uploads recorded file to active character account.",
- },
- PushButton{
- AssignTo: &obj.RecordingButton,
- MinSize: Size{Height: 40},
- Text: "Start recording",
- },
- },
+ CheckBox{
+ Text: "Upload file after recording complete",
+ AssignTo: &obj.AutoUploadCheckbox,
+ Alignment: AlignHNearVCenter,
+ Enabled: false,
+ Checked: Bind("AutoUpload"),
+ ToolTipText: "Automatically uploads recorded file to active character account.",
+ },
+ PushButton{
+ AssignTo: &obj.RecordingButton,
+ MinSize: Size{Height: 40},
+ Text: "Start recording",
},
},
},
GroupBox{
- Title: "Captured region:",
- Layout: VBox{},
+ Title: "Captured region:",
+ Layout: VBox{},
+ AssignTo: &obj.CapturePreviewGroupBox,
+ OnSizeChanged: func() {
+ h := obj.MainWindow.AsContainerBase().MinSizeHint()
+ c := obj.MainWindow.AsContainerBase().Size()
+ _ = obj.MainWindow.SetMinMaxSize(h, walk.Size{})
+ if c.Height > h.Height {
+ _ = obj.MainWindow.AsFormBase().WindowBase.SetSize(h)
+ }
+
+ },
Children: []Widget{
CustomWidget{
AssignTo: &obj.CaptureWidget,
- MinSize: Size{Width: 255, Height: 800},
+ MinSize: Size{Width: 255, Height: 1},
Paint: customWidgetPaintFunc,
InvalidatesOnResize: true,
ClearsBackground: true,
@@ -359,5 +334,87 @@ func NewAbyssRecorderWindow(config interface{}, customWidgetPaintFunc walk.Paint
log.Fatal(err)
}
+ logFiles, _ := clr.GetLogFiles(time.Now(), time.Duration(24)*time.Hour)
+
+ charMap := clr.MapCharactersToFiles(logFiles)
+ buildRunnerList(charMap, obj.CombatLogCharacterGroup)
+
+ settingsChangedHandler := func(c *config.CaptureConfig) {
+ _ = config.Write(c)
+ clr.SetLogFolder(c.EVEGameLogsFolder)
+ logFiles, err := clr.GetLogFiles(time.Now(), time.Duration(24)*time.Hour)
+
+ if err != nil {
+ return
+ }
+
+ buildRunnerList(clr.MapCharactersToFiles(logFiles), obj.CombatLogCharacterGroup)
+
+ // rebind hotkeys
+ win.UnregisterHotKey(obj.MainWindow.Handle(), config.HotkeyRecoder)
+ win.UnregisterHotKey(obj.MainWindow.Handle(), config.HotkeyWeather30)
+ win.UnregisterHotKey(obj.MainWindow.Handle(), config.HotkeyWeather50)
+ win.UnregisterHotKey(obj.MainWindow.Handle(), config.HotkeyWeather70)
+
+ walk.RegisterGlobalHotKey(obj.MainWindow, config.HotkeyRecoder, c.RecorderShortcut)
+ walk.RegisterGlobalHotKey(obj.MainWindow, config.HotkeyWeather30, c.Weather30Shortcut)
+ walk.RegisterGlobalHotKey(obj.MainWindow, config.HotkeyWeather50, c.Weather50Shortcut)
+ walk.RegisterGlobalHotKey(obj.MainWindow, config.HotkeyWeather70, c.Weather70Shortcut)
+ }
+
+ obj.SettingsAction.Triggered().Attach(func() {
+ _, _ = RunAnimalDialog(obj.MainWindow, c, settingsChangedHandler)
+ })
+
+ chooser := NewAbyssTypeChooser(obj.AbyssTypeToolbar, c.(*config.CaptureConfig))
+ chooser.Init()
+
return &obj
}
+
+func (m *AbyssRecorderWindow) RefreshPresets(c *config.CaptureConfig) {
+ _ = m.PresetSwitcherMenu.Actions().Clear()
+
+ for presetName := range c.Presets {
+ presetName := presetName
+ action := walk.NewAction()
+ _ = action.SetText(presetName)
+ _ = action.Triggered().Attach(func() {
+ modifiers := walk.ModifiersDown()
+ if modifiers == walk.ModControl {
+ delete(c.Presets, presetName)
+ _ = config.Write(c)
+ m.RefreshPresets(c)
+ } else {
+ p := c.Presets[presetName]
+ _ = m.XSetting.SetValue(float64(p.X))
+ _ = m.YSetting.SetValue(float64(p.Y))
+ _ = m.HSetting.SetValue(float64(p.H))
+ }
+ })
+
+ _ = m.PresetSwitcherMenu.Actions().Add(action)
+ }
+
+ if len(c.Presets) > 0 {
+ _ = m.Toolbar.Actions().At(presetToolbarAction).SetEnabled(true)
+ } else {
+ _ = m.Toolbar.Actions().At(presetToolbarAction).SetEnabled(false)
+ }
+}
+
+func buildRunnerList(characters map[string]combatlog.CombatLogFile, parent walk.Container) {
+ for i := 0; i < parent.Children().Len(); i++ {
+ w := parent.Children().At(i)
+ w.SetVisible(false)
+ }
+
+ for charName := range characters {
+ cb, _ := walk.NewCheckBox(parent)
+ _ = cb.SetText(charName)
+ _ = cb.SetMinMaxSize(walk.Size{Width: 400}, walk.Size{Width: 800})
+ _ = cb.SetAlignment(walk.AlignHNearVCenter)
+ cb.SetChecked(false)
+ _ = parent.Children().Add(cb)
+ }
+}
diff --git a/internal/mainwindow/newpresetdialog.go b/internal/mainwindow/newpresetdialog.go
new file mode 100644
index 0000000..de40e7a
--- /dev/null
+++ b/internal/mainwindow/newpresetdialog.go
@@ -0,0 +1,73 @@
+package mainwindow
+
+import (
+ "log"
+
+ "github.com/shivas/abyss-blackbox/internal/config"
+
+ "github.com/lxn/walk"
+ . "github.com/lxn/walk/declarative" // nolint:stylecheck,revive // we needs side effects
+)
+
+func RunNewPresetDialog(owner walk.Form, presetValue config.Preset, c *config.CaptureConfig) (int, error) {
+ var (
+ dlg *walk.Dialog
+ db *walk.DataBinder
+ acceptPB, cancelPB *walk.PushButton
+ PresetNameEdit *walk.LineEdit
+ )
+
+ data := map[string]interface{}{"Name": ""}
+
+ return Dialog{
+ AssignTo: &dlg,
+ Title: "New preset",
+ DefaultButton: &acceptPB,
+ CancelButton: &cancelPB,
+ DataBinder: DataBinder{
+ AssignTo: &db,
+ DataSource: data,
+ OnSubmitted: func() {
+ log.Printf("new preset saving: %#v with values: %v", data, presetValue)
+ if c.Presets == nil {
+ c.Presets = make(map[string]config.Preset)
+ }
+
+ c.Presets[data["Name"].(string)] = presetValue
+ },
+ },
+ Layout: VBox{},
+ Children: []Widget{
+ TextLabel{
+ Text: "Preset name:",
+ },
+ LineEdit{
+ Text: Bind("Name"),
+ AssignTo: &PresetNameEdit,
+ },
+ Composite{
+ Layout: HBox{},
+ Children: []Widget{
+ HSpacer{},
+ PushButton{
+ AssignTo: &acceptPB,
+ Text: "OK",
+ OnClicked: func() {
+ if err := db.Submit(); err != nil {
+ log.Print(err)
+ return
+ }
+
+ dlg.Accept()
+ },
+ },
+ PushButton{
+ AssignTo: &cancelPB,
+ Text: "Cancel",
+ OnClicked: func() { dlg.Cancel() },
+ },
+ },
+ },
+ },
+ }.Run(owner)
+}
diff --git a/internal/mainwindow/settings.go b/internal/mainwindow/settings.go
new file mode 100644
index 0000000..d8a1ee5
--- /dev/null
+++ b/internal/mainwindow/settings.go
@@ -0,0 +1,280 @@
+package mainwindow
+
+import (
+ "log"
+
+ "github.com/shivas/abyss-blackbox/internal/config"
+
+ "github.com/lxn/walk"
+ . "github.com/lxn/walk/declarative" // nolint:stylecheck,revive // we needs side effects
+)
+
+type ShortcutSetter interface {
+ SetRecorderShortcut(int, walk.Shortcut)
+}
+
+func RunAnimalDialog(owner walk.Form, conf interface{}, onSettingsSubmit func(c *config.CaptureConfig)) (int, error) {
+ var (
+ dlg *walk.Dialog
+ db *walk.DataBinder
+ acceptPB, cancelPB *walk.PushButton
+ RecorderShortcutEdit *walk.LineEdit
+ RecorderShortcutRecordButton *walk.PushButton
+ Weather30ShortcutEdit *walk.LineEdit
+ Weather30ShortcutRecordButton *walk.PushButton
+ Weather50ShortcutEdit *walk.LineEdit
+ Weather50ShortcutRecordButton *walk.PushButton
+ Weather70ShortcutEdit *walk.LineEdit
+ Weather70ShortcutRecordButton *walk.PushButton
+ LootRecordDiscriminatorEdit *walk.LineEdit
+ EVEGameLogsFolderLabel *walk.TextLabel
+ ChooseLogDirButton *walk.PushButton
+ )
+
+ shortcutStringToKey := make(map[string]walk.Shortcut)
+
+ return Dialog{
+ AssignTo: &dlg,
+ Title: "Settings",
+ DefaultButton: &acceptPB,
+ CancelButton: &cancelPB,
+ DataBinder: DataBinder{
+ AssignTo: &db,
+ DataSource: conf,
+ OnSubmitted: func() {
+ if c, ok := conf.(*config.CaptureConfig); ok {
+ if setter, ok2 := conf.(ShortcutSetter); ok2 {
+ if key, exists := shortcutStringToKey[c.RecorderShortcutText]; exists {
+ setter.SetRecorderShortcut(config.HotkeyRecoder, key)
+ }
+ if key, exists := shortcutStringToKey[c.Weather30ShortcutText]; exists {
+ setter.SetRecorderShortcut(config.HotkeyWeather30, key)
+ }
+ if key, exists := shortcutStringToKey[c.Weather50ShortcutText]; exists {
+ setter.SetRecorderShortcut(config.HotkeyWeather50, key)
+ }
+ if key, exists := shortcutStringToKey[c.Weather70ShortcutText]; exists {
+ setter.SetRecorderShortcut(config.HotkeyWeather70, key)
+ }
+ }
+ onSettingsSubmit(c)
+ }
+ },
+ },
+ MinSize: Size{Width: 500, Height: 300},
+ Layout: VBox{},
+ Children: []Widget{
+ GroupBox{
+ Title: "Combat log capture",
+ Layout: VBox{},
+ Alignment: AlignHNearVNear,
+ Children: []Widget{
+ TextLabel{
+ Text: Bind("EVEGameLogsFolder"),
+ AssignTo: &EVEGameLogsFolderLabel,
+ },
+ PushButton{
+ Text: "Choose",
+ AssignTo: &ChooseLogDirButton,
+ OnClicked: func() {
+ fd := walk.FileDialog{}
+ accepted, _ := fd.ShowBrowseFolder(owner)
+ if accepted {
+ _ = EVEGameLogsFolderLabel.SetText(fd.FilePath)
+ }
+ },
+ },
+ },
+ },
+ GroupBox{
+ Title: "Loot recording settings:",
+ Layout: VBox{},
+ Alignment: AlignHNearVNear,
+ Children: []Widget{
+ TextLabel{
+ Text: "Ship loot record discriminator item: (quantity in each ship should be different)",
+ },
+ LineEdit{
+ Text: Bind("LootRecordDiscriminator"),
+ AssignTo: &LootRecordDiscriminatorEdit,
+ },
+ TextLabel{
+ Text: "Only used when multiboxing destroyer or frigate runs.",
+ },
+ },
+ },
+ GroupBox{
+ Title: "Shortcut configuration:",
+ Layout: VBox{},
+ Alignment: AlignHNearVNear,
+ Children: []Widget{
+ Composite{
+ Layout: HBox{},
+ Alignment: AlignHNearVNear,
+ Children: []Widget{
+ TextLabel{
+ Text: "Start/Stop shortcut",
+ },
+ LineEdit{
+ Text: Bind("RecorderShortcutText"),
+ AssignTo: &RecorderShortcutEdit,
+ OnKeyPress: func(key walk.Key) {
+ shortcut := walk.Shortcut{Modifiers: walk.ModifiersDown(), Key: key}
+ _ = RecorderShortcutEdit.SetText(shortcut.String())
+ shortcutStringToKey[shortcut.String()] = shortcut
+ },
+ Enabled: false,
+ ReadOnly: true,
+ },
+ PushButton{
+ AssignTo: &RecorderShortcutRecordButton,
+ MinSize: Size{Height: 20},
+ Text: "Record shortcut",
+ OnClicked: func() {
+ if !RecorderShortcutEdit.Enabled() { // start recording
+ RecorderShortcutEdit.SetEnabled(true)
+ _ = RecorderShortcutEdit.SetFocus()
+ _ = RecorderShortcutRecordButton.SetText("Save")
+ } else { // persist new shortcut and rebind
+ RecorderShortcutEdit.SetEnabled(false)
+ _ = RecorderShortcutRecordButton.SetText("Record shortcut")
+ }
+ },
+ },
+ },
+ },
+ Composite{
+ Layout: HBox{},
+ Alignment: AlignHNearVNear,
+ Children: []Widget{
+ TextLabel{
+ Text: "Weather strength 30%",
+ },
+ LineEdit{
+ Text: Bind("Weather30ShortcutText"),
+ AssignTo: &Weather30ShortcutEdit,
+ OnKeyPress: func(key walk.Key) {
+ shortcut := walk.Shortcut{Modifiers: walk.ModifiersDown(), Key: key}
+ _ = Weather30ShortcutEdit.SetText(shortcut.String())
+ shortcutStringToKey[shortcut.String()] = shortcut
+ },
+ Enabled: false,
+ ReadOnly: true,
+ },
+ PushButton{
+ AssignTo: &Weather30ShortcutRecordButton,
+ MinSize: Size{Height: 20},
+ Text: "Record shortcut",
+ OnClicked: func() {
+ if !Weather30ShortcutEdit.Enabled() { // start recording
+ Weather30ShortcutEdit.SetEnabled(true)
+ _ = Weather30ShortcutEdit.SetFocus()
+ _ = Weather30ShortcutRecordButton.SetText("Save")
+ } else { // persist new shortcut and rebind
+ Weather30ShortcutEdit.SetEnabled(false)
+ _ = Weather30ShortcutRecordButton.SetText("Record shortcut")
+ }
+ },
+ },
+ },
+ },
+ Composite{
+ Layout: HBox{},
+ Alignment: AlignHNearVNear,
+ Children: []Widget{
+ TextLabel{
+ Text: "Weather strength 50%",
+ },
+ LineEdit{
+ Text: Bind("Weather50ShortcutText"),
+ AssignTo: &Weather50ShortcutEdit,
+ OnKeyPress: func(key walk.Key) {
+ shortcut := walk.Shortcut{Modifiers: walk.ModifiersDown(), Key: key}
+ _ = Weather50ShortcutEdit.SetText(shortcut.String())
+ shortcutStringToKey[shortcut.String()] = shortcut
+ },
+ Enabled: false,
+ ReadOnly: true,
+ },
+ PushButton{
+ AssignTo: &Weather50ShortcutRecordButton,
+ MinSize: Size{Height: 20},
+ Text: "Record shortcut",
+ OnClicked: func() {
+ if !Weather50ShortcutEdit.Enabled() { // start recording
+ Weather50ShortcutEdit.SetEnabled(true)
+ _ = Weather50ShortcutEdit.SetFocus()
+ _ = Weather50ShortcutRecordButton.SetText("Save")
+ } else { // persist new shortcut and rebind
+ Weather50ShortcutEdit.SetEnabled(false)
+ _ = Weather50ShortcutRecordButton.SetText("Record shortcut")
+ }
+ },
+ },
+ },
+ },
+ Composite{
+ Layout: HBox{},
+ Alignment: AlignHNearVNear,
+ Children: []Widget{
+ TextLabel{
+ Text: "Weather strength 70%",
+ },
+ LineEdit{
+ Text: Bind("Weather70ShortcutText"),
+ AssignTo: &Weather70ShortcutEdit,
+ OnKeyPress: func(key walk.Key) {
+ shortcut := walk.Shortcut{Modifiers: walk.ModifiersDown(), Key: key}
+ _ = Weather70ShortcutEdit.SetText(shortcut.String())
+ shortcutStringToKey[shortcut.String()] = shortcut
+ },
+ Enabled: false,
+ ReadOnly: true,
+ },
+ PushButton{
+ AssignTo: &Weather70ShortcutRecordButton,
+ MinSize: Size{Height: 20},
+ Text: "Record shortcut",
+ OnClicked: func() {
+ if !Weather70ShortcutEdit.Enabled() { // start recording
+ Weather70ShortcutEdit.SetEnabled(true)
+ _ = Weather70ShortcutEdit.SetFocus()
+ _ = Weather70ShortcutRecordButton.SetText("Save")
+ } else { // persist new shortcut and rebind
+ Weather70ShortcutEdit.SetEnabled(false)
+ _ = Weather70ShortcutRecordButton.SetText("Record shortcut")
+ }
+ },
+ },
+ },
+ },
+ },
+ AlwaysConsumeSpace: true,
+ MinSize: Size{Height: 20},
+ },
+ Composite{
+ Layout: HBox{},
+ Children: []Widget{
+ HSpacer{},
+ PushButton{
+ AssignTo: &acceptPB,
+ Text: "OK",
+ OnClicked: func() {
+ if err := db.Submit(); err != nil {
+ log.Print(err)
+ return
+ }
+
+ dlg.Accept()
+ },
+ },
+ PushButton{
+ AssignTo: &cancelPB,
+ Text: "Cancel",
+ OnClicked: func() { dlg.Cancel() },
+ },
+ },
+ },
+ },
+ }.Run(owner)
+}
diff --git a/internal/mainwindow/triglogo.png b/internal/mainwindow/triglogo.png
new file mode 100644
index 0000000..b53c8d7
Binary files /dev/null and b/internal/mainwindow/triglogo.png differ
diff --git a/internal/version/version.go b/internal/version/version.go
new file mode 100644
index 0000000..38ba06c
--- /dev/null
+++ b/internal/version/version.go
@@ -0,0 +1,4 @@
+package version
+
+var RecorderVersion string
+var GoVersion string