Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[life]: add modifier click as alternative to get other 1/2 pixel; -nomouse flag. also only track movements/drag after a click #65

Merged
merged 3 commits into from
Oct 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 28 additions & 7 deletions ansipixels/mouse.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,23 +62,44 @@ func (ap *AnsiPixels) MouseDecode() {
}

const (
MouseLeft = 0
MouseRight = 0b10
MouseMove = 0b100000
MouseLeft = 0b00
MouseRight = 0b10
MouseMove = 0b100000
Shift = 0b000100
Alt = 0b001000
Ctrl = 0b010000
AllModifiers = Shift | Alt | Ctrl
AnyModifierMask = ^AllModifiers
)

func (ap *AnsiPixels) AltMod() bool {
return ap.Mbuttons&Alt != 0
}

func (ap *AnsiPixels) ShiftMod() bool {
return ap.Mbuttons&Alt != 0
}

func (ap *AnsiPixels) CtrlMod() bool {
return ap.Mbuttons&Alt != 0
}

func (ap *AnsiPixels) AnyModifier() bool {
return ap.Mbuttons&AllModifiers != 0
}

func (ap *AnsiPixels) LeftClick() bool {
return ap.Mouse && (ap.Mbuttons == MouseLeft)
return ap.Mouse && ((ap.Mbuttons & AnyModifierMask) == MouseLeft)
}

func (ap *AnsiPixels) RightClick() bool {
return ap.Mouse && (ap.Mbuttons == MouseRight)
return ap.Mouse && ((ap.Mbuttons & AnyModifierMask) == MouseRight)
}

func (ap *AnsiPixels) LeftDrag() bool {
return ap.Mouse && (ap.Mbuttons == MouseMove|MouseLeft)
return ap.Mouse && ((ap.Mbuttons & AnyModifierMask) == MouseMove|MouseLeft)
}

func (ap *AnsiPixels) RightDrag() bool {
return ap.Mouse && (ap.Mbuttons == MouseMove|MouseRight)
return ap.Mouse && ((ap.Mbuttons & AnyModifierMask) == MouseMove|MouseRight)
}
39 changes: 32 additions & 7 deletions life/life.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,14 +150,17 @@ type Game struct {
lastClickX, lastClickY int
delta int // which 1/2 pixel we're targeting with the mouse.
lastWasClick bool
lastWasAlt bool
hasMouse bool
}

func Main() int {
fpsFlag := flag.Float64("fps", 60, "Frames per second")
flagRandomFill := flag.Float64("fill", 0.1, "Random fill factor (0 to 1)")
flagGlider := flag.Bool("glider", false, "Start with a glider (default is random)")
noMouseFlag := flag.Bool("nomouse", false, "Disable mouse tracking")
cli.Main()
game := &Game{}
game := &Game{hasMouse: !*noMouseFlag}
ap := ansipixels.NewAnsiPixels(*fpsFlag)
err := ap.Open()
if err != nil {
Expand All @@ -166,7 +169,9 @@ func Main() int {
game.ap = ap
defer game.End()
ap.HideCursor()
ap.MouseTrackingOn() // needed for drag, other ap.MouseClickOn() is enough.
if game.hasMouse {
ap.MouseClickOn() // start with just clicks, we turn on drag after a click.
}
fillFactor := float32(*flagRandomFill)
ap.OnResize = func() error {
game.c = NewConway(ap.W, 2*ap.H) // half pixels vertically.
Expand Down Expand Up @@ -232,8 +237,13 @@ func (g *Game) DrawOne() {
}
Draw(g.ap, g.c)
if g.showHelp {
g.ap.WriteBoxed(g.ap.H/2+2, "Space to pause, q to quit, i for info, other key to run\n"+
"Left click or hold to set, right click to clear\nClick in same spot for other half pixel")
helpText := "Space to pause, q to quit, i for info, other key to run\n"
if g.hasMouse {
helpText += "Left click or hold to set, right click to clear\nHold a modifier or click in same spot for other half pixel"
} else {
helpText += "Mouse support disabled, run without -nomouse for mouse support"
}
g.ap.WriteBoxed(g.ap.H/2+2, "%s", helpText)
g.showHelp = false
}
g.ap.EndSyncMode()
Expand All @@ -246,7 +256,8 @@ func (g *Game) Next() {
}

func (g *Game) End() {
g.ap.MouseTrackingOff() // g.ap.MouseClickOff()
g.ap.MouseTrackingOff()
g.ap.MouseClickOff()
g.ap.ShowCursor()
g.ap.MoveCursor(0, g.ap.H-2)
g.ap.Restore()
Expand All @@ -266,23 +277,37 @@ func (g *Game) HandleMouse() {
delta = g.delta
}
g.lastWasClick = false
modifier := g.ap.AnyModifier()
if modifier {
delta = 1
g.lastWasAlt = true
} else {
if g.lastWasAlt {
delta = 0
}
g.lastWasAlt = false
}
switch {
case g.ap.LeftClick(), ld:
log.LogVf("Mouse left (%06b) click (drag %t) at %d, %d", g.ap.Mbuttons, ld, g.ap.Mx, g.ap.My)
log.LogVf("Mouse left (%06b) alt %t click (drag %t) at %d, %d", g.ap.Mbuttons, modifier, ld, g.ap.Mx, g.ap.My)
g.c.SetCurrent(g.ap.Mx-1, (g.ap.My-1)*2+delta)
g.lastWasClick = true
g.ap.MouseTrackingOn() // needed for drag, other ap.MouseClickOn() is enough.
if ld {
g.DrawOne()
return
}
case g.ap.RightClick():
log.LogVf("Mouse right (%06b) click (drag %t) at %d, %d", g.ap.Mbuttons, leftDrag, g.ap.Mx, g.ap.My)
log.LogVf("Mouse right (%06b) alt %t click (drag %t) at %d, %d", g.ap.Mbuttons, modifier, leftDrag, g.ap.Mx, g.ap.My)
g.c.ClearCurrent(g.ap.Mx-1, (g.ap.My-1)*2+delta)
g.lastWasClick = true
default:
log.LogVf("Mouse %06b at %d, %d last was click %t same spot %t left drag %t",
g.ap.Mbuttons, g.ap.Mx, g.ap.My,
prevWasClick, sameSpot, leftDrag)
if prevWasClick {
g.ap.MouseClickOn() // turns off drag and back to just clicks.
}
return
}
if sameSpot {
Expand Down
Loading