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

Fixes a number of Pointer related issues #774

Merged
merged 17 commits into from
Nov 8, 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
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,9 @@ object ConfigGen {
| magnification = 1,
| transparentBackground = false,
| resizePolicy = ResizePolicy.Resize,
| advanced = AdvancedGameConfig(
| renderingTechnology = RenderingTechnology.WebGL2WithFallback,
| antiAliasing = ${indigoOptions.metadata.antiAliasing.toString},
| premultipliedAlpha = true,
| batchSize = 256,
| autoLoadStandardShaders = true,
| disableContextMenu = true
| )
| advanced = AdvancedGameConfig
| .default
| .withAntiAliasing(${indigoOptions.metadata.antiAliasing.toString})
| )
|""".stripMargin

Expand Down
44 changes: 22 additions & 22 deletions indigo/indigo-extras/src/main/scala/indigoextras/ui/Button.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import indigo.shared.datatypes.Point
import indigo.shared.datatypes.Rectangle
import indigo.shared.datatypes.Size
import indigo.shared.events.GlobalEvent
import indigo.shared.input.Mouse
import indigo.shared.input.PointerState
import indigo.shared.scenegraph.EntityNode
import indigo.shared.scenegraph.Graphic
import indigo.shared.scenegraph.Group
Expand Down Expand Up @@ -51,52 +51,52 @@ final case class Button(
def withDepth(newDepth: Depth): Button =
this.copy(depth = newDepth)

def update(mouse: Mouse): Outcome[Button] = {
val mouseInBounds = bounds.isPointWithin(mouse.position)
def update(pointer: PointerState): Outcome[Button] = {
val pointerInBounds = pointer.positions.exists(p => bounds.isPointWithin(p))

val upEvents: Batch[GlobalEvent] =
if mouseInBounds && mouse.mouseReleased then onUp()
if pointerInBounds && pointer.released then onUp()
else Batch.empty

val clickEvents: Batch[GlobalEvent] =
if mouseInBounds && mouse.mouseClicked then onClick()
if pointerInBounds && pointer.isClicked then onClick()
else Batch.empty

val downEvents: Batch[GlobalEvent] =
if mouseInBounds && mouse.mousePressed then onDown()
if pointerInBounds && pointer.pressed then onDown()
else Batch.empty

val mouseButtonEvents: Batch[GlobalEvent] =
val pointerButtonEvents: Batch[GlobalEvent] =
downEvents ++ upEvents ++ clickEvents

state match
// Stay in Down state
case ButtonState.Down if mouseInBounds && mouse.isLeftDown =>
Outcome(this).addGlobalEvents(onHoldDown() ++ mouseButtonEvents)
case ButtonState.Down if pointerInBounds && pointer.isLeftDown =>
Outcome(this).addGlobalEvents(onHoldDown() ++ pointerButtonEvents)

// Move to Down state
case ButtonState.Up if mouseInBounds && mouse.mousePressed =>
Outcome(toDownState).addGlobalEvents(onHoverOver() ++ mouseButtonEvents)
case ButtonState.Up if pointerInBounds && pointer.pressed =>
Outcome(toDownState).addGlobalEvents(onHoverOver() ++ pointerButtonEvents)

case ButtonState.Over if mouseInBounds && mouse.mousePressed =>
Outcome(toDownState).addGlobalEvents(mouseButtonEvents)
case ButtonState.Over if pointerInBounds && pointer.pressed =>
Outcome(toDownState).addGlobalEvents(pointerButtonEvents)

// Out of Down state
case ButtonState.Down if mouseInBounds && !mouse.isLeftDown =>
Outcome(toOverState).addGlobalEvents(onHoverOver() ++ mouseButtonEvents)
case ButtonState.Down if pointerInBounds && !pointer.isLeftDown =>
Outcome(toOverState).addGlobalEvents(onHoverOver() ++ pointerButtonEvents)

case ButtonState.Down if !mouseInBounds && !mouse.isLeftDown =>
Outcome(toUpState).addGlobalEvents(onHoverOut() ++ mouseButtonEvents)
case ButtonState.Down if !pointerInBounds && !pointer.isLeftDown =>
Outcome(toUpState).addGlobalEvents(onHoverOut() ++ pointerButtonEvents)

//
case ButtonState.Up if mouseInBounds =>
Outcome(toOverState).addGlobalEvents(onHoverOver() ++ mouseButtonEvents)
case ButtonState.Up if pointerInBounds =>
Outcome(toOverState).addGlobalEvents(onHoverOver() ++ pointerButtonEvents)

case ButtonState.Over if !mouseInBounds =>
Outcome(toUpState).addGlobalEvents(onHoverOut() ++ mouseButtonEvents)
case ButtonState.Over if !pointerInBounds =>
Outcome(toUpState).addGlobalEvents(onHoverOut() ++ pointerButtonEvents)

case _ =>
Outcome(this).addGlobalEvents(mouseButtonEvents)
Outcome(this).addGlobalEvents(pointerButtonEvents)
}

private def applyPositionAndDepth(sceneNode: SceneNode, pt: Point, d: Depth): SceneNode =
Expand Down
36 changes: 18 additions & 18 deletions indigo/indigo-extras/src/main/scala/indigoextras/ui/HitArea.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import indigo.shared.datatypes.Rectangle
import indigo.shared.events.GlobalEvent
import indigo.shared.geometry.Polygon
import indigo.shared.geometry.Vertex
import indigo.shared.input.Mouse
import indigo.shared.input.PointerState

final case class HitArea(
area: Polygon.Closed,
Expand All @@ -20,42 +20,42 @@ final case class HitArea(
onHoldDown: () => Batch[GlobalEvent]
) derives CanEqual:

def update(mouse: Mouse): Outcome[HitArea] = {
val mouseInBounds = area.contains(Vertex.fromPoint(mouse.position))
def update(pointer: PointerState): Outcome[HitArea] = {
val pointerInBounds = pointer.positions.exists(p => area.contains(Vertex.fromPoint(p)))

val upEvents: Batch[GlobalEvent] =
if mouseInBounds && mouse.mouseReleased then onUp()
if pointerInBounds && pointer.released then onUp()
else Batch.empty

val clickEvents: Batch[GlobalEvent] =
if mouseInBounds && mouse.mouseClicked then onClick()
if pointerInBounds && pointer.isClicked then onClick()
else Batch.empty

val downEvents: Batch[GlobalEvent] =
if mouseInBounds && mouse.mousePressed then onDown()
if pointerInBounds && pointer.pressed then onDown()
else Batch.empty

val mouseButtonEvents: Batch[GlobalEvent] =
val pointerButtonEvents: Batch[GlobalEvent] =
downEvents ++ upEvents ++ clickEvents

state match
case ButtonState.Down if mouseInBounds && mouse.isLeftDown =>
Outcome(this).addGlobalEvents(onHoldDown() ++ mouseButtonEvents)
case ButtonState.Down if pointerInBounds && pointer.isLeftDown =>
Outcome(this).addGlobalEvents(onHoldDown() ++ pointerButtonEvents)

case ButtonState.Up if mouseInBounds =>
Outcome(toOverState).addGlobalEvents(onHoverOver() ++ mouseButtonEvents)
case ButtonState.Up if pointerInBounds =>
Outcome(toOverState).addGlobalEvents(onHoverOver() ++ pointerButtonEvents)

case ButtonState.Over if mouseInBounds && mouse.mousePressed =>
Outcome(toDownState).addGlobalEvents(mouseButtonEvents)
case ButtonState.Over if pointerInBounds && pointer.pressed =>
Outcome(toDownState).addGlobalEvents(pointerButtonEvents)

case ButtonState.Down if mouseInBounds && !mouse.isLeftDown =>
Outcome(toOverState).addGlobalEvents(onHoverOver() ++ mouseButtonEvents)
case ButtonState.Down if pointerInBounds && !pointer.isLeftDown =>
Outcome(toOverState).addGlobalEvents(onHoverOver() ++ pointerButtonEvents)

case ButtonState.Over if !mouseInBounds =>
Outcome(toUpState).addGlobalEvents(onHoverOut() ++ mouseButtonEvents)
case ButtonState.Over if !pointerInBounds =>
Outcome(toUpState).addGlobalEvents(onHoverOut() ++ pointerButtonEvents)

case _ =>
Outcome(this).addGlobalEvents(mouseButtonEvents)
Outcome(this).addGlobalEvents(pointerButtonEvents)
}

def withUpActions(actions: GlobalEvent*): HitArea =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import indigo.shared.collections.Batch
import indigo.shared.constants.Key
import indigo.shared.datatypes._
import indigo.shared.events.GlobalEvent
import indigo.shared.events.MouseButton
import indigo.shared.scenegraph.Graphic
import indigo.shared.scenegraph.SceneNode
import indigo.shared.scenegraph.Text
Expand Down Expand Up @@ -217,10 +218,11 @@ final case class InputField(
rec(frameContext.inputState.keyboard.keysReleased.toList, this, false, None)
else Outcome(this)

if (frameContext.inputState.mouse.mouseReleased)
if (frameContext.inputState.pointers.isReleased)
bounds(frameContext.boundaryLocator) match
case Some(bounds) =>
if frameContext.inputState.mouse.wasMouseUpWithin(bounds) then updated.flatMap(_.giveFocus)
if frameContext.inputState.pointers.wasUpWithin(bounds, MouseButton.LeftMouseButton) then
updated.flatMap(_.giveFocus)
else updated.flatMap(_.loseFocus)
case _ =>
updated
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import indigo.shared.datatypes.Depth
import indigo.shared.datatypes.Point
import indigo.shared.datatypes.Rectangle
import indigo.shared.events.GlobalEvent
import indigo.shared.input.Mouse
import indigo.shared.input.PointerState
import indigo.shared.scenegraph.EntityNode
import indigo.shared.scenegraph.Graphic
import indigo.shared.scenegraph.Group
Expand Down Expand Up @@ -318,33 +318,35 @@ final case class RadioButtonGroup(
rec(radioButtons, false, Nil)
}

/** Update all the option buttons according to the newest state of mouse input.
/** Update all the option buttons according to the newest state of pointer input.
*
* @param mouse
* The current mouse state
* @param pointer
* The current pointer state
* @return
* An Outcome[RadioButtonGroup] with this radio button's new state
*/
def update(mouse: Mouse): Outcome[RadioButtonGroup] = {
def update(pointer: PointerState): Outcome[RadioButtonGroup] = {
val indexedOptions = options.zipWithIndex

val selected: Option[Int] =
indexedOptions.flatMap {
case (o, i)
if mouse.isLeftDown && o.hitArea.getOrElse(hitArea).moveBy(o.position).isPointWithin(mouse.position) =>
Batch(i)
pointer.maybePosition.flatMap(pointerPos =>
indexedOptions.flatMap {
case (o, i)
if pointer.isLeftDown && o.hitArea.getOrElse(hitArea).moveBy(o.position).isPointWithin(pointerPos) =>
Batch(i)

case _ =>
Batch.empty
}.headOption
case _ =>
Batch.empty
}.headOption
)

val updatedOptions: Batch[Outcome[RadioButton]] =
indexedOptions.map {
// Selected already
case (o, _) if o.inSelectedState && selected.isEmpty =>
Outcome(o)

// Selected already after some mouse selection
// Selected already after some pointer selection
case (o, i) if o.inSelectedState && selected.isDefined && selected.contains(i) =>
Outcome(o)

Expand All @@ -356,15 +358,15 @@ final case class RadioButtonGroup(
case (o, i) if o.inSelectedState && selected.isDefined && !selected.contains(i) =>
Outcome(o.copy(state = RadioButtonState.Normal), o.onUnselected())

// Not selected, no mouse click, mouse within, should be in hover state.
// Not selected, no pointer click, pointer within, should be in hover state.
case (o, _)
if !o.inSelectedState && !mouse.isLeftDown && o.hitArea
if pointer.maybePosition != None && !o.inSelectedState && !pointer.isLeftDown && o.hitArea
.getOrElse(hitArea)
.moveBy(o.position)
.isPointWithin(mouse.position) =>
.isPointWithin(pointer.position) =>
Outcome(o.copy(state = RadioButtonState.Hover), o.onHoverOver())

// Hovered, but mouse outside so revert to normal
// Hovered, but pointer outside so revert to normal
case (o, _) if o.inHoverState =>
Outcome(o.copy(state = RadioButtonState.Normal), o.onHoverOut())

Expand Down
Loading
Loading