Merge pull request #10 from SpeckiJ/repl-improvements
REPL improvements
This commit is contained in:
commit
c912986436
|
@ -6,6 +6,7 @@ import (
|
||||||
_ "image/gif" // register gif, jpeg, png format handlers
|
_ "image/gif" // register gif, jpeg, png format handlers
|
||||||
_ "image/jpeg"
|
_ "image/jpeg"
|
||||||
"image/png"
|
"image/png"
|
||||||
|
"math"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"golang.org/x/image/draw"
|
"golang.org/x/image/draw"
|
||||||
|
@ -63,10 +64,28 @@ func ImgColorFilter(img *image.NRGBA, from, to color.NRGBA) *image.NRGBA {
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func ScaleImage(img image.Image, factor int) (scaled *image.NRGBA) {
|
func ScaleImage(img image.Image, factorX, factorY float64, highQuality bool) (scaled *image.NRGBA) {
|
||||||
b := img.Bounds()
|
b := img.Bounds()
|
||||||
scaledBounds := image.Rect(0, 0, b.Max.X*factor, b.Max.Y*factor)
|
newX := int(math.Ceil(factorX * float64(b.Max.X)))
|
||||||
|
newY := int(math.Ceil(factorY * float64(b.Max.Y)))
|
||||||
|
scaledBounds := image.Rect(0, 0, newX, newY)
|
||||||
scaledImg := image.NewNRGBA(scaledBounds)
|
scaledImg := image.NewNRGBA(scaledBounds)
|
||||||
draw.NearestNeighbor.Scale(scaledImg, scaledBounds, img, b, draw.Src, nil)
|
scaler := draw.NearestNeighbor
|
||||||
|
if highQuality {
|
||||||
|
scaler = draw.CatmullRom
|
||||||
|
}
|
||||||
|
scaler.Scale(scaledImg, scaledBounds, img, b, draw.Src, nil)
|
||||||
return scaledImg
|
return scaledImg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RotateImage90(img *image.NRGBA) (rotated *image.NRGBA) {
|
||||||
|
b := img.Bounds()
|
||||||
|
rotated = image.NewNRGBA(image.Rect(0, 0, b.Max.Y, b.Max.X))
|
||||||
|
for x := b.Min.X; x < b.Max.X; x++ {
|
||||||
|
for y := b.Min.Y; y < b.Max.Y; y++ {
|
||||||
|
col := img.NRGBAAt(x, y)
|
||||||
|
rotated.SetNRGBA(b.Max.Y-y, x, col)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ func pt(p fixed.Point26_6) image.Point {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func RenderText(text string, scale int, texture, bgTex image.Image) *image.NRGBA {
|
func RenderText(text string, scale float64, texture, bgTex image.Image) *image.NRGBA {
|
||||||
face := basicfont.Face7x13
|
face := basicfont.Face7x13
|
||||||
stringBounds, _ := font.BoundString(face, text)
|
stringBounds, _ := font.BoundString(face, text)
|
||||||
|
|
||||||
|
@ -38,5 +38,5 @@ func RenderText(text string, scale int, texture, bgTex image.Image) *image.NRGBA
|
||||||
img.Rect = img.Bounds().Sub(img.Bounds().Min)
|
img.Rect = img.Bounds().Sub(img.Bounds().Min)
|
||||||
|
|
||||||
// scale up, as this font is quite small
|
// scale up, as this font is quite small
|
||||||
return ScaleImage(img, scale)
|
return ScaleImage(img, scale, scale, false)
|
||||||
}
|
}
|
||||||
|
|
93
rpc/repl.go
93
rpc/repl.go
|
@ -28,9 +28,10 @@ const textMode = "txt"
|
||||||
// RunREPL starts reading os.Stdin for commands to apply to the given Fluter
|
// RunREPL starts reading os.Stdin for commands to apply to the given Fluter
|
||||||
func RunREPL(f Fluter) {
|
func RunREPL(f Fluter) {
|
||||||
mode := commandMode
|
mode := commandMode
|
||||||
textSize := 10
|
textSize := 10.0
|
||||||
var textCol image.Image = image.White
|
var textCol image.Image = image.White
|
||||||
var bgCol image.Image = image.Transparent
|
var bgCol image.Image = image.Transparent
|
||||||
|
var taskStore = make(map[string]pixelflut.FlutTask)
|
||||||
|
|
||||||
fmt.Print("[rán] REPL is active. ")
|
fmt.Print("[rán] REPL is active. ")
|
||||||
printHelp()
|
printHelp()
|
||||||
|
@ -66,6 +67,29 @@ func RunREPL(f Fluter) {
|
||||||
case "start":
|
case "start":
|
||||||
t.Paused = false
|
t.Paused = false
|
||||||
|
|
||||||
|
case "toggle", ".":
|
||||||
|
t.Paused = !t.Paused
|
||||||
|
if t.Paused {
|
||||||
|
f.stopTask()
|
||||||
|
printTask = false
|
||||||
|
}
|
||||||
|
|
||||||
|
case "store", "save":
|
||||||
|
printTask = false
|
||||||
|
if len(args) == 0 {
|
||||||
|
fmt.Println("must specify name")
|
||||||
|
} else {
|
||||||
|
taskStore[strings.Join(args, " ")] = t
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
|
||||||
|
case "load", "l":
|
||||||
|
if len(args) == 0 {
|
||||||
|
fmt.Println("must specify name")
|
||||||
|
} else {
|
||||||
|
t = taskStore[strings.Join(args, " ")]
|
||||||
|
}
|
||||||
|
|
||||||
case "offset", "of":
|
case "offset", "of":
|
||||||
if len(args) == 1 && args[0] == "rand" {
|
if len(args) == 1 && args[0] == "rand" {
|
||||||
t.RandOffset = true
|
t.RandOffset = true
|
||||||
|
@ -86,7 +110,7 @@ func RunREPL(f Fluter) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case "address", "a":
|
case "host", "address", "a":
|
||||||
if len(args) == 1 {
|
if len(args) == 1 {
|
||||||
t.Address = args[0]
|
t.Address = args[0]
|
||||||
}
|
}
|
||||||
|
@ -102,7 +126,7 @@ func RunREPL(f Fluter) {
|
||||||
case "txt":
|
case "txt":
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
if size, err := strconv.Atoi(args[0]); err == nil {
|
if size, err := strconv.Atoi(args[0]); err == nil {
|
||||||
textSize = size
|
textSize = float64(size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(args) > 1 {
|
if len(args) > 1 {
|
||||||
|
@ -131,14 +155,51 @@ func RunREPL(f Fluter) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case "scale", "s":
|
||||||
|
quality := true
|
||||||
|
var facX, facY float64
|
||||||
|
var err error
|
||||||
|
if len(args) >= 1 {
|
||||||
|
facX, err = strconv.ParseFloat(args[0], 64)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
facY = facX
|
||||||
|
if len(args) >= 2 {
|
||||||
|
facY, err = strconv.ParseFloat(args[1], 64)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(args) > 2 {
|
||||||
|
quality = false
|
||||||
|
}
|
||||||
|
t.Img = render.ScaleImage(t.Img, facX, facY, quality)
|
||||||
|
}
|
||||||
|
|
||||||
|
case "rotate", "r":
|
||||||
|
t.Img = render.RotateImage90(t.Img)
|
||||||
|
|
||||||
|
// the commands below don't affect the task, so we don't need to apply it to clients -> continue
|
||||||
|
|
||||||
case "metrics":
|
case "metrics":
|
||||||
f.toggleMetrics()
|
f.toggleMetrics()
|
||||||
printTask = false
|
continue
|
||||||
|
|
||||||
|
case "status":
|
||||||
|
fmt.Println(t)
|
||||||
|
continue
|
||||||
|
|
||||||
|
case "help":
|
||||||
|
printHelp()
|
||||||
|
continue
|
||||||
|
|
||||||
default:
|
default:
|
||||||
printTask = false
|
|
||||||
fmt.Print("[rán] unknown command. ")
|
fmt.Print("[rán] unknown command. ")
|
||||||
printHelp()
|
printHelp()
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if printTask {
|
if printTask {
|
||||||
|
@ -151,19 +212,27 @@ func RunREPL(f Fluter) {
|
||||||
|
|
||||||
func printHelp() {
|
func printHelp() {
|
||||||
fmt.Println(`available commands:
|
fmt.Println(`available commands:
|
||||||
|
tasks
|
||||||
start start fluting
|
start start fluting
|
||||||
stop pause fluting
|
stop pause fluting
|
||||||
c <n> set number of connections per client
|
status print current task
|
||||||
a <host>:<port> set target server
|
save <name> store current task
|
||||||
offset <x> <y> set top-left offset
|
load <name> load previously stored task
|
||||||
offset rand random offset for each draw
|
content
|
||||||
metrics toggle bandwidth reporting (may cost some performance)
|
|
||||||
|
|
||||||
i <filepath> set image
|
i <filepath> set image
|
||||||
txt <scale> <color <bgcolor> <txt> send text
|
txt <scale> <color <bgcolor> <txt> send text
|
||||||
txt [<scale> [<color> [<bgcolor>]] enter interactive text mode
|
txt [<scale> [<color> [<bgcolor>]] enter interactive text mode
|
||||||
|
scale <facX> [<facY> [lofi]] scale content
|
||||||
|
rotate rotate content 90°
|
||||||
|
draw modes
|
||||||
|
o set order (l,r,t,b,random)
|
||||||
|
of <x> <y> set top-left offset
|
||||||
|
of rand random offset for each draw
|
||||||
rgbsplit toggle RGB split effect
|
rgbsplit toggle RGB split effect
|
||||||
o set order (l,r,t,b,shuffle)`)
|
networking
|
||||||
|
c <n> set number of connections per client
|
||||||
|
a <host>:<port> set target server
|
||||||
|
metrics toggle bandwidth reporting (may cost some performance)`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to parse as hex-encoded RGB color,
|
// try to parse as hex-encoded RGB color,
|
||||||
|
|
Loading…
Reference in New Issue