android: Re-implement overlay editing
This commit is contained in:
parent
5807cf1b4d
commit
b0a434b99f
|
@ -90,7 +90,6 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
|
|||
binding.doneControlConfig.setOnClickListener { stopConfiguringControls() }
|
||||
|
||||
// Setup overlay.
|
||||
resetInputOverlay()
|
||||
updateShowFpsOverlay()
|
||||
|
||||
binding.inGameMenu.getHeaderView(0).findViewById<TextView>(R.id.text_game_title).text =
|
||||
|
|
|
@ -45,9 +45,15 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
|
|||
private val overlayButtons: MutableSet<InputOverlayDrawableButton> = HashSet()
|
||||
private val overlayDpads: MutableSet<InputOverlayDrawableDpad> = HashSet()
|
||||
private val overlayJoysticks: MutableSet<InputOverlayDrawableJoystick> = HashSet()
|
||||
|
||||
private var inEditMode = false
|
||||
private var buttonBeingConfigured: InputOverlayDrawableButton? = null
|
||||
private var dpadBeingConfigured: InputOverlayDrawableDpad? = null
|
||||
private var joystickBeingConfigured: InputOverlayDrawableJoystick? = null
|
||||
|
||||
private val preferences: SharedPreferences =
|
||||
PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
|
||||
|
||||
private val gyro = FloatArray(3)
|
||||
private val accel = FloatArray(3)
|
||||
private var motionTimestamp: Long = 0
|
||||
|
@ -114,7 +120,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
|
|||
}
|
||||
NativeLibrary.onGamePadButtonEvent(
|
||||
NativeLibrary.Player1Device,
|
||||
button.id,
|
||||
button.buttonId,
|
||||
button.status
|
||||
)
|
||||
shouldUpdateView = true
|
||||
|
@ -224,8 +230,109 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
|
|||
return false
|
||||
}
|
||||
|
||||
private fun onTouchWhileEditing(event: MotionEvent?): Boolean {
|
||||
// TODO: Reimplement this
|
||||
private fun onTouchWhileEditing(event: MotionEvent): Boolean {
|
||||
val pointerIndex = event.actionIndex
|
||||
val fingerPositionX = event.getX(pointerIndex).toInt()
|
||||
val fingerPositionY = event.getY(pointerIndex).toInt()
|
||||
|
||||
// TODO: Provide support for portrait layout
|
||||
//val orientation =
|
||||
// if (resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) "-Portrait" else ""
|
||||
|
||||
for (button in overlayButtons) {
|
||||
// Determine the button state to apply based on the MotionEvent action flag.
|
||||
when (event.action and MotionEvent.ACTION_MASK) {
|
||||
MotionEvent.ACTION_DOWN,
|
||||
MotionEvent.ACTION_POINTER_DOWN ->
|
||||
// If no button is being moved now, remember the currently touched button to move.
|
||||
if (buttonBeingConfigured == null &&
|
||||
button.bounds.contains(
|
||||
fingerPositionX,
|
||||
fingerPositionY
|
||||
)
|
||||
) {
|
||||
buttonBeingConfigured = button
|
||||
buttonBeingConfigured!!.onConfigureTouch(event)
|
||||
}
|
||||
MotionEvent.ACTION_MOVE -> if (buttonBeingConfigured != null) {
|
||||
buttonBeingConfigured!!.onConfigureTouch(event)
|
||||
invalidate()
|
||||
return true
|
||||
}
|
||||
MotionEvent.ACTION_UP,
|
||||
MotionEvent.ACTION_POINTER_UP -> if (buttonBeingConfigured === button) {
|
||||
// Persist button position by saving new place.
|
||||
saveControlPosition(
|
||||
buttonBeingConfigured!!.buttonId,
|
||||
buttonBeingConfigured!!.bounds.centerX(),
|
||||
buttonBeingConfigured!!.bounds.centerY(),
|
||||
""
|
||||
)
|
||||
buttonBeingConfigured = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (dpad in overlayDpads) {
|
||||
// Determine the button state to apply based on the MotionEvent action flag.
|
||||
when (event.action and MotionEvent.ACTION_MASK) {
|
||||
MotionEvent.ACTION_DOWN,
|
||||
MotionEvent.ACTION_POINTER_DOWN ->
|
||||
// If no button is being moved now, remember the currently touched button to move.
|
||||
if (buttonBeingConfigured == null &&
|
||||
dpad.bounds.contains(fingerPositionX, fingerPositionY)
|
||||
) {
|
||||
dpadBeingConfigured = dpad
|
||||
dpadBeingConfigured!!.onConfigureTouch(event)
|
||||
}
|
||||
MotionEvent.ACTION_MOVE -> if (dpadBeingConfigured != null) {
|
||||
dpadBeingConfigured!!.onConfigureTouch(event)
|
||||
invalidate()
|
||||
return true
|
||||
}
|
||||
MotionEvent.ACTION_UP,
|
||||
MotionEvent.ACTION_POINTER_UP -> if (dpadBeingConfigured === dpad) {
|
||||
// Persist button position by saving new place.
|
||||
saveControlPosition(
|
||||
dpadBeingConfigured!!.upId,
|
||||
dpadBeingConfigured!!.bounds.centerX(),
|
||||
dpadBeingConfigured!!.bounds.centerY(),
|
||||
""
|
||||
)
|
||||
dpadBeingConfigured = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (joystick in overlayJoysticks) {
|
||||
when (event.action) {
|
||||
MotionEvent.ACTION_DOWN,
|
||||
MotionEvent.ACTION_POINTER_DOWN -> if (joystickBeingConfigured == null &&
|
||||
joystick.bounds.contains(
|
||||
fingerPositionX,
|
||||
fingerPositionY
|
||||
)
|
||||
) {
|
||||
joystickBeingConfigured = joystick
|
||||
joystickBeingConfigured!!.onConfigureTouch(event)
|
||||
}
|
||||
MotionEvent.ACTION_MOVE -> if (joystickBeingConfigured != null) {
|
||||
joystickBeingConfigured!!.onConfigureTouch(event)
|
||||
invalidate()
|
||||
}
|
||||
MotionEvent.ACTION_UP,
|
||||
MotionEvent.ACTION_POINTER_UP -> if (joystickBeingConfigured != null) {
|
||||
saveControlPosition(
|
||||
joystickBeingConfigured!!.buttonId,
|
||||
joystickBeingConfigured!!.bounds.centerX(),
|
||||
joystickBeingConfigured!!.bounds.centerY(),
|
||||
""
|
||||
)
|
||||
joystickBeingConfigured = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
|
@ -24,32 +24,30 @@ class InputOverlayDrawableButton(
|
|||
res: Resources,
|
||||
defaultStateBitmap: Bitmap,
|
||||
pressedStateBitmap: Bitmap,
|
||||
buttonId: Int
|
||||
val buttonId: Int
|
||||
) {
|
||||
/**
|
||||
* Gets this InputOverlayDrawableButton's button ID.
|
||||
*
|
||||
* @return this InputOverlayDrawableButton's button ID.
|
||||
*/
|
||||
// The ID value what type of button this Drawable represents.
|
||||
val id: Int
|
||||
|
||||
// The ID value what motion event is tracking
|
||||
var trackId: Int
|
||||
|
||||
// The drawable position on the screen
|
||||
private var buttonPositionX = 0
|
||||
private var buttonPositionY = 0
|
||||
|
||||
val width: Int
|
||||
val height: Int
|
||||
|
||||
private val defaultStateBitmap: BitmapDrawable
|
||||
private val pressedStateBitmap: BitmapDrawable
|
||||
private var pressedState = false
|
||||
|
||||
private var previousTouchX = 0
|
||||
private var previousTouchY = 0
|
||||
var controlPositionX = 0
|
||||
var controlPositionY = 0
|
||||
|
||||
init {
|
||||
this.defaultStateBitmap = BitmapDrawable(res, defaultStateBitmap)
|
||||
this.pressedStateBitmap = BitmapDrawable(res, pressedStateBitmap)
|
||||
id = buttonId
|
||||
trackId = -1
|
||||
width = this.defaultStateBitmap.intrinsicWidth
|
||||
height = this.defaultStateBitmap.intrinsicHeight
|
||||
|
@ -104,6 +102,34 @@ class InputOverlayDrawableButton(
|
|||
private val currentStateBitmapDrawable: BitmapDrawable
|
||||
get() = if (pressedState) pressedStateBitmap else defaultStateBitmap
|
||||
|
||||
fun onConfigureTouch(event: MotionEvent): Boolean {
|
||||
val pointerIndex = event.actionIndex
|
||||
val fingerPositionX = event.getX(pointerIndex).toInt()
|
||||
val fingerPositionY = event.getY(pointerIndex).toInt()
|
||||
|
||||
when (event.action) {
|
||||
MotionEvent.ACTION_DOWN -> {
|
||||
previousTouchX = fingerPositionX
|
||||
previousTouchY = fingerPositionY
|
||||
controlPositionX = fingerPositionX - (width / 2)
|
||||
controlPositionY = fingerPositionY - (height / 2)
|
||||
}
|
||||
MotionEvent.ACTION_MOVE -> {
|
||||
controlPositionX += fingerPositionX - previousTouchX
|
||||
controlPositionY += fingerPositionY - previousTouchY
|
||||
setBounds(
|
||||
controlPositionX,
|
||||
controlPositionY,
|
||||
width + controlPositionX,
|
||||
height + controlPositionY
|
||||
)
|
||||
previousTouchX = fingerPositionX
|
||||
previousTouchY = fingerPositionY
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
fun setBounds(left: Int, top: Int, right: Int, bottom: Int) {
|
||||
defaultStateBitmap.setBounds(left, top, right, bottom)
|
||||
pressedStateBitmap.setBounds(left, top, right, bottom)
|
||||
|
@ -111,6 +137,6 @@ class InputOverlayDrawableButton(
|
|||
|
||||
val status: Int
|
||||
get() = if (pressedState) ButtonState.PRESSED else ButtonState.RELEASED
|
||||
private val bounds: Rect
|
||||
val bounds: Rect
|
||||
get() = defaultStateBitmap.bounds
|
||||
}
|
||||
|
|
|
@ -45,13 +45,19 @@ class InputOverlayDrawableDpad(
|
|||
val leftId: Int
|
||||
val rightId: Int
|
||||
var trackId: Int
|
||||
private var controlPositionX = 0
|
||||
private var controlPositionY = 0
|
||||
|
||||
val width: Int
|
||||
val height: Int
|
||||
|
||||
private val defaultStateBitmap: BitmapDrawable
|
||||
private val pressedOneDirectionStateBitmap: BitmapDrawable
|
||||
private val pressedTwoDirectionsStateBitmap: BitmapDrawable
|
||||
|
||||
private var previousTouchX = 0
|
||||
private var previousTouchY = 0
|
||||
private var controlPositionX = 0
|
||||
private var controlPositionY = 0
|
||||
|
||||
private var upButtonState = false
|
||||
private var downButtonState = false
|
||||
private var leftButtonState = false
|
||||
|
@ -215,6 +221,32 @@ class InputOverlayDrawableDpad(
|
|||
val rightStatus: Int
|
||||
get() = if (rightButtonState) ButtonState.PRESSED else ButtonState.RELEASED
|
||||
|
||||
fun onConfigureTouch(event: MotionEvent): Boolean {
|
||||
val pointerIndex = event.actionIndex
|
||||
val fingerPositionX = event.getX(pointerIndex).toInt()
|
||||
val fingerPositionY = event.getY(pointerIndex).toInt()
|
||||
|
||||
when (event.action) {
|
||||
MotionEvent.ACTION_DOWN -> {
|
||||
previousTouchX = fingerPositionX
|
||||
previousTouchY = fingerPositionY
|
||||
}
|
||||
MotionEvent.ACTION_MOVE -> {
|
||||
controlPositionX += fingerPositionX - previousTouchX
|
||||
controlPositionY += fingerPositionY - previousTouchY
|
||||
setBounds(
|
||||
controlPositionX,
|
||||
controlPositionY,
|
||||
width + controlPositionX,
|
||||
height + controlPositionY
|
||||
)
|
||||
previousTouchX = fingerPositionX
|
||||
previousTouchY = fingerPositionY
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
fun setPosition(x: Int, y: Int) {
|
||||
controlPositionX = x
|
||||
controlPositionY = y
|
||||
|
|
|
@ -39,31 +39,39 @@ class InputOverlayDrawableJoystick(
|
|||
val joystickId: Int,
|
||||
val buttonId: Int
|
||||
) {
|
||||
|
||||
// The ID value what motion event is tracking
|
||||
var trackId = -1
|
||||
|
||||
var xAxis = 0f
|
||||
private var yAxis = 0f
|
||||
private var controlPositionX = 0
|
||||
private var controlPositionY = 0
|
||||
|
||||
val width: Int
|
||||
val height: Int
|
||||
|
||||
private var virtBounds: Rect
|
||||
private val origBounds: Rect
|
||||
private var origBounds: Rect
|
||||
|
||||
private val outerBitmap: BitmapDrawable
|
||||
private val defaultStateInnerBitmap: BitmapDrawable
|
||||
private val pressedStateInnerBitmap: BitmapDrawable
|
||||
|
||||
private var previousTouchX = 0
|
||||
private var previousTouchY = 0
|
||||
var controlPositionX = 0
|
||||
var controlPositionY = 0
|
||||
|
||||
private val boundsBoxBitmap: BitmapDrawable
|
||||
|
||||
private var pressedState = false
|
||||
|
||||
// TODO: Add button support
|
||||
val buttonStatus: Int
|
||||
get() =
|
||||
NativeLibrary.ButtonState.RELEASED
|
||||
var bounds: Rect?
|
||||
var bounds: Rect
|
||||
get() = outerBitmap.bounds
|
||||
set(bounds) {
|
||||
outerBitmap.bounds = bounds!!
|
||||
outerBitmap.bounds = bounds
|
||||
}
|
||||
|
||||
// Nintendo joysticks have y axis inverted
|
||||
|
@ -83,7 +91,7 @@ class InputOverlayDrawableJoystick(
|
|||
bounds = rectOuter
|
||||
defaultStateInnerBitmap.bounds = rectInner
|
||||
pressedStateInnerBitmap.bounds = rectInner
|
||||
virtBounds = bounds!!
|
||||
virtBounds = bounds
|
||||
origBounds = outerBitmap.copyBounds()
|
||||
boundsBoxBitmap.alpha = 0
|
||||
boundsBoxBitmap.bounds = virtBounds
|
||||
|
@ -106,8 +114,9 @@ class InputOverlayDrawableJoystick(
|
|||
motionEvent == MotionEvent.ACTION_DOWN || motionEvent == MotionEvent.ACTION_POINTER_DOWN
|
||||
val isActionUp =
|
||||
motionEvent == MotionEvent.ACTION_UP || motionEvent == MotionEvent.ACTION_POINTER_UP
|
||||
|
||||
if (isActionDown) {
|
||||
if (!bounds!!.contains(xPosition, yPosition)) {
|
||||
if (!bounds.contains(xPosition, yPosition)) {
|
||||
return false
|
||||
}
|
||||
pressedState = true
|
||||
|
@ -122,6 +131,7 @@ class InputOverlayDrawableJoystick(
|
|||
boundsBoxBitmap.bounds = virtBounds
|
||||
trackId = pointerId
|
||||
}
|
||||
|
||||
if (isActionUp) {
|
||||
if (trackId != pointerId) {
|
||||
return false
|
||||
|
@ -147,7 +157,9 @@ class InputOverlayDrawableJoystick(
|
|||
trackId = -1
|
||||
return true
|
||||
}
|
||||
|
||||
if (trackId == -1) return false
|
||||
|
||||
for (i in 0 until event.pointerCount) {
|
||||
if (trackId != event.getPointerId(i)) {
|
||||
continue
|
||||
|
@ -179,6 +191,50 @@ class InputOverlayDrawableJoystick(
|
|||
return false
|
||||
}
|
||||
|
||||
fun onConfigureTouch(event: MotionEvent): Boolean {
|
||||
val pointerIndex = event.actionIndex
|
||||
val fingerPositionX = event.getX(pointerIndex).toInt()
|
||||
val fingerPositionY = event.getY(pointerIndex).toInt()
|
||||
|
||||
when (event.action) {
|
||||
MotionEvent.ACTION_DOWN -> {
|
||||
previousTouchX = fingerPositionX
|
||||
previousTouchY = fingerPositionY
|
||||
controlPositionX = fingerPositionX - (width / 2)
|
||||
controlPositionY = fingerPositionY - (height / 2)
|
||||
}
|
||||
MotionEvent.ACTION_MOVE -> {
|
||||
controlPositionX += fingerPositionX - previousTouchX
|
||||
controlPositionY += fingerPositionY - previousTouchY
|
||||
bounds = Rect(
|
||||
controlPositionX,
|
||||
controlPositionY,
|
||||
outerBitmap.intrinsicWidth + controlPositionX,
|
||||
outerBitmap.intrinsicHeight + controlPositionY
|
||||
)
|
||||
virtBounds = Rect(
|
||||
controlPositionX,
|
||||
controlPositionY,
|
||||
outerBitmap.intrinsicWidth + controlPositionX,
|
||||
outerBitmap.intrinsicHeight + controlPositionY
|
||||
)
|
||||
setInnerBounds()
|
||||
bounds = Rect(
|
||||
Rect(
|
||||
controlPositionX,
|
||||
controlPositionY,
|
||||
outerBitmap.intrinsicWidth + controlPositionX,
|
||||
outerBitmap.intrinsicHeight + controlPositionY
|
||||
)
|
||||
)
|
||||
previousTouchX = fingerPositionX
|
||||
previousTouchY = fingerPositionY
|
||||
}
|
||||
}
|
||||
origBounds = outerBitmap.copyBounds()
|
||||
return true
|
||||
}
|
||||
|
||||
private fun setInnerBounds() {
|
||||
var x = virtBounds.centerX() + (xAxis * (virtBounds.width() / 2)).toInt()
|
||||
var y = virtBounds.centerY() + (yAxis * (virtBounds.height() / 2)).toInt()
|
||||
|
|
Reference in New Issue