117 lines
2.7 KiB
Go
117 lines
2.7 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"fmt"
|
|
"image/png"
|
|
"log"
|
|
"os"
|
|
"time"
|
|
|
|
"github.com/dop251/goja"
|
|
"github.com/go-vgo/robotgo"
|
|
qt "github.com/mappu/miqt/qt6"
|
|
"github.com/vcaesar/gcv"
|
|
)
|
|
|
|
const (
|
|
jsWait string = `SIKULI_WAIT`
|
|
jsTimeout string = `SIKULI_TIMEOUT`
|
|
jsThreshold string = `SIKULI_THRESHOLD`
|
|
|
|
DefaultWait = 200 * time.Millisecond
|
|
DefaultTimeout = 30 * time.Second
|
|
DefaultThreshold = float64(0.9)
|
|
)
|
|
|
|
func runScript() {
|
|
|
|
mw.MainWindow.Hide()
|
|
defer mw.MainWindow.Show()
|
|
|
|
startTime := time.Now()
|
|
|
|
time.Sleep(DefaultWait)
|
|
|
|
rt := goja.New()
|
|
rt.GlobalObject().Set("ClickAt", func(filepath string, x, y int) error {
|
|
|
|
// Load image
|
|
bb, err := os.ReadFile(filepath)
|
|
if err != nil {
|
|
return fmt.Errorf("Opening file %q: %v", filepath, err)
|
|
}
|
|
|
|
searchImg, err := png.Decode(bytes.NewReader(bb))
|
|
if err != nil {
|
|
return fmt.Errorf("Parsing PNG file %q: %v", filepath, err)
|
|
}
|
|
|
|
wait := time.Duration(rt.Get(jsWait).ToInteger()) * time.Millisecond
|
|
timeout := time.Duration(rt.Get(jsTimeout).ToInteger()) * time.Millisecond
|
|
threshold := rt.Get(jsThreshold).ToFloat()
|
|
if threshold > 1 || threshold < 0 {
|
|
return fmt.Errorf("SIKULI_THRESHOLD should be between 0 and 1, got %.2f", threshold)
|
|
}
|
|
|
|
// Loop and wait for target to appear
|
|
|
|
startTime := time.Now()
|
|
|
|
for {
|
|
|
|
// Take screen capture
|
|
|
|
bmp := robotgo.CaptureScreen(0)
|
|
fullScreenImg := robotgo.ToImage(bmp)
|
|
robotgo.FreeBitmap(bmp)
|
|
|
|
// Load into gocv
|
|
// FindImg() uses TM_CCOEFF_NORMED, which puts the best match in _max_ not _min_
|
|
_, maxV, _, maxP := gcv.FindImg(searchImg, fullScreenImg)
|
|
|
|
// Check if the maxV is within our wanted bounds
|
|
|
|
if float64(maxV) > threshold {
|
|
ok := robotgo.MoveMouseSmooth(maxP.X+x, maxP.Y+y)
|
|
if !ok {
|
|
return errors.New("MoveMouse failure")
|
|
}
|
|
|
|
robotgo.MouseClick()
|
|
|
|
// Success
|
|
return nil
|
|
}
|
|
|
|
// Didn't find a match
|
|
// If there's still time left, then keep waiting a bit longer
|
|
|
|
if time.Now().Sub(startTime) > timeout {
|
|
return fmt.Errorf("Image %q not found (timed out after %s)", filepath, timeout.Truncate(100*time.Millisecond).String())
|
|
}
|
|
|
|
time.Sleep(wait)
|
|
}
|
|
})
|
|
|
|
log.Print(mw.textEdit.ToPlainText()) // n.b. missing img tag
|
|
|
|
src := html_to_src(mw.textEdit.ToHtml()) // n.b. lots of extra junk
|
|
|
|
rt.Set(jsWait, DefaultWait.Milliseconds())
|
|
rt.Set(jsTimeout, DefaultTimeout.Milliseconds())
|
|
rt.Set(jsThreshold, DefaultThreshold)
|
|
|
|
_, err := rt.RunString(src)
|
|
|
|
simpleDuration := time.Now().Sub(startTime).Truncate(100 * time.Millisecond)
|
|
mw.statusbar.ShowMessage(fmt.Sprintf("Script execution completed in %s", simpleDuration.String()))
|
|
|
|
if err != nil {
|
|
mw.MainWindow.Show()
|
|
qt.QMessageBox_Critical(mw.MainWindow.QWidget, "Script error", err.Error())
|
|
}
|
|
}
|