diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/ui/AdvancedMappingControlViewHolder.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/ui/AdvancedMappingControlViewHolder.kt index 80771a6f4b..017bc1e642 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/ui/AdvancedMappingControlViewHolder.kt +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/ui/AdvancedMappingControlViewHolder.kt @@ -2,13 +2,15 @@ package org.dolphinemu.dolphinemu.features.input.ui +import android.view.View import androidx.lifecycle.Lifecycle import org.dolphinemu.dolphinemu.databinding.ListItemAdvancedMappingControlBinding import org.dolphinemu.dolphinemu.features.input.model.ControllerInterface import org.dolphinemu.dolphinemu.features.input.model.CoreDevice import org.dolphinemu.dolphinemu.utils.LifecycleViewHolder -import org.dolphinemu.dolphinemu.utils.Log +import java.text.DecimalFormat import java.util.function.Consumer +import kotlin.math.abs class AdvancedMappingControlViewHolder( private val binding: ListItemAdvancedMappingControlBinding, @@ -19,12 +21,16 @@ class AdvancedMappingControlViewHolder( private lateinit var control: CoreDevice.Control + private var previousState = Float.POSITIVE_INFINITY + init { binding.root.setOnClickListener { onClickCallback.accept(control.getName()) } if (isInput) { ControllerInterface.inputStateChanged.observe(this) { updateInputValue() } + } else { + binding.layoutState.visibility = View.GONE } } @@ -41,8 +47,23 @@ class AdvancedMappingControlViewHolder( throw IllegalStateException("AdvancedMappingControlViewHolder leak") } - // TODO - Log.info("AdvancedMappingControlViewHolder: Value of " + control.getName() + " is " + - control.getState()) + var state = control.getState().toFloat() + if (abs(state - previousState) >= stateUpdateThreshold) { + previousState = state + + // Don't print a minus sign for signed zeroes + if (state == -0.0f) + state = 0.0f + + binding.textState.setText(stateFormat.format(state)) + binding.controlStateBar.state = state + } + } + + companion object { + private val stateFormat = DecimalFormat("#.####") + + // For performance, require state to change by a certain threshold before we update the UI + private val stateUpdateThreshold = 0.00005f } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/ui/ControlStateBarHorizontal.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/ui/ControlStateBarHorizontal.kt new file mode 100644 index 0000000000..a7a02921e8 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/ui/ControlStateBarHorizontal.kt @@ -0,0 +1,25 @@ +package org.dolphinemu.dolphinemu.features.input.ui + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.LinearLayout +import org.dolphinemu.dolphinemu.databinding.ViewControlStateBarHorizontalBinding + +class ControlStateBarHorizontal @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : LinearLayout(context, attrs, defStyleAttr) { + + private val binding = + ViewControlStateBarHorizontalBinding.inflate(LayoutInflater.from(context), this) + + private val impl = ControlStateBarImpl(binding.viewFilled, binding.viewUnfilled) + + var state: Float + get() = impl.state + set(value) { + impl.state = value + } +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/ui/ControlStateBarImpl.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/ui/ControlStateBarImpl.kt new file mode 100644 index 0000000000..027448b0e3 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/ui/ControlStateBarImpl.kt @@ -0,0 +1,28 @@ +package org.dolphinemu.dolphinemu.features.input.ui + +import android.view.View +import android.widget.LinearLayout +import androidx.core.math.MathUtils + +class ControlStateBarImpl(private val filledView: View, private val unfilledView: View) { + private var _state = 0.0f + + var state: Float + get() = _state + set(value) { + val clampedState = MathUtils.clamp(value, 0.0f, 1.0f) + if (clampedState != _state) { + setLinearLayoutWeight(filledView, clampedState) + setLinearLayoutWeight(unfilledView, 1.0f - clampedState) + } + _state = clampedState + } + + companion object { + private fun setLinearLayoutWeight(view: View, weight: Float) { + val layoutParams = view.layoutParams as LinearLayout.LayoutParams + layoutParams.weight = weight + view.layoutParams = layoutParams + } + } +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/ui/ControlStateBarVertical.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/ui/ControlStateBarVertical.kt new file mode 100644 index 0000000000..cb7c37ad70 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/ui/ControlStateBarVertical.kt @@ -0,0 +1,30 @@ +package org.dolphinemu.dolphinemu.features.input.ui + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.LinearLayout +import org.dolphinemu.dolphinemu.databinding.ViewControlStateBarVerticalBinding + +class ControlStateBarVertical @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : LinearLayout(context, attrs, defStyleAttr) { + + init { + // Setting this in the XML file has no effect for some reason + orientation = VERTICAL + } + + private val binding = + ViewControlStateBarVerticalBinding.inflate(LayoutInflater.from(context), this) + + private val impl = ControlStateBarImpl(binding.viewFilled, binding.viewUnfilled) + + var state: Float + get() = impl.state + set(value) { + impl.state = value + } +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/ui/viewholder/InputMappingControlSettingViewHolder.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/ui/viewholder/InputMappingControlSettingViewHolder.kt index b6b30da53d..312fc9f6a5 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/ui/viewholder/InputMappingControlSettingViewHolder.kt +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/ui/viewholder/InputMappingControlSettingViewHolder.kt @@ -10,14 +10,17 @@ import org.dolphinemu.dolphinemu.features.input.model.view.InputMappingControlSe import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter import org.dolphinemu.dolphinemu.features.settings.ui.viewholder.SettingViewHolder -import org.dolphinemu.dolphinemu.utils.Log +import kotlin.math.abs class InputMappingControlSettingViewHolder( private val binding: ListItemMappingBinding, adapter: SettingsAdapter ) : SettingViewHolder(binding.getRoot(), adapter) { + lateinit var setting: InputMappingControlSetting + private var previousState = Float.POSITIVE_INFINITY + init { ControllerInterface.inputStateChanged.observe(this) { updateInputValue() @@ -34,6 +37,10 @@ class InputMappingControlSettingViewHolder( binding.textSettingDescription.text = setting.value binding.buttonAdvancedSettings.setOnClickListener { clicked: View -> onLongClick(clicked) } + if (!setting.isInput) { + binding.controlStateBar.visibility = View.INVISIBLE + } + setStyle(binding.textSettingName, setting) updateInputValue() } @@ -69,9 +76,16 @@ class InputMappingControlSettingViewHolder( } if (setting.isInput) { - // TODO - Log.info("InputMappingControlSettingViewHolder: Value of " + setting.name + " is " + - setting.state) + val state = setting.state.toFloat() + if (abs(state - previousState) >= stateUpdateThreshold) { + previousState = state + binding.controlStateBar.state = state + } } } + + companion object { + // For performance, require state to change by a certain threshold before we update the UI + private val stateUpdateThreshold = 0.01f + } } diff --git a/Source/Android/app/src/main/res/layout-ldrtl/list_item_mapping.xml b/Source/Android/app/src/main/res/layout-ldrtl/list_item_mapping.xml index 94f219b4c1..e1a2118b36 100644 --- a/Source/Android/app/src/main/res/layout-ldrtl/list_item_mapping.xml +++ b/Source/Android/app/src/main/res/layout-ldrtl/list_item_mapping.xml @@ -22,7 +22,7 @@ android:layout_marginTop="@dimen/spacing_large" android:textSize="16sp" android:textAlignment="viewStart" - android:layout_toStartOf="@+id/button_advanced_settings" + android:layout_toStartOf="@id/control_state_bar" tools:text="Setting Name" /> + +