mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2025-07-19 19:13:03 +00:00
improve virtual controller:
* add digital 8-Way pad * add on screen element size and position configuration * begin with cleanup
This commit is contained in:
parent
4c533fedfd
commit
f23bb9fac1
12
app/app.iml
12
app/app.iml
@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<module external.linked.project.id=":app" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="limelight-android" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
|
<module external.linked.project.id=":app" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="moonlight-new" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
|
||||||
<component name="FacetManager">
|
<component name="FacetManager">
|
||||||
<facet type="android-gradle" name="Android-Gradle">
|
<facet type="android-gradle" name="Android-Gradle">
|
||||||
<configuration>
|
<configuration>
|
||||||
@ -85,24 +85,18 @@
|
|||||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/coverage-instrumented-classes" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex-cache" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jacoco" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/javaResources" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/libs" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/ndk" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/ndk" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/nonRootDebug" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/proguard" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/tmp" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
|
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
|
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
|
||||||
</content>
|
</content>
|
||||||
|
@ -76,18 +76,7 @@
|
|||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value="com.limelight.AppView" />
|
android:value="com.limelight.AppView" />
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
|
||||||
android:name=".binding.input.virtual_controller.VirtualControllerConfiguration"
|
|
||||||
android:screenOrientation="landscape"
|
|
||||||
android:theme="@style/StreamTheme"
|
|
||||||
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection" >
|
|
||||||
</activity>
|
|
||||||
<activity
|
|
||||||
android:name=".binding.input.virtual_controller.VirtualControllerSettings"
|
|
||||||
android:screenOrientation="landscape"
|
|
||||||
android:theme="@android:style/Theme.Holo.Dialog"
|
|
||||||
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection" >
|
|
||||||
</activity>
|
|
||||||
<service
|
<service
|
||||||
android:name=".discovery.DiscoveryService"
|
android:name=".discovery.DiscoveryService"
|
||||||
android:label="mDNS PC Auto-Discovery Service" />
|
android:label="mDNS PC Auto-Discovery Service" />
|
||||||
|
@ -287,9 +287,11 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
evdevHandler.start();
|
evdevHandler.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prefConfig.virtualController_enable)
|
if (prefConfig.virtualController_enable) {
|
||||||
{
|
// create virtual onscreen controller
|
||||||
virtualController = new VirtualController(conn, (FrameLayout) findViewById(R.id.surfaceView).getParent(), getApplicationContext());
|
virtualController = new VirtualController(conn,
|
||||||
|
(FrameLayout)findViewById(R.id.surfaceView).getParent(),
|
||||||
|
this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prefConfig.usbDriver) {
|
if (prefConfig.usbDriver) {
|
||||||
@ -315,6 +317,11 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
|
|
||||||
// Apply the size change
|
// Apply the size change
|
||||||
sv.setLayoutParams(lp);
|
sv.setLayoutParams(lp);
|
||||||
|
|
||||||
|
// refresh virtual controller layout
|
||||||
|
if (virtualController != null) {
|
||||||
|
virtualController.refreshLayout();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkDataConnection()
|
private void checkDataConnection()
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
/**
|
||||||
|
* Created by Karim Mreisi.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.limelight.binding.input.virtual_controller;
|
package com.limelight.binding.input.virtual_controller;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@ -10,88 +14,199 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Karim Mreisi on 30.11.2014.
|
* This is a analog stick on screen element. It is used to get 2-Axis user input.
|
||||||
*/
|
*/
|
||||||
public class AnalogStick extends VirtualControllerElement
|
public class AnalogStick extends VirtualControllerElement {
|
||||||
{
|
|
||||||
float radius_complete = 0;
|
|
||||||
float radius_minimum = 0;
|
|
||||||
float radius_dead_zone = 0;
|
|
||||||
float radius_analog_stick = 0;
|
|
||||||
|
|
||||||
float position_pressed_x = 0;
|
/** outer radius size in percent of the ui element */
|
||||||
float position_pressed_y = 0;
|
public static final int SIZE_RADIUS_COMPLETE = 90;
|
||||||
|
/** analog stick size in percent of the ui element */
|
||||||
|
public static final int SIZE_RADIUS_ANALOG_STICK = 90;
|
||||||
|
/** dead zone size in percent of the ui element */
|
||||||
|
public static final int SIZE_RADIUS_DEADZONE = 90;
|
||||||
|
/** time frame for a double click */
|
||||||
|
public final static long timeoutDoubleClick = 250;
|
||||||
|
|
||||||
float position_moved_x = 0;
|
/**
|
||||||
float position_moved_y = 0;
|
* Listener interface to update registered observers.
|
||||||
|
*/
|
||||||
|
public interface AnalogStickListener {
|
||||||
|
|
||||||
float position_stick_x = 0;
|
/**
|
||||||
float position_stick_y = 0;
|
* onMovement event will be fired on real analog stick movement (outside of the deadzone).
|
||||||
|
* @param x horizontal position, value from -1.0 ... 0 .. 1.0
|
||||||
|
* @param y vertical position, value from -1.0 ... 0 .. 1.0
|
||||||
|
*/
|
||||||
|
void onMovement(float x, float y);
|
||||||
|
|
||||||
Paint paint = new Paint();
|
/**
|
||||||
|
* onClick event will be fired on click on the analog stick
|
||||||
|
*/
|
||||||
|
void onClick();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* onDoubleClick event will be fired on a double click in a short time frame on the analog
|
||||||
|
* stick.
|
||||||
|
*/
|
||||||
|
void onDoubleClick();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* onRevoke event will be fired on unpress of the analog stick.
|
||||||
|
*/
|
||||||
|
void onRevoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Movement states of the analog sick.
|
||||||
|
*/
|
||||||
|
private enum STICK_STATE {
|
||||||
|
NO_MOVEMENT,
|
||||||
|
MOVED_IN_DEAD_ZONE,
|
||||||
|
MOVED_ACTIVE
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Click type states.
|
||||||
|
*/
|
||||||
|
private enum CLICK_STATE {
|
||||||
|
SINGLE,
|
||||||
|
DOUBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
/** configuration if the analog stick should be displayed as circle or square*/
|
||||||
|
private boolean circle_stick = true; // TODO: implement square sick for simulations
|
||||||
|
|
||||||
|
/** outer radius, this size will be automatically updated on resize */
|
||||||
|
private float radius_complete = 0;
|
||||||
|
/** analog stick radius, this size will be automatically updated on resize */
|
||||||
|
private float radius_analog_stick = 0;
|
||||||
|
/** dead zone radius, this size will be automatically updated on resize */
|
||||||
|
private float radius_dead_zone = 0;
|
||||||
|
|
||||||
|
/** horizontal position in relation to the center of the element */
|
||||||
|
private float relative_x = 0;
|
||||||
|
/** vertical position in relation to the center of the element */
|
||||||
|
private float relative_y = 0;
|
||||||
|
|
||||||
|
|
||||||
_STICK_STATE stick_state = _STICK_STATE.NO_MOVEMENT;
|
private double movement_radius = 0;
|
||||||
_CLICK_STATE click_state = _CLICK_STATE.SINGLE;
|
private double movement_angle = 0;
|
||||||
|
|
||||||
List<AnalogStickListener> listeners = new ArrayList<>();
|
private float position_stick_x = 0;
|
||||||
OnTouchListener onTouchListener = null;
|
private float position_stick_y = 0;
|
||||||
private long timeoutDoubleClick = 250;
|
|
||||||
|
private Paint paint = new Paint();
|
||||||
|
|
||||||
|
private STICK_STATE stick_state = STICK_STATE.NO_MOVEMENT;
|
||||||
|
private CLICK_STATE click_state = CLICK_STATE.SINGLE;
|
||||||
|
|
||||||
|
private List<AnalogStickListener> listeners = new ArrayList<>();
|
||||||
private long timeLastClick = 0;
|
private long timeLastClick = 0;
|
||||||
|
|
||||||
public AnalogStick(Context context)
|
private static double getMovementRadius(float x, float y) {
|
||||||
{
|
// corner cases
|
||||||
super(context);
|
if (x == 0) {
|
||||||
|
return y > 0 ? y : -y;
|
||||||
|
}
|
||||||
|
if (y == 0) {
|
||||||
|
return x > 0 ? x : -x;
|
||||||
|
}
|
||||||
|
// return hypotenuse (pythagoras)
|
||||||
|
return Math.sqrt(x * x + y * y);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getAngle(float way_x, float way_y) {
|
||||||
|
double angle = 0;
|
||||||
|
// prevent divisions by zero for corner cases
|
||||||
|
if (way_x == 0) {
|
||||||
|
return way_y < 0 ? Math.PI : 0;
|
||||||
|
} else if (way_y == 0) {
|
||||||
|
if (way_x > 0) {
|
||||||
|
return Math.PI * 3 / 2;
|
||||||
|
} else if (way_x < 0) {
|
||||||
|
return Math.PI * 1 / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// return correct calculated angle for each quadrant
|
||||||
|
if (way_x > 0) {
|
||||||
|
if (way_y < 0) {
|
||||||
|
// first quadrant
|
||||||
|
return 3 * Math.PI / 2 + Math.atan((double) (-way_y / way_x));
|
||||||
|
} else {
|
||||||
|
// second quadrant
|
||||||
|
return Math.PI + Math.atan((double) (way_x / way_y));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (way_y > 0) {
|
||||||
|
// third quadrant
|
||||||
|
return Math.PI / 2 + Math.atan((double) (way_y / -way_x));
|
||||||
|
} else {
|
||||||
|
// fourth quadrant
|
||||||
|
return 0 + Math.atan((double) (-way_x / -way_y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public AnalogStick(VirtualController controller, Context context) {
|
||||||
|
super(controller, context);
|
||||||
|
// reset stick position
|
||||||
position_stick_x = getWidth() / 2;
|
position_stick_x = getWidth() / 2;
|
||||||
position_stick_y = getHeight() / 2;
|
position_stick_y = getHeight() / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addAnalogStickListener(AnalogStickListener listener)
|
public void addAnalogStickListener(AnalogStickListener listener) {
|
||||||
{
|
|
||||||
listeners.add(listener);
|
listeners.add(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOnTouchListener(OnTouchListener listener)
|
private void notifyOnMovement(float x, float y) {
|
||||||
{
|
_DBG("movement x: " + x + " movement y: " + y);
|
||||||
onTouchListener = listener;
|
// notify listeners
|
||||||
|
for (AnalogStickListener listener : listeners) {
|
||||||
|
listener.onMovement(x, y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setColors(int normalColor, int pressedColor)
|
private void notifyOnClick() {
|
||||||
{
|
_DBG("click");
|
||||||
|
// notify listeners
|
||||||
|
for (AnalogStickListener listener : listeners) {
|
||||||
|
listener.onClick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void notifyOnDoubleClick() {
|
||||||
|
_DBG("double click");
|
||||||
|
// notify listeners
|
||||||
|
for (AnalogStickListener listener : listeners) {
|
||||||
|
listener.onDoubleClick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void notifyOnRevoke() {
|
||||||
|
_DBG("revoke");
|
||||||
|
// notify listeners
|
||||||
|
for (AnalogStickListener listener : listeners) {
|
||||||
|
listener.onRevoke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColors(int normalColor, int pressedColor) {
|
||||||
this.normalColor = normalColor;
|
this.normalColor = normalColor;
|
||||||
this.pressedColor = pressedColor;
|
this.pressedColor = pressedColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
private double getMovementRadius(float x, float y)
|
|
||||||
{
|
|
||||||
if (x == 0)
|
|
||||||
{
|
|
||||||
return y > 0 ? y : -y;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (y == 0)
|
|
||||||
{
|
|
||||||
return x > 0 ? x : -x;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Math.sqrt(x * x + y * y);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onSizeChanged(int w, int h, int oldw, int oldh)
|
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||||
{
|
// calculate new radius sizes depending
|
||||||
radius_complete = getPercent(getCorrectWidth() / 2, 90);
|
radius_complete = getPercent(getCorrectWidth() / 2, 90);
|
||||||
radius_minimum = getPercent(getCorrectWidth() / 2, 30);
|
radius_dead_zone = getPercent(getCorrectWidth() / 2, 30);
|
||||||
radius_dead_zone = getPercent(getCorrectWidth() / 2, 10);
|
|
||||||
radius_analog_stick = getPercent(getCorrectWidth() / 2, 20);
|
radius_analog_stick = getPercent(getCorrectWidth() / 2, 20);
|
||||||
|
|
||||||
super.onSizeChanged(w, h, oldw, oldh);
|
super.onSizeChanged(w, h, oldw, oldh);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDraw(Canvas canvas)
|
protected void onElementDraw(Canvas canvas) {
|
||||||
{
|
|
||||||
// set transparent background
|
// set transparent background
|
||||||
canvas.drawColor(Color.TRANSPARENT);
|
canvas.drawColor(Color.TRANSPARENT);
|
||||||
|
|
||||||
@ -99,293 +214,126 @@ public class AnalogStick extends VirtualControllerElement
|
|||||||
paint.setStrokeWidth(getPercent(getCorrectWidth() / 2, 2));
|
paint.setStrokeWidth(getPercent(getCorrectWidth() / 2, 2));
|
||||||
|
|
||||||
// draw outer circle
|
// draw outer circle
|
||||||
if (!isPressed() || click_state == _CLICK_STATE.SINGLE)
|
if (!isPressed() || click_state == CLICK_STATE.SINGLE) {
|
||||||
{
|
|
||||||
paint.setColor(normalColor);
|
paint.setColor(normalColor);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
paint.setColor(pressedColor);
|
paint.setColor(pressedColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
canvas.drawCircle(getWidth() / 2, getHeight() / 2, radius_complete, paint);
|
canvas.drawCircle(getWidth() / 2, getHeight() / 2, radius_complete, paint);
|
||||||
|
|
||||||
paint.setColor(normalColor);
|
paint.setColor(normalColor);
|
||||||
// draw minimum
|
// draw dead zone
|
||||||
canvas.drawCircle(getWidth() / 2, getHeight() / 2, radius_minimum, paint);
|
canvas.drawCircle(getWidth() / 2, getHeight() / 2, radius_dead_zone, paint);
|
||||||
|
|
||||||
// draw stick depending on state (no movement, moved, active(out of dead zone))
|
// draw stick depending on state
|
||||||
switch (stick_state)
|
switch (stick_state) {
|
||||||
{
|
case NO_MOVEMENT: {
|
||||||
case NO_MOVEMENT:
|
|
||||||
{
|
|
||||||
paint.setColor(normalColor);
|
paint.setColor(normalColor);
|
||||||
canvas.drawCircle(getWidth() / 2, getHeight() / 2, radius_analog_stick, paint);
|
canvas.drawCircle(getWidth() / 2, getHeight() / 2, radius_analog_stick, paint);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MOVED_IN_DEAD_ZONE:
|
case MOVED_IN_DEAD_ZONE: {
|
||||||
{
|
|
||||||
paint.setColor(normalColor);
|
paint.setColor(normalColor);
|
||||||
canvas.drawCircle(position_stick_x, position_stick_y, radius_analog_stick, paint);
|
canvas.drawCircle(position_stick_x, position_stick_y, radius_analog_stick, paint);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MOVED_ACTIVE:
|
case MOVED_ACTIVE: {
|
||||||
{
|
|
||||||
paint.setColor(pressedColor);
|
paint.setColor(pressedColor);
|
||||||
canvas.drawCircle(position_stick_x, position_stick_y, radius_analog_stick, paint);
|
canvas.drawCircle(position_stick_x, position_stick_y, radius_analog_stick, paint);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
super.onDraw(canvas);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private double getAngle(float way_x, float way_y)
|
private void updatePosition() {
|
||||||
{
|
// get 100% way
|
||||||
double angle = 0;
|
float complete = (radius_complete - radius_analog_stick - radius_dead_zone);
|
||||||
|
|
||||||
// prevent divisions by zero
|
// calculate relative way
|
||||||
if (way_x == 0)
|
float correlated_y = (float) (Math.sin(Math.PI / 2 - movement_angle) * (movement_radius));
|
||||||
{
|
float correlated_x = (float) (Math.cos(Math.PI / 2 - movement_angle) * (movement_radius));
|
||||||
if (way_y > 0)
|
|
||||||
{
|
|
||||||
angle = 0;
|
|
||||||
}
|
|
||||||
else if (way_y < 0)
|
|
||||||
{
|
|
||||||
angle = Math.PI;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (way_y == 0)
|
|
||||||
{
|
|
||||||
if (way_x > 0)
|
|
||||||
{
|
|
||||||
angle = Math.PI * 3 / 2;
|
|
||||||
}
|
|
||||||
else if (way_x < 0)
|
|
||||||
{
|
|
||||||
angle = Math.PI * 1 / 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (way_x > 0)
|
|
||||||
{
|
|
||||||
if (way_y < 0)
|
|
||||||
{ // first quadrant
|
|
||||||
angle =
|
|
||||||
3 * Math.PI / 2 + Math.atan((double) (-way_y / way_x));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ // second quadrant
|
|
||||||
angle = Math.PI + Math.atan((double) (way_x / way_y));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (way_y > 0)
|
|
||||||
{ // third quadrant
|
|
||||||
angle = Math.PI / 2 + Math.atan((double) (way_y / -way_x));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ // fourth quadrant
|
|
||||||
angle = 0 + Math.atan((double) (-way_x / -way_y));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_DBG("angle: " + angle + " way y: " + way_y + " way x: " + way_x);
|
|
||||||
|
|
||||||
return angle;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void moveActionCallback(float x, float y)
|
|
||||||
{
|
|
||||||
_DBG("movement x: " + x + " movement y: " + y);
|
|
||||||
|
|
||||||
// notify listeners
|
|
||||||
for (AnalogStickListener listener : listeners)
|
|
||||||
{
|
|
||||||
listener.onMovement(x, y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void clickActionCallback()
|
|
||||||
{
|
|
||||||
_DBG("click");
|
|
||||||
|
|
||||||
// notify listeners
|
|
||||||
for (AnalogStickListener listener : listeners)
|
|
||||||
{
|
|
||||||
listener.onClick();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void doubleClickActionCallback()
|
|
||||||
{
|
|
||||||
_DBG("double click");
|
|
||||||
|
|
||||||
// notify listeners
|
|
||||||
for (AnalogStickListener listener : listeners)
|
|
||||||
{
|
|
||||||
listener.onDoubleClick();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void revokeActionCallback()
|
|
||||||
{
|
|
||||||
_DBG("revoke");
|
|
||||||
|
|
||||||
// notify listeners
|
|
||||||
for (AnalogStickListener listener : listeners)
|
|
||||||
{
|
|
||||||
listener.onRevoke();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updatePosition()
|
|
||||||
{
|
|
||||||
// get real way for each axis
|
|
||||||
float way_center_x = -(getWidth() / 2 - position_moved_x);
|
|
||||||
float way_center_y = -(getHeight() / 2 - position_moved_y);
|
|
||||||
|
|
||||||
// get radius and angel of movement from center
|
|
||||||
double movement_radius = getMovementRadius(way_center_x, way_center_y);
|
|
||||||
double movement_angle = getAngle(way_center_x, way_center_y);
|
|
||||||
|
|
||||||
// get dead zone way for each axis
|
|
||||||
float way_pressed_x = position_pressed_x - position_moved_x;
|
|
||||||
float way_pressed_y = position_pressed_y - position_moved_y;
|
|
||||||
|
|
||||||
// get radius and angel from pressed position
|
|
||||||
double movement_dead_zone_radius = getMovementRadius(way_pressed_x, way_pressed_y);
|
|
||||||
|
|
||||||
// chop radius if out of outer circle
|
|
||||||
if (movement_radius > (radius_complete - radius_analog_stick))
|
|
||||||
{
|
|
||||||
movement_radius = radius_complete - radius_analog_stick;
|
|
||||||
}
|
|
||||||
|
|
||||||
// calculate new positions
|
|
||||||
float correlated_y =
|
|
||||||
(float) (Math.sin(Math.PI / 2 - movement_angle) * (movement_radius));
|
|
||||||
float correlated_x =
|
|
||||||
(float) (Math.cos(Math.PI / 2 - movement_angle) * (movement_radius));
|
|
||||||
|
|
||||||
float complete = (radius_complete - radius_analog_stick - radius_minimum);
|
|
||||||
|
|
||||||
float movement_x;
|
|
||||||
float movement_y;
|
|
||||||
|
|
||||||
movement_x = -(1 / complete) * (correlated_x - (correlated_x > 0 ? radius_minimum : -radius_minimum));
|
|
||||||
movement_y = (1 / complete) * (correlated_y - (correlated_y > 0 ? radius_minimum : -radius_minimum));
|
|
||||||
|
|
||||||
|
// update positions
|
||||||
position_stick_x = getWidth() / 2 - correlated_x;
|
position_stick_x = getWidth() / 2 - correlated_x;
|
||||||
position_stick_y = getHeight() / 2 - correlated_y;
|
position_stick_y = getHeight() / 2 - correlated_y;
|
||||||
|
|
||||||
// check if analog stick is outside of dead zone and minimum
|
// set active depending on dead zone
|
||||||
if (movement_radius > radius_minimum && movement_dead_zone_radius > radius_dead_zone)
|
stick_state = movement_radius > radius_dead_zone ?
|
||||||
{
|
STICK_STATE.MOVED_ACTIVE : STICK_STATE.MOVED_IN_DEAD_ZONE;
|
||||||
// set active
|
|
||||||
stick_state = _STICK_STATE.MOVED_ACTIVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stick_state == _STICK_STATE.MOVED_ACTIVE)
|
// trigger move event if state active
|
||||||
{
|
if (stick_state == STICK_STATE.MOVED_ACTIVE) {
|
||||||
moveActionCallback(movement_x, movement_y);
|
notifyOnMovement(-(1 / complete) *
|
||||||
|
(correlated_x - (correlated_x > 0 ? radius_dead_zone : -radius_dead_zone)), (1 / complete) *
|
||||||
|
(correlated_y - (correlated_y > 0 ? radius_dead_zone : -radius_dead_zone)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onTouchEvent(MotionEvent event)
|
public boolean onElementTouchEvent(MotionEvent event) {
|
||||||
{
|
// save last click state
|
||||||
// get masked (not specific to a pointer) action
|
CLICK_STATE lastClickState = click_state;
|
||||||
int action = event.getActionMasked();
|
|
||||||
_CLICK_STATE lastClickState = click_state;
|
|
||||||
|
|
||||||
position_moved_x = event.getX();
|
// get absolute way for each axis
|
||||||
position_moved_y = event.getY();
|
relative_x = -(getWidth() / 2 - event.getX());
|
||||||
|
relative_y = -(getHeight() / 2 - event.getY());
|
||||||
|
|
||||||
switch (action)
|
// get radius and angel of movement from center
|
||||||
{
|
movement_radius = getMovementRadius(relative_x, relative_y);
|
||||||
|
movement_angle = getAngle(relative_x, relative_y);
|
||||||
|
|
||||||
|
// chop radius if out of outer circle and already pressed
|
||||||
|
if (movement_radius > (radius_complete - radius_analog_stick)) {
|
||||||
|
// not pressed already, so ignore event from outer circle
|
||||||
|
if (!isPressed()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
movement_radius = radius_complete - radius_analog_stick;
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle event depending on action
|
||||||
|
switch (event.getActionMasked()) {
|
||||||
|
// down event (touch event)
|
||||||
case MotionEvent.ACTION_DOWN:
|
case MotionEvent.ACTION_DOWN:
|
||||||
case MotionEvent.ACTION_POINTER_DOWN:
|
case MotionEvent.ACTION_POINTER_DOWN: {
|
||||||
{
|
// set to dead zoned, will be corrected in update position if necessary
|
||||||
setPressed(true);
|
stick_state = STICK_STATE.MOVED_IN_DEAD_ZONE;
|
||||||
position_pressed_x = position_moved_x;
|
|
||||||
position_pressed_y = position_moved_y;
|
|
||||||
stick_state = _STICK_STATE.MOVED_IN_DEAD_ZONE;
|
|
||||||
|
|
||||||
// check for double click
|
// check for double click
|
||||||
if (lastClickState == _CLICK_STATE.SINGLE && timeLastClick + timeoutDoubleClick > System.currentTimeMillis())
|
if (lastClickState == CLICK_STATE.SINGLE &&
|
||||||
{
|
timeLastClick + timeoutDoubleClick > System.currentTimeMillis()) {
|
||||||
click_state = _CLICK_STATE.DOUBLE;
|
click_state = CLICK_STATE.DOUBLE;
|
||||||
|
notifyOnDoubleClick();
|
||||||
doubleClickActionCallback();
|
} else {
|
||||||
|
click_state = CLICK_STATE.SINGLE;
|
||||||
|
notifyOnClick();
|
||||||
}
|
}
|
||||||
else
|
// reset last click timestamp
|
||||||
{
|
|
||||||
click_state = _CLICK_STATE.SINGLE;
|
|
||||||
|
|
||||||
clickActionCallback();
|
|
||||||
}
|
|
||||||
|
|
||||||
timeLastClick = System.currentTimeMillis();
|
timeLastClick = System.currentTimeMillis();
|
||||||
|
// set item pressed and update
|
||||||
|
setPressed(true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// up event (revoke touch)
|
||||||
case MotionEvent.ACTION_UP:
|
case MotionEvent.ACTION_UP:
|
||||||
case MotionEvent.ACTION_POINTER_UP:
|
case MotionEvent.ACTION_POINTER_UP: {
|
||||||
{
|
|
||||||
setPressed(false);
|
setPressed(false);
|
||||||
stick_state = _STICK_STATE.NO_MOVEMENT;
|
|
||||||
|
|
||||||
revokeActionCallback();
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isPressed())
|
if (isPressed()) {
|
||||||
{ // when is pressed calculate new positions (will trigger movement if necessary)
|
// when is pressed calculate new positions (will trigger movement if necessary)
|
||||||
updatePosition();
|
updatePosition();
|
||||||
|
} else {
|
||||||
|
stick_state = STICK_STATE.NO_MOVEMENT;
|
||||||
|
notifyOnRevoke();
|
||||||
|
// not longer pressed reset analog stick
|
||||||
|
notifyOnMovement(0, 0);
|
||||||
}
|
}
|
||||||
else
|
// refresh view
|
||||||
{ // not longer pressed reset analog stick
|
|
||||||
moveActionCallback(0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// to get view refreshed
|
|
||||||
invalidate();
|
invalidate();
|
||||||
|
// accept the touch event
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum _STICK_STATE
|
|
||||||
{
|
|
||||||
NO_MOVEMENT,
|
|
||||||
MOVED_IN_DEAD_ZONE,
|
|
||||||
MOVED_ACTIVE
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private enum _CLICK_STATE
|
|
||||||
{
|
|
||||||
SINGLE,
|
|
||||||
DOUBLE
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface AnalogStickListener
|
|
||||||
{
|
|
||||||
void onMovement(float x, float y);
|
|
||||||
|
|
||||||
void onClick();
|
|
||||||
|
|
||||||
void onRevoke();
|
|
||||||
|
|
||||||
void onDoubleClick();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
/**
|
||||||
|
* Created by Karim Mreisi.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.limelight.binding.input.virtual_controller;
|
package com.limelight.binding.input.virtual_controller;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@ -13,14 +17,42 @@ import java.util.Timer;
|
|||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Karim on 24.01.2015.
|
* This is a digital button on screen element. It is used to get click and double click user input.
|
||||||
*/
|
*/
|
||||||
public class DigitalButton extends VirtualControllerElement
|
public class DigitalButton extends VirtualControllerElement {
|
||||||
{
|
|
||||||
static List<DigitalButton> allButtonsList = new ArrayList<>();
|
|
||||||
|
|
||||||
List<DigitalButtonListener> listeners = new ArrayList<>();
|
/**
|
||||||
OnTouchListener onTouchListener = null;
|
* Listener interface to update registered observers.
|
||||||
|
*/
|
||||||
|
public interface DigitalButtonListener {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* onClick event will be fired on button click.
|
||||||
|
*/
|
||||||
|
void onClick();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* onLongClick event will be fired on button long click.
|
||||||
|
*/
|
||||||
|
void onLongClick();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* onRelease event will be fired on button unpress.
|
||||||
|
*/
|
||||||
|
void onRelease();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private class TimerLongClickTimerTask extends TimerTask {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
onLongClickCallback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<DigitalButtonListener> listeners = new ArrayList<DigitalButtonListener>();
|
||||||
private String text = "";
|
private String text = "";
|
||||||
private int icon = -1;
|
private int icon = -1;
|
||||||
private long timerLongClickTimeout = 3000;
|
private long timerLongClickTimeout = 3000;
|
||||||
@ -30,17 +62,14 @@ public class DigitalButton extends VirtualControllerElement
|
|||||||
private int layer;
|
private int layer;
|
||||||
private DigitalButton movingButton = null;
|
private DigitalButton movingButton = null;
|
||||||
|
|
||||||
boolean inRange(float x, float y)
|
boolean inRange(float x, float y) {
|
||||||
{
|
|
||||||
return (this.getX() < x && this.getX() + this.getWidth() > x) &&
|
return (this.getX() < x && this.getX() + this.getWidth() > x) &&
|
||||||
(this.getY() < y && this.getY() + this.getHeight() > y);
|
(this.getY() < y && this.getY() + this.getHeight() > y);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean checkMovement(float x, float y, DigitalButton movingButton)
|
public boolean checkMovement(float x, float y, DigitalButton movingButton) {
|
||||||
{
|
|
||||||
// check if the movement happened in the same layer
|
// check if the movement happened in the same layer
|
||||||
if (movingButton.layer != this.layer)
|
if (movingButton.layer != this.layer) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,36 +78,27 @@ public class DigitalButton extends VirtualControllerElement
|
|||||||
|
|
||||||
// check if the movement directly happened on the button
|
// check if the movement directly happened on the button
|
||||||
if ((this.movingButton == null || movingButton == this.movingButton)
|
if ((this.movingButton == null || movingButton == this.movingButton)
|
||||||
&& this.inRange(x, y))
|
&& this.inRange(x, y)) {
|
||||||
{
|
|
||||||
// set button pressed state depending on moving button pressed state
|
// set button pressed state depending on moving button pressed state
|
||||||
if (this.isPressed() != movingButton.isPressed())
|
if (this.isPressed() != movingButton.isPressed()) {
|
||||||
{
|
|
||||||
this.setPressed(movingButton.isPressed());
|
this.setPressed(movingButton.isPressed());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// check if the movement is outside of the range and the movement button
|
// check if the movement is outside of the range and the movement button
|
||||||
// is saved moving button
|
// is the saved moving button
|
||||||
else if (movingButton == this.movingButton)
|
else if (movingButton == this.movingButton) {
|
||||||
{
|
|
||||||
this.setPressed(false);
|
this.setPressed(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if a change occurred
|
// check if a change occurred
|
||||||
if (wasPressed != isPressed())
|
if (wasPressed != isPressed()) {
|
||||||
{
|
if (isPressed()) {
|
||||||
|
// is pressed set moving button and emit click event
|
||||||
if (isPressed())
|
|
||||||
{ // is pressed set moving button and emit click event
|
|
||||||
this.movingButton = movingButton;
|
this.movingButton = movingButton;
|
||||||
|
|
||||||
onClickCallback();
|
onClickCallback();
|
||||||
}
|
} else {
|
||||||
|
// no longer pressed reset moving button and emit release event
|
||||||
else
|
|
||||||
{ // no longer pressed reset moving button and emit release event
|
|
||||||
this.movingButton = null;
|
this.movingButton = null;
|
||||||
|
|
||||||
onReleaseCallback();
|
onReleaseCallback();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,51 +110,35 @@ public class DigitalButton extends VirtualControllerElement
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkMovementForAllButtons(float x, float y)
|
private void checkMovementForAllButtons(float x, float y) {
|
||||||
{
|
for (VirtualControllerElement element : virtualController.getElements()) {
|
||||||
for (DigitalButton button : allButtonsList)
|
if (element != this && element instanceof DigitalButton){
|
||||||
{
|
((DigitalButton)element).checkMovement(x, y, this);
|
||||||
if (button != this)
|
|
||||||
{
|
|
||||||
button.checkMovement(x, y, this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public DigitalButton(int layer, Context context)
|
public DigitalButton(VirtualController controller, int layer, Context context) {
|
||||||
{
|
super(controller, context);
|
||||||
super(context);
|
|
||||||
|
|
||||||
this.layer = layer;
|
this.layer = layer;
|
||||||
|
|
||||||
allButtonsList.add(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addDigitalButtonListener(DigitalButtonListener listener)
|
public void addDigitalButtonListener(DigitalButtonListener listener) {
|
||||||
{
|
|
||||||
listeners.add(listener);
|
listeners.add(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOnTouchListener(OnTouchListener listener)
|
public void setText(String text) {
|
||||||
{
|
|
||||||
onTouchListener = listener;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setText(String text)
|
|
||||||
{
|
|
||||||
this.text = text;
|
this.text = text;
|
||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setIcon(int id)
|
public void setIcon(int id) {
|
||||||
{
|
|
||||||
this.icon = id;
|
this.icon = id;
|
||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDraw(Canvas canvas)
|
protected void onElementDraw(Canvas canvas) {
|
||||||
{
|
|
||||||
// set transparent background
|
// set transparent background
|
||||||
canvas.drawColor(Color.TRANSPARENT);
|
canvas.drawColor(Color.TRANSPARENT);
|
||||||
|
|
||||||
@ -146,90 +150,58 @@ public class DigitalButton extends VirtualControllerElement
|
|||||||
|
|
||||||
paint.setColor(isPressed() ? pressedColor : normalColor);
|
paint.setColor(isPressed() ? pressedColor : normalColor);
|
||||||
paint.setStyle(Paint.Style.STROKE);
|
paint.setStyle(Paint.Style.STROKE);
|
||||||
canvas.drawRect(
|
canvas.drawRect(1, 1, getWidth() - 1, getHeight() - 1, paint);
|
||||||
1, 1,
|
|
||||||
getWidth() - 1, getHeight() - 1,
|
|
||||||
paint
|
|
||||||
);
|
|
||||||
|
|
||||||
if (icon != -1)
|
if (icon != -1) {
|
||||||
{
|
|
||||||
Drawable d = getResources().getDrawable(icon);
|
Drawable d = getResources().getDrawable(icon);
|
||||||
d.setBounds(5, 5, getWidth() - 5, getHeight() - 5);
|
d.setBounds(5, 5, getWidth() - 5, getHeight() - 5);
|
||||||
d.draw(canvas);
|
d.draw(canvas);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
paint.setStyle(Paint.Style.FILL_AND_STROKE);
|
paint.setStyle(Paint.Style.FILL_AND_STROKE);
|
||||||
canvas.drawText(text,
|
canvas.drawText(text, getPercent(getWidth(), 50), getPercent(getHeight(), 73), paint);
|
||||||
getPercent(getWidth(), 50), getPercent(getHeight(), 73),
|
}
|
||||||
paint);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
super.onDraw(canvas);
|
private void onClickCallback() {
|
||||||
}
|
|
||||||
|
|
||||||
private void onClickCallback()
|
|
||||||
{
|
|
||||||
_DBG("clicked");
|
_DBG("clicked");
|
||||||
|
|
||||||
// notify listeners
|
// notify listeners
|
||||||
for (DigitalButtonListener listener : listeners)
|
for (DigitalButtonListener listener : listeners) {
|
||||||
{
|
|
||||||
listener.onClick();
|
listener.onClick();
|
||||||
}
|
}
|
||||||
|
|
||||||
timerLongClick = new Timer();
|
timerLongClick = new Timer();
|
||||||
longClickTimerTask = new TimerLongClickTimerTask();
|
longClickTimerTask = new TimerLongClickTimerTask();
|
||||||
|
|
||||||
timerLongClick.schedule(longClickTimerTask, timerLongClickTimeout);
|
timerLongClick.schedule(longClickTimerTask, timerLongClickTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onLongClickCallback()
|
private void onLongClickCallback() {
|
||||||
{
|
|
||||||
_DBG("long click");
|
_DBG("long click");
|
||||||
|
|
||||||
// notify listeners
|
// notify listeners
|
||||||
for (DigitalButtonListener listener : listeners)
|
for (DigitalButtonListener listener : listeners) {
|
||||||
{
|
|
||||||
listener.onLongClick();
|
listener.onLongClick();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onReleaseCallback()
|
private void onReleaseCallback() {
|
||||||
{
|
|
||||||
_DBG("released");
|
_DBG("released");
|
||||||
|
|
||||||
// notify listeners
|
// notify listeners
|
||||||
for (DigitalButtonListener listener : listeners)
|
for (DigitalButtonListener listener : listeners) {
|
||||||
{
|
|
||||||
listener.onRelease();
|
listener.onRelease();
|
||||||
}
|
}
|
||||||
|
|
||||||
timerLongClick.cancel();
|
timerLongClick.cancel();
|
||||||
longClickTimerTask.cancel();
|
longClickTimerTask.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onTouchEvent(MotionEvent event)
|
public boolean onElementTouchEvent(MotionEvent event) {
|
||||||
{
|
|
||||||
/*
|
|
||||||
if (onTouchListener != null)
|
|
||||||
{
|
|
||||||
return onTouchListener.onTouch(this, event);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
// get masked (not specific to a pointer) action
|
// get masked (not specific to a pointer) action
|
||||||
|
|
||||||
float x = getX() + event.getX();
|
float x = getX() + event.getX();
|
||||||
float y = getY() + event.getY();
|
float y = getY() + event.getY();
|
||||||
int action = event.getActionMasked();
|
int action = event.getActionMasked();
|
||||||
|
|
||||||
switch (action)
|
switch (action) {
|
||||||
{
|
|
||||||
case MotionEvent.ACTION_DOWN:
|
case MotionEvent.ACTION_DOWN:
|
||||||
case MotionEvent.ACTION_POINTER_DOWN:
|
case MotionEvent.ACTION_POINTER_DOWN: {
|
||||||
{
|
|
||||||
movingButton = null;
|
movingButton = null;
|
||||||
setPressed(true);
|
setPressed(true);
|
||||||
onClickCallback();
|
onClickCallback();
|
||||||
@ -238,16 +210,14 @@ public class DigitalButton extends VirtualControllerElement
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case MotionEvent.ACTION_MOVE:
|
case MotionEvent.ACTION_MOVE: {
|
||||||
{
|
|
||||||
checkMovementForAllButtons(x, y);
|
checkMovementForAllButtons(x, y);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case MotionEvent.ACTION_CANCEL:
|
case MotionEvent.ACTION_CANCEL:
|
||||||
case MotionEvent.ACTION_UP:
|
case MotionEvent.ACTION_UP:
|
||||||
case MotionEvent.ACTION_POINTER_UP:
|
case MotionEvent.ACTION_POINTER_UP: {
|
||||||
{
|
|
||||||
setPressed(false);
|
setPressed(false);
|
||||||
onReleaseCallback();
|
onReleaseCallback();
|
||||||
|
|
||||||
@ -257,29 +227,9 @@ public class DigitalButton extends VirtualControllerElement
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
default:
|
default: {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface DigitalButtonListener
|
|
||||||
{
|
|
||||||
void onClick();
|
|
||||||
|
|
||||||
void onLongClick();
|
|
||||||
|
|
||||||
void onRelease();
|
|
||||||
}
|
|
||||||
|
|
||||||
private class TimerLongClickTimerTask extends TimerTask
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void run()
|
|
||||||
{
|
|
||||||
onLongClickCallback();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
/**
|
||||||
|
* Created by Karim Mreisi.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.limelight.binding.input.virtual_controller;
|
package com.limelight.binding.input.virtual_controller;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@ -9,11 +13,7 @@ import android.view.MotionEvent;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
public class DigitalPad extends VirtualControllerElement {
|
||||||
* Created by Karim Mreisi on 23.01.2015.
|
|
||||||
*/
|
|
||||||
public class DigitalPad extends VirtualControllerElement
|
|
||||||
{
|
|
||||||
public final static int DIGITAL_PAD_DIRECTION_NO_DIRECTION = 0;
|
public final static int DIGITAL_PAD_DIRECTION_NO_DIRECTION = 0;
|
||||||
int direction = DIGITAL_PAD_DIRECTION_NO_DIRECTION;
|
int direction = DIGITAL_PAD_DIRECTION_NO_DIRECTION;
|
||||||
public final static int DIGITAL_PAD_DIRECTION_LEFT = 1;
|
public final static int DIGITAL_PAD_DIRECTION_LEFT = 1;
|
||||||
@ -21,26 +21,17 @@ public class DigitalPad extends VirtualControllerElement
|
|||||||
public final static int DIGITAL_PAD_DIRECTION_RIGHT = 4;
|
public final static int DIGITAL_PAD_DIRECTION_RIGHT = 4;
|
||||||
public final static int DIGITAL_PAD_DIRECTION_DOWN = 8;
|
public final static int DIGITAL_PAD_DIRECTION_DOWN = 8;
|
||||||
List<DigitalPadListener> listeners = new ArrayList<DigitalPadListener>();
|
List<DigitalPadListener> listeners = new ArrayList<DigitalPadListener>();
|
||||||
OnTouchListener onTouchListener = null;
|
|
||||||
|
|
||||||
public DigitalPad(Context context)
|
public DigitalPad(VirtualController controller, Context context) {
|
||||||
{
|
super(controller, context);
|
||||||
super(context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addDigitalPadListener(DigitalPadListener listener)
|
public void addDigitalPadListener(DigitalPadListener listener) {
|
||||||
{
|
|
||||||
listeners.add(listener);
|
listeners.add(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOnTouchListener(OnTouchListener listener)
|
|
||||||
{
|
|
||||||
onTouchListener = listener;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDraw(Canvas canvas)
|
protected void onElementDraw(Canvas canvas) {
|
||||||
{
|
|
||||||
// set transparent background
|
// set transparent background
|
||||||
canvas.drawColor(Color.TRANSPARENT);
|
canvas.drawColor(Color.TRANSPARENT);
|
||||||
|
|
||||||
@ -50,8 +41,7 @@ public class DigitalPad extends VirtualControllerElement
|
|||||||
paint.setTextAlign(Paint.Align.CENTER);
|
paint.setTextAlign(Paint.Align.CENTER);
|
||||||
paint.setStrokeWidth(3);
|
paint.setStrokeWidth(3);
|
||||||
|
|
||||||
if (direction == DIGITAL_PAD_DIRECTION_NO_DIRECTION)
|
if (direction == DIGITAL_PAD_DIRECTION_NO_DIRECTION) {
|
||||||
{
|
|
||||||
// draw no direction rect
|
// draw no direction rect
|
||||||
paint.setStyle(Paint.Style.STROKE);
|
paint.setStyle(Paint.Style.STROKE);
|
||||||
paint.setColor(normalColor);
|
paint.setColor(normalColor);
|
||||||
@ -84,7 +74,7 @@ public class DigitalPad extends VirtualControllerElement
|
|||||||
);
|
);
|
||||||
paint.setStyle(Paint.Style.STROKE);
|
paint.setStyle(Paint.Style.STROKE);
|
||||||
canvas.drawLine(
|
canvas.drawLine(
|
||||||
0, getPercent(getWidth(), 33),
|
0, getPercent(getHeight(), 33),
|
||||||
getPercent(getWidth(), 33), 0,
|
getPercent(getWidth(), 33), 0,
|
||||||
paint
|
paint
|
||||||
);
|
);
|
||||||
@ -169,87 +159,60 @@ public class DigitalPad extends VirtualControllerElement
|
|||||||
getPercent(getWidth(), 0), getPercent(getHeight(), 66),
|
getPercent(getWidth(), 0), getPercent(getHeight(), 66),
|
||||||
paint
|
paint
|
||||||
);
|
);
|
||||||
|
|
||||||
super.onDraw(canvas);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void newDirectionCallback(int direction)
|
private void newDirectionCallback(int direction) {
|
||||||
{
|
|
||||||
_DBG("direction: " + direction);
|
_DBG("direction: " + direction);
|
||||||
|
|
||||||
// notify listeners
|
// notify listeners
|
||||||
for (DigitalPadListener listener : listeners)
|
for (DigitalPadListener listener : listeners) {
|
||||||
{
|
|
||||||
listener.onDirectionChange(direction);
|
listener.onDirectionChange(direction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onTouchEvent(MotionEvent event)
|
public boolean onElementTouchEvent(MotionEvent event) {
|
||||||
{
|
|
||||||
if (onTouchListener != null)
|
|
||||||
{
|
|
||||||
return onTouchListener.onTouch(this, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
// get masked (not specific to a pointer) action
|
// get masked (not specific to a pointer) action
|
||||||
int action = event.getActionMasked();
|
switch (event.getActionMasked()) {
|
||||||
|
|
||||||
switch (action)
|
|
||||||
{
|
|
||||||
case MotionEvent.ACTION_DOWN:
|
case MotionEvent.ACTION_DOWN:
|
||||||
case MotionEvent.ACTION_POINTER_DOWN:
|
case MotionEvent.ACTION_POINTER_DOWN:
|
||||||
{
|
case MotionEvent.ACTION_MOVE: {
|
||||||
direction = 0;
|
direction = 0;
|
||||||
|
|
||||||
if (event.getX() < getPercent(getWidth(), 33))
|
if (event.getX() < getPercent(getWidth(), 33)) {
|
||||||
{
|
|
||||||
direction |= DIGITAL_PAD_DIRECTION_LEFT;
|
direction |= DIGITAL_PAD_DIRECTION_LEFT;
|
||||||
}
|
}
|
||||||
|
if (event.getX() > getPercent(getWidth(), 66)) {
|
||||||
if (event.getX() > getPercent(getWidth(), 66))
|
|
||||||
{
|
|
||||||
direction |= DIGITAL_PAD_DIRECTION_RIGHT;
|
direction |= DIGITAL_PAD_DIRECTION_RIGHT;
|
||||||
}
|
}
|
||||||
|
if (event.getY() > getPercent(getHeight(), 66)) {
|
||||||
if (event.getY() > getPercent(getHeight(), 66))
|
|
||||||
{
|
|
||||||
direction |= DIGITAL_PAD_DIRECTION_DOWN;
|
direction |= DIGITAL_PAD_DIRECTION_DOWN;
|
||||||
}
|
}
|
||||||
|
if (event.getY() < getPercent(getHeight(), 33)) {
|
||||||
if (event.getY() < getPercent(getHeight(), 33))
|
|
||||||
{
|
|
||||||
direction |= DIGITAL_PAD_DIRECTION_UP;
|
direction |= DIGITAL_PAD_DIRECTION_UP;
|
||||||
}
|
}
|
||||||
|
|
||||||
newDirectionCallback(direction);
|
newDirectionCallback(direction);
|
||||||
|
|
||||||
invalidate();
|
invalidate();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case MotionEvent.ACTION_CANCEL:
|
case MotionEvent.ACTION_CANCEL:
|
||||||
case MotionEvent.ACTION_UP:
|
case MotionEvent.ACTION_UP:
|
||||||
case MotionEvent.ACTION_POINTER_UP:
|
case MotionEvent.ACTION_POINTER_UP: {
|
||||||
{
|
|
||||||
direction = 0;
|
direction = 0;
|
||||||
|
|
||||||
newDirectionCallback(direction);
|
newDirectionCallback(direction);
|
||||||
|
|
||||||
invalidate();
|
invalidate();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
default:
|
default: {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface DigitalPadListener
|
public interface DigitalPadListener {
|
||||||
{
|
|
||||||
void onDirectionChange(int direction);
|
void onDirectionChange(int direction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,49 @@
|
|||||||
|
/**
|
||||||
|
* Created by Karim Mreisi.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.limelight.binding.input.virtual_controller;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import com.limelight.nvstream.input.ControllerPacket;
|
||||||
|
|
||||||
|
public class LeftAnalogStick extends AnalogStick {
|
||||||
|
public LeftAnalogStick(final VirtualController controller, final Context context) {
|
||||||
|
super(controller, context);
|
||||||
|
|
||||||
|
addAnalogStickListener(new AnalogStick.AnalogStickListener() {
|
||||||
|
@Override
|
||||||
|
public void onMovement(float x, float y) {
|
||||||
|
VirtualController.ControllerInputContext inputContext =
|
||||||
|
controller.getControllerInputContext();
|
||||||
|
inputContext.leftStickX = (short) (x * 0x7FFE);
|
||||||
|
inputContext.leftStickY = (short) (y * 0x7FFE);
|
||||||
|
|
||||||
|
controller.sendControllerInputContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDoubleClick() {
|
||||||
|
VirtualController.ControllerInputContext inputContext =
|
||||||
|
controller.getControllerInputContext();
|
||||||
|
inputContext.inputMap |= ControllerPacket.LS_CLK_FLAG;
|
||||||
|
|
||||||
|
controller.sendControllerInputContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRevoke() {
|
||||||
|
VirtualController.ControllerInputContext inputContext =
|
||||||
|
controller.getControllerInputContext();
|
||||||
|
inputContext.inputMap &= ~ControllerPacket.LS_CLK_FLAG;
|
||||||
|
|
||||||
|
controller.sendControllerInputContext();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
/**
|
||||||
|
* Created by Karim Mreisi.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.limelight.binding.input.virtual_controller;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
public class LeftTrigger extends DigitalButton {
|
||||||
|
public LeftTrigger(final VirtualController controller, final int layer, final Context context) {
|
||||||
|
super(controller, layer, context);
|
||||||
|
addDigitalButtonListener(new DigitalButton.DigitalButtonListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick() {
|
||||||
|
VirtualController.ControllerInputContext inputContext =
|
||||||
|
controller.getControllerInputContext();
|
||||||
|
inputContext.leftTrigger = (byte)0xFF;
|
||||||
|
|
||||||
|
controller.sendControllerInputContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLongClick() {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRelease() {
|
||||||
|
VirtualController.ControllerInputContext inputContext =
|
||||||
|
controller.getControllerInputContext();
|
||||||
|
inputContext.leftTrigger = (byte)0x00;
|
||||||
|
|
||||||
|
controller.sendControllerInputContext();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
/**
|
||||||
|
* Created by Karim Mreisi.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.limelight.binding.input.virtual_controller;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import com.limelight.nvstream.input.ControllerPacket;
|
||||||
|
|
||||||
|
public class RightAnalogStick extends AnalogStick {
|
||||||
|
public RightAnalogStick(final VirtualController controller, final Context context) {
|
||||||
|
super(controller, context);
|
||||||
|
|
||||||
|
addAnalogStickListener(new AnalogStick.AnalogStickListener() {
|
||||||
|
@Override
|
||||||
|
public void onMovement(float x, float y) {
|
||||||
|
VirtualController.ControllerInputContext inputContext =
|
||||||
|
controller.getControllerInputContext();
|
||||||
|
inputContext.rightStickX = (short) (x * 0x7FFE);
|
||||||
|
inputContext.rightStickY = (short) (y * 0x7FFE);
|
||||||
|
|
||||||
|
controller.sendControllerInputContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDoubleClick() {
|
||||||
|
VirtualController.ControllerInputContext inputContext =
|
||||||
|
controller.getControllerInputContext();
|
||||||
|
inputContext.inputMap |= ControllerPacket.RS_CLK_FLAG;
|
||||||
|
|
||||||
|
controller.sendControllerInputContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRevoke() {
|
||||||
|
VirtualController.ControllerInputContext inputContext =
|
||||||
|
controller.getControllerInputContext();
|
||||||
|
inputContext.inputMap &= ~ControllerPacket.RS_CLK_FLAG;
|
||||||
|
|
||||||
|
controller.sendControllerInputContext();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
/**
|
||||||
|
* Created by Karim Mreisi.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.limelight.binding.input.virtual_controller;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
public class RightTrigger extends DigitalButton {
|
||||||
|
public RightTrigger(final VirtualController controller, final int layer, final Context context) {
|
||||||
|
super(controller, layer, context);
|
||||||
|
addDigitalButtonListener(new DigitalButton.DigitalButtonListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick() {
|
||||||
|
VirtualController.ControllerInputContext inputContext =
|
||||||
|
controller.getControllerInputContext();
|
||||||
|
inputContext.rightTrigger = (byte)0xFF;
|
||||||
|
|
||||||
|
controller.sendControllerInputContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLongClick() {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRelease() {
|
||||||
|
VirtualController.ControllerInputContext inputContext =
|
||||||
|
controller.getControllerInputContext();
|
||||||
|
inputContext.rightTrigger = (byte)0x00;
|
||||||
|
|
||||||
|
controller.sendControllerInputContext();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -1,467 +1,148 @@
|
|||||||
|
/**
|
||||||
|
* Created by Karim Mreisi.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.limelight.binding.input.virtual_controller;
|
package com.limelight.binding.input.virtual_controller;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.limelight.R;
|
import com.limelight.R;
|
||||||
import com.limelight.nvstream.NvConnection;
|
import com.limelight.nvstream.NvConnection;
|
||||||
import com.limelight.nvstream.input.ControllerPacket;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
public class VirtualController {
|
||||||
* Created by Karim Mreisi on 30.11.2014.
|
public class ControllerInputContext {
|
||||||
*/
|
public short inputMap = 0x0000;
|
||||||
public class VirtualController
|
public byte leftTrigger = 0x00;
|
||||||
{
|
public byte rightTrigger = 0x00;
|
||||||
private static final boolean _PRINT_DEBUG_INFORMATION = false;
|
public short rightStickX = 0x0000;
|
||||||
NvConnection connection = null;
|
public short rightStickY = 0x0000;
|
||||||
|
public short leftStickX = 0x0000;
|
||||||
|
public short leftStickY = 0x0000;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ControllerMode {
|
||||||
|
Active,
|
||||||
|
Configuration
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final boolean _PRINT_DEBUG_INFORMATION = true;
|
||||||
|
|
||||||
|
private NvConnection connection = null;
|
||||||
private Context context = null;
|
private Context context = null;
|
||||||
private short inputMap = 0x0000;
|
|
||||||
private byte leftTrigger = 0x00;
|
|
||||||
private byte rightTrigger = 0x00;
|
|
||||||
private short rightStickX = 0x0000;
|
|
||||||
private short rightStickY = 0x0000;
|
|
||||||
private short leftStickX = 0x0000;
|
|
||||||
private short leftStickY = 0x0000;
|
|
||||||
|
|
||||||
private FrameLayout frame_layout = null;
|
private FrameLayout frame_layout = null;
|
||||||
private RelativeLayout relative_layout = null;
|
private RelativeLayout relative_layout = null;
|
||||||
|
|
||||||
private RelativeLayout.LayoutParams layoutParamsButtonStart = null;
|
ControllerMode currentMode = ControllerMode.Active;
|
||||||
private RelativeLayout.LayoutParams layoutParamsButtonSelect = null;
|
ControllerInputContext inputContext = new ControllerInputContext();
|
||||||
|
|
||||||
private RelativeLayout.LayoutParams layoutParamsDPad = null;
|
|
||||||
|
|
||||||
private RelativeLayout.LayoutParams layoutParamsButtonA = null;
|
|
||||||
private RelativeLayout.LayoutParams layoutParamsButtonB = null;
|
|
||||||
private RelativeLayout.LayoutParams layoutParamsButtonX = null;
|
|
||||||
private RelativeLayout.LayoutParams layoutParamsButtonY = null;
|
|
||||||
private RelativeLayout.LayoutParams layoutParamsButtonLT = null;
|
|
||||||
private RelativeLayout.LayoutParams layoutParamsButtonRT = null;
|
|
||||||
private RelativeLayout.LayoutParams layoutParamsButtonLB = null;
|
|
||||||
private RelativeLayout.LayoutParams layoutParamsButtonRB = null;
|
|
||||||
|
|
||||||
private RelativeLayout.LayoutParams layoutParamsStick = null;
|
|
||||||
private RelativeLayout.LayoutParams layoutParamsStick2 = null;
|
|
||||||
|
|
||||||
private RelativeLayout.LayoutParams layoutParamsButtonConfigure = null;
|
private RelativeLayout.LayoutParams layoutParamsButtonConfigure = null;
|
||||||
|
private Button buttonConfigure = null;
|
||||||
|
|
||||||
private DigitalButton buttonStart = null;
|
private List<VirtualControllerElement> elements = new ArrayList<VirtualControllerElement>();
|
||||||
private DigitalButton buttonSelect = null;
|
|
||||||
|
|
||||||
private DigitalPad digitalPad = null;
|
public VirtualController(final NvConnection conn, FrameLayout layout, final Context context) {
|
||||||
|
|
||||||
private DigitalButton buttonA = null;
|
|
||||||
private DigitalButton buttonB = null;
|
|
||||||
private DigitalButton buttonX = null;
|
|
||||||
private DigitalButton buttonY = null;
|
|
||||||
private DigitalButton buttonLT = null;
|
|
||||||
private DigitalButton buttonRT = null;
|
|
||||||
private DigitalButton buttonLB = null;
|
|
||||||
private DigitalButton buttonRB = null;
|
|
||||||
|
|
||||||
private AnalogStick stick = null;
|
|
||||||
private AnalogStick stick2 = null;
|
|
||||||
|
|
||||||
private DigitalButton buttonConfigure = null;
|
|
||||||
|
|
||||||
public VirtualController(final NvConnection conn, FrameLayout layout, final Context context)
|
|
||||||
{
|
|
||||||
this.connection = conn;
|
this.connection = conn;
|
||||||
this.frame_layout = layout;
|
this.frame_layout = layout;
|
||||||
this.context = context;
|
this.context = context;
|
||||||
|
|
||||||
relative_layout = new RelativeLayout(context);
|
relative_layout = new RelativeLayout(context);
|
||||||
|
|
||||||
relative_layout.addOnLayoutChangeListener(new View.OnLayoutChangeListener()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom)
|
|
||||||
{
|
|
||||||
refreshLayout();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
frame_layout.addView(relative_layout);
|
frame_layout.addView(relative_layout);
|
||||||
|
|
||||||
digitalPad = new DigitalPad(context);
|
buttonConfigure = new Button(context);
|
||||||
digitalPad.addDigitalPadListener(new DigitalPad.DigitalPadListener()
|
buttonConfigure.setBackgroundResource(R.drawable.settings);
|
||||||
{
|
buttonConfigure.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onDirectionChange(int direction)
|
public void onClick(View v) {
|
||||||
{
|
if (currentMode == ControllerMode.Configuration) {
|
||||||
do
|
currentMode = ControllerMode.Active;
|
||||||
{
|
} else {
|
||||||
if (direction == DigitalPad.DIGITAL_PAD_DIRECTION_NO_DIRECTION)
|
currentMode = ControllerMode.Configuration;
|
||||||
{
|
|
||||||
inputMap &= ~ControllerPacket.LEFT_FLAG;
|
|
||||||
inputMap &= ~ControllerPacket.RIGHT_FLAG;
|
|
||||||
inputMap &= ~ControllerPacket.UP_FLAG;
|
|
||||||
inputMap &= ~ControllerPacket.DOWN_FLAG;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
Toast.makeText(context, "CHANGE MODE " + currentMode, Toast.LENGTH_SHORT).show();
|
||||||
|
|
||||||
if ((direction & DigitalPad.DIGITAL_PAD_DIRECTION_LEFT) > 0)
|
relative_layout.invalidate();
|
||||||
{
|
|
||||||
inputMap |= ControllerPacket.LEFT_FLAG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((direction & DigitalPad.DIGITAL_PAD_DIRECTION_RIGHT) > 0)
|
|
||||||
{
|
|
||||||
inputMap |= ControllerPacket.RIGHT_FLAG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((direction & DigitalPad.DIGITAL_PAD_DIRECTION_UP) > 0)
|
|
||||||
{
|
|
||||||
inputMap |= ControllerPacket.UP_FLAG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((direction & DigitalPad.DIGITAL_PAD_DIRECTION_DOWN) > 0)
|
|
||||||
{
|
|
||||||
inputMap |= ControllerPacket.DOWN_FLAG;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (false);
|
|
||||||
|
|
||||||
sendControllerInputPacket();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
buttonX = createDigitalButton("X", ControllerPacket.X_FLAG, context);
|
|
||||||
buttonY = createDigitalButton("Y", ControllerPacket.Y_FLAG, context);
|
|
||||||
buttonA = createDigitalButton("A", ControllerPacket.A_FLAG, context);
|
|
||||||
buttonB = createDigitalButton("B", ControllerPacket.B_FLAG, context);
|
|
||||||
|
|
||||||
buttonLT = new DigitalButton(2, context);
|
|
||||||
buttonLT.setText("LT");
|
|
||||||
buttonLT.addDigitalButtonListener(new DigitalButton.DigitalButtonListener()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void onClick()
|
|
||||||
{
|
|
||||||
leftTrigger = (byte) (1 * 0xFF);
|
|
||||||
|
|
||||||
sendControllerInputPacket();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void removeElements() {
|
||||||
public void onLongClick()
|
for (VirtualControllerElement element : elements) {
|
||||||
{
|
relative_layout.removeView(element);
|
||||||
|
elements.remove(element);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void addElement(VirtualControllerElement element, int x, int y, int width, int height) {
|
||||||
public void onRelease()
|
elements.add(element);
|
||||||
{
|
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(width, height);
|
||||||
leftTrigger = (byte) (0 * 0xFF);
|
layoutParams.setMargins(x, y, 0, 0);
|
||||||
|
|
||||||
sendControllerInputPacket();
|
relative_layout.addView(element, layoutParams);
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
buttonRT = new DigitalButton(2, context);
|
|
||||||
buttonRT.setText("RT");
|
|
||||||
buttonRT.addDigitalButtonListener(new DigitalButton.DigitalButtonListener()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void onClick()
|
|
||||||
{
|
|
||||||
rightTrigger = (byte) (0xFF);
|
|
||||||
|
|
||||||
sendControllerInputPacket();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public List<VirtualControllerElement> getElements() {
|
||||||
public void onLongClick()
|
return elements;
|
||||||
{
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private static final void _DBG(String text) {
|
||||||
public void onRelease()
|
if (_PRINT_DEBUG_INFORMATION) {
|
||||||
{
|
|
||||||
rightTrigger = (byte) (0);
|
|
||||||
|
|
||||||
sendControllerInputPacket();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
buttonLB = createDigitalButton("LB", ControllerPacket.LB_FLAG, context);
|
|
||||||
buttonRB = createDigitalButton("RB", ControllerPacket.RB_FLAG, context);
|
|
||||||
|
|
||||||
stick = new AnalogStick(context);
|
|
||||||
|
|
||||||
stick.addAnalogStickListener(new AnalogStick.AnalogStickListener()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void onMovement(float x, float y)
|
|
||||||
{
|
|
||||||
leftStickX = (short) (x * 0x7FFE);
|
|
||||||
leftStickY = (short) (y * 0x7FFE);
|
|
||||||
|
|
||||||
_DBG("LEFT STICK MOVEMENT X: " + leftStickX + " Y: " + leftStickY);
|
|
||||||
sendControllerInputPacket();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClick()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDoubleClick()
|
|
||||||
{
|
|
||||||
inputMap |= ControllerPacket.LS_CLK_FLAG;
|
|
||||||
|
|
||||||
sendControllerInputPacket();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onRevoke()
|
|
||||||
{
|
|
||||||
inputMap &= ~ControllerPacket.LS_CLK_FLAG;
|
|
||||||
|
|
||||||
sendControllerInputPacket();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
stick2 = new AnalogStick(context);
|
|
||||||
stick2.addAnalogStickListener(new AnalogStick.AnalogStickListener()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void onMovement(float x, float y)
|
|
||||||
{
|
|
||||||
rightStickX = (short) (x * 0x7FFE);
|
|
||||||
rightStickY = (short) (y * 0x7FFE);
|
|
||||||
|
|
||||||
_DBG("RIGHT STICK MOVEMENT X: " + rightStickX + " Y: " + rightStickY);
|
|
||||||
sendControllerInputPacket();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClick()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDoubleClick()
|
|
||||||
{
|
|
||||||
inputMap |= ControllerPacket.RS_CLK_FLAG;
|
|
||||||
|
|
||||||
sendControllerInputPacket();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onRevoke()
|
|
||||||
{
|
|
||||||
inputMap &= ~ControllerPacket.RS_CLK_FLAG;
|
|
||||||
|
|
||||||
sendControllerInputPacket();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
buttonStart = createDigitalButton("START", ControllerPacket.PLAY_FLAG, context);
|
|
||||||
buttonSelect =
|
|
||||||
createDigitalButton("SELECT", ControllerPacket.SPECIAL_BUTTON_FLAG, context);
|
|
||||||
|
|
||||||
buttonConfigure = new DigitalButton(1, context);
|
|
||||||
buttonConfigure.setIcon(R.drawable.settings);
|
|
||||||
buttonConfigure.addDigitalButtonListener(new DigitalButton.DigitalButtonListener()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void onClick()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onLongClick()
|
|
||||||
{
|
|
||||||
openSettingsDialog();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onRelease()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
refreshLayout();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final void _DBG(String text)
|
|
||||||
{
|
|
||||||
if (_PRINT_DEBUG_INFORMATION)
|
|
||||||
{
|
|
||||||
System.out.println("VirtualController: " + text);
|
System.out.println("VirtualController: " + text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getPercentageV(int percent)
|
public void refreshLayout() {
|
||||||
{
|
relative_layout.removeAllViews();
|
||||||
return (int) (((float) frame_layout.getHeight() / (float) 100) * (float) percent);
|
removeElements();
|
||||||
|
|
||||||
|
layoutParamsButtonConfigure = new RelativeLayout.LayoutParams(50, 50);
|
||||||
|
relative_layout.addView(buttonConfigure, layoutParamsButtonConfigure);
|
||||||
|
|
||||||
|
VirtualControllerConfigurationLoader.createDefaultLayout(this, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getPercentageH(int percent)
|
public ControllerMode getControllerMode () {
|
||||||
{
|
return currentMode;
|
||||||
return (int) (((float) frame_layout.getWidth() / (float) 100) * (float) percent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setPercentilePosition(RelativeLayout.LayoutParams parm, float pos_x, float pos_y)
|
public ControllerInputContext getControllerInputContext () {
|
||||||
{
|
return inputContext;
|
||||||
parm.setMargins(
|
}
|
||||||
(int) (((float) frame_layout.getWidth() / (float) 100 * pos_x) - ((float) parm.width / (float) 2)),
|
|
||||||
(int) (((float) frame_layout.getHeight() / (float) 100 * pos_y) - ((float) parm.height / (float) 2)),
|
public void sendControllerInputContext() {
|
||||||
0,
|
sendControllerInputPacket();
|
||||||
0
|
}
|
||||||
|
|
||||||
|
private void sendControllerInputPacket() {
|
||||||
|
try {
|
||||||
|
_DBG("INPUT_MAP + " + inputContext.inputMap);
|
||||||
|
_DBG("LEFT_TRIGGER " + inputContext.leftTrigger);
|
||||||
|
_DBG("RIGHT_TRIGGER " + inputContext.rightTrigger);
|
||||||
|
_DBG("LEFT STICK X: " + inputContext.leftStickX + " Y: " + inputContext.leftStickY);
|
||||||
|
_DBG("RIGHT STICK X: " + inputContext.rightStickX + " Y: " + inputContext.rightStickY);
|
||||||
|
_DBG("RIGHT STICK X: " + inputContext.rightStickX + " Y: " + inputContext.rightStickY);
|
||||||
|
|
||||||
|
if (connection != null) {
|
||||||
|
connection.sendControllerInput(
|
||||||
|
inputContext.inputMap,
|
||||||
|
inputContext.leftTrigger,
|
||||||
|
inputContext.rightTrigger,
|
||||||
|
inputContext.leftStickX,
|
||||||
|
inputContext.leftStickY,
|
||||||
|
inputContext.rightStickX,
|
||||||
|
inputContext.rightStickY
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
public void openSettingsDialog()
|
|
||||||
{
|
|
||||||
Intent virtualControllerConfiguration =
|
|
||||||
new Intent(context, VirtualControllerSettings.class);
|
|
||||||
virtualControllerConfiguration.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
||||||
|
|
||||||
context.startActivity(virtualControllerConfiguration);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void refreshLayout()
|
|
||||||
{
|
|
||||||
relative_layout.removeAllViews();
|
|
||||||
|
|
||||||
layoutParamsDPad =
|
|
||||||
new RelativeLayout.LayoutParams(getPercentageV(30), getPercentageV(30));
|
|
||||||
|
|
||||||
layoutParamsStick =
|
|
||||||
new RelativeLayout.LayoutParams(getPercentageV(40), getPercentageV(40));
|
|
||||||
layoutParamsStick2 =
|
|
||||||
new RelativeLayout.LayoutParams(getPercentageV(40), getPercentageV(40));
|
|
||||||
|
|
||||||
layoutParamsButtonA =
|
|
||||||
new RelativeLayout.LayoutParams(getPercentageV(10), getPercentageV(10));
|
|
||||||
layoutParamsButtonB =
|
|
||||||
new RelativeLayout.LayoutParams(getPercentageV(10), getPercentageV(10));
|
|
||||||
layoutParamsButtonX =
|
|
||||||
new RelativeLayout.LayoutParams(getPercentageV(10), getPercentageV(10));
|
|
||||||
layoutParamsButtonY =
|
|
||||||
new RelativeLayout.LayoutParams(getPercentageV(10), getPercentageV(10));
|
|
||||||
layoutParamsButtonLT =
|
|
||||||
new RelativeLayout.LayoutParams(getPercentageV(10), getPercentageV(10));
|
|
||||||
layoutParamsButtonRT =
|
|
||||||
new RelativeLayout.LayoutParams(getPercentageV(10), getPercentageV(10));
|
|
||||||
|
|
||||||
layoutParamsButtonLB =
|
|
||||||
new RelativeLayout.LayoutParams(getPercentageV(10), getPercentageV(10));
|
|
||||||
layoutParamsButtonRB =
|
|
||||||
new RelativeLayout.LayoutParams(getPercentageV(10), getPercentageV(10));
|
|
||||||
|
|
||||||
layoutParamsButtonStart =
|
|
||||||
new RelativeLayout.LayoutParams(getPercentageH(12), getPercentageV(8));
|
|
||||||
layoutParamsButtonSelect =
|
|
||||||
new RelativeLayout.LayoutParams(getPercentageH(12), getPercentageV(8));
|
|
||||||
|
|
||||||
layoutParamsButtonConfigure =
|
|
||||||
new RelativeLayout.LayoutParams(getPercentageV(10), getPercentageV(10));
|
|
||||||
|
|
||||||
setPercentilePosition(layoutParamsDPad, 10, 35);
|
|
||||||
|
|
||||||
setPercentilePosition(layoutParamsStick, 22, 78);
|
|
||||||
setPercentilePosition(layoutParamsStick2, 78, 78);
|
|
||||||
|
|
||||||
setPercentilePosition(layoutParamsButtonA, 85, 52);
|
|
||||||
setPercentilePosition(layoutParamsButtonB, 92, 47);
|
|
||||||
setPercentilePosition(layoutParamsButtonX, 85, 40);
|
|
||||||
setPercentilePosition(layoutParamsButtonY, 92, 35);
|
|
||||||
|
|
||||||
setPercentilePosition(layoutParamsButtonLT, 95, 68);
|
|
||||||
setPercentilePosition(layoutParamsButtonRT, 95, 80);
|
|
||||||
|
|
||||||
setPercentilePosition(layoutParamsButtonLB, 85, 28);
|
|
||||||
setPercentilePosition(layoutParamsButtonRB, 92, 23);
|
|
||||||
|
|
||||||
setPercentilePosition(layoutParamsButtonSelect, 43, 94);
|
|
||||||
setPercentilePosition(layoutParamsButtonStart, 57, 94);
|
|
||||||
|
|
||||||
setPercentilePosition(layoutParamsButtonConfigure, 93, 7);
|
|
||||||
|
|
||||||
relative_layout.addView(digitalPad, layoutParamsDPad);
|
|
||||||
|
|
||||||
relative_layout.addView(stick, layoutParamsStick);
|
|
||||||
relative_layout.addView(stick2, layoutParamsStick2);
|
|
||||||
|
|
||||||
relative_layout.addView(buttonA, layoutParamsButtonA);
|
|
||||||
relative_layout.addView(buttonB, layoutParamsButtonB);
|
|
||||||
relative_layout.addView(buttonX, layoutParamsButtonX);
|
|
||||||
relative_layout.addView(buttonY, layoutParamsButtonY);
|
|
||||||
relative_layout.addView(buttonLT, layoutParamsButtonLT);
|
|
||||||
relative_layout.addView(buttonRT, layoutParamsButtonRT);
|
|
||||||
relative_layout.addView(buttonLB, layoutParamsButtonLB);
|
|
||||||
relative_layout.addView(buttonRB, layoutParamsButtonRB);
|
|
||||||
|
|
||||||
relative_layout.addView(buttonSelect, layoutParamsButtonSelect);
|
|
||||||
relative_layout.addView(buttonStart, layoutParamsButtonStart);
|
|
||||||
|
|
||||||
relative_layout.addView(buttonConfigure, layoutParamsButtonConfigure);
|
|
||||||
}
|
|
||||||
|
|
||||||
private DigitalButton createDigitalButton(String text, final int key, Context context)
|
|
||||||
{
|
|
||||||
DigitalButton button = new DigitalButton(1, context);
|
|
||||||
button.setText(text);
|
|
||||||
button.addDigitalButtonListener(new DigitalButton.DigitalButtonListener()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void onClick()
|
|
||||||
{
|
|
||||||
inputMap |= key;
|
|
||||||
sendControllerInputPacket();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onLongClick()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onRelease()
|
|
||||||
{
|
|
||||||
inputMap &= ~key;
|
|
||||||
sendControllerInputPacket();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return button;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendControllerInputPacket()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_DBG("INPUT_MAP + " + inputMap);
|
|
||||||
_DBG("LEFT_TRIGGER " + leftTrigger);
|
|
||||||
_DBG("RIGHT_TRIGGER " + rightTrigger);
|
|
||||||
_DBG("LEFT STICK X: " + leftStickX + " Y: " + leftStickY);
|
|
||||||
_DBG("RIGHT STICK X: " + rightStickX + " Y: " + rightStickY);
|
|
||||||
_DBG("RIGHT STICK X: " + rightStickX + " Y: " + rightStickY);
|
|
||||||
|
|
||||||
if (connection != null)
|
|
||||||
{
|
|
||||||
connection.sendControllerInput(inputMap, leftTrigger, rightTrigger,
|
|
||||||
leftStickX, leftStickY, rightStickX, rightStickY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,43 +0,0 @@
|
|||||||
package com.limelight.binding.input.virtual_controller;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.Window;
|
|
||||||
import android.view.WindowManager;
|
|
||||||
import android.widget.FrameLayout;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import com.limelight.R;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Karim Mreisi on 22.01.2015.
|
|
||||||
*/
|
|
||||||
public class VirtualControllerConfiguration extends Activity
|
|
||||||
{
|
|
||||||
VirtualController virtualController;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState)
|
|
||||||
{
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
|
|
||||||
// We don't want a title bar
|
|
||||||
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
|
||||||
|
|
||||||
// Full-screen and don't let the display go off
|
|
||||||
getWindow().addFlags(
|
|
||||||
WindowManager.LayoutParams.FLAG_FULLSCREEN |
|
|
||||||
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
|
||||||
|
|
||||||
// Inflate the content
|
|
||||||
setContentView(R.layout.activity_configure_virtual_controller);
|
|
||||||
|
|
||||||
FrameLayout frameLayout =
|
|
||||||
(FrameLayout) findViewById(R.id.configure_virtual_controller_frameLayout);
|
|
||||||
|
|
||||||
// start with configuration constructor
|
|
||||||
virtualController = new VirtualController(null, frameLayout, this);
|
|
||||||
|
|
||||||
Toast.makeText(getApplicationContext(), "Not implemented yet!", Toast.LENGTH_SHORT).show();
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,269 @@
|
|||||||
|
/**
|
||||||
|
* Created by Karim Mreisi.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.limelight.binding.input.virtual_controller;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
import android.util.DisplayMetrics;
|
||||||
|
|
||||||
|
import com.limelight.nvstream.input.ControllerPacket;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class VirtualControllerConfigurationLoader {
|
||||||
|
private static final String PROFILE_PATH = "profiles";
|
||||||
|
private static int getPercent(
|
||||||
|
int percent,
|
||||||
|
int total) {
|
||||||
|
return (int) (((float) total / (float) 100) * (float) percent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DigitalPad createDigitalPad(
|
||||||
|
final VirtualController controller,
|
||||||
|
final Context context) {
|
||||||
|
|
||||||
|
DigitalPad digitalPad = new DigitalPad(controller, context);
|
||||||
|
digitalPad.addDigitalPadListener(new DigitalPad.DigitalPadListener() {
|
||||||
|
@Override
|
||||||
|
public void onDirectionChange(int direction) {
|
||||||
|
VirtualController.ControllerInputContext inputContext =
|
||||||
|
controller.getControllerInputContext();
|
||||||
|
|
||||||
|
if (direction == DigitalPad.DIGITAL_PAD_DIRECTION_NO_DIRECTION) {
|
||||||
|
inputContext.inputMap &= ~ControllerPacket.LEFT_FLAG;
|
||||||
|
inputContext.inputMap &= ~ControllerPacket.RIGHT_FLAG;
|
||||||
|
inputContext.inputMap &= ~ControllerPacket.UP_FLAG;
|
||||||
|
inputContext.inputMap &= ~ControllerPacket.DOWN_FLAG;
|
||||||
|
|
||||||
|
controller.sendControllerInputContext();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((direction & DigitalPad.DIGITAL_PAD_DIRECTION_LEFT) > 0) {
|
||||||
|
inputContext.inputMap |= ControllerPacket.LEFT_FLAG;
|
||||||
|
}
|
||||||
|
if ((direction & DigitalPad.DIGITAL_PAD_DIRECTION_RIGHT) > 0) {
|
||||||
|
inputContext.inputMap |= ControllerPacket.RIGHT_FLAG;
|
||||||
|
}
|
||||||
|
if ((direction & DigitalPad.DIGITAL_PAD_DIRECTION_UP) > 0) {
|
||||||
|
inputContext.inputMap |= ControllerPacket.UP_FLAG;
|
||||||
|
}
|
||||||
|
if ((direction & DigitalPad.DIGITAL_PAD_DIRECTION_DOWN) > 0) {
|
||||||
|
inputContext.inputMap |= ControllerPacket.DOWN_FLAG;
|
||||||
|
}
|
||||||
|
controller.sendControllerInputContext();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return digitalPad;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DigitalButton createDigitalButton(
|
||||||
|
final int keyShort,
|
||||||
|
final int keyLong,
|
||||||
|
final int layer,
|
||||||
|
final String text,
|
||||||
|
final int icon,
|
||||||
|
final VirtualController controller,
|
||||||
|
final Context context) {
|
||||||
|
DigitalButton button = new DigitalButton(controller, layer, context);
|
||||||
|
button.setText(text);
|
||||||
|
button.setIcon(icon);
|
||||||
|
|
||||||
|
button.addDigitalButtonListener(new DigitalButton.DigitalButtonListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick() {
|
||||||
|
VirtualController.ControllerInputContext inputContext =
|
||||||
|
controller.getControllerInputContext();
|
||||||
|
inputContext.inputMap |= keyShort;
|
||||||
|
|
||||||
|
controller.sendControllerInputContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLongClick() {
|
||||||
|
VirtualController.ControllerInputContext inputContext =
|
||||||
|
controller.getControllerInputContext();
|
||||||
|
inputContext.inputMap |= keyLong;
|
||||||
|
|
||||||
|
controller.sendControllerInputContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRelease() {
|
||||||
|
VirtualController.ControllerInputContext inputContext =
|
||||||
|
controller.getControllerInputContext();
|
||||||
|
inputContext.inputMap &= ~keyShort;
|
||||||
|
inputContext.inputMap &= ~keyLong;
|
||||||
|
|
||||||
|
controller.sendControllerInputContext();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DigitalButton createLeftTrigger(
|
||||||
|
final int layer,
|
||||||
|
final String text,
|
||||||
|
final int icon,
|
||||||
|
final VirtualController controller,
|
||||||
|
final Context context) {
|
||||||
|
LeftTrigger button = new LeftTrigger(controller, layer, context);
|
||||||
|
button.setText(text);
|
||||||
|
button.setIcon(icon);
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DigitalButton createRightTrigger(
|
||||||
|
final int layer,
|
||||||
|
final String text,
|
||||||
|
final int icon,
|
||||||
|
final VirtualController controller,
|
||||||
|
final Context context) {
|
||||||
|
RightTrigger button = new RightTrigger(controller, layer, context);
|
||||||
|
button.setText(text);
|
||||||
|
button.setIcon(icon);
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static AnalogStick createLeftStick(
|
||||||
|
final VirtualController controller,
|
||||||
|
final Context context) {
|
||||||
|
return new LeftAnalogStick(controller, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static AnalogStick createRightStick(
|
||||||
|
final VirtualController controller,
|
||||||
|
final Context context) {
|
||||||
|
return new RightAnalogStick(controller, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void createDefaultLayout(final VirtualController controller, final Context context) {
|
||||||
|
|
||||||
|
DisplayMetrics screen = context.getResources().getDisplayMetrics();
|
||||||
|
|
||||||
|
controller.addElement(createDigitalPad(controller, context),
|
||||||
|
getPercent(5, screen.widthPixels),
|
||||||
|
getPercent(10, screen.heightPixels),
|
||||||
|
getPercent(30, screen.widthPixels),
|
||||||
|
getPercent(40, screen.heightPixels)
|
||||||
|
);
|
||||||
|
|
||||||
|
controller.addElement(createDigitalButton(
|
||||||
|
ControllerPacket.A_FLAG, 0, 1, "A", -1, controller, context),
|
||||||
|
getPercent(75, screen.widthPixels),
|
||||||
|
getPercent(40, screen.heightPixels),
|
||||||
|
getPercent(10, screen.widthPixels),
|
||||||
|
getPercent(10, screen.heightPixels)
|
||||||
|
);
|
||||||
|
|
||||||
|
controller.addElement(createDigitalButton(
|
||||||
|
ControllerPacket.B_FLAG, 0, 1, "B", -1, controller, context),
|
||||||
|
getPercent(85, screen.widthPixels),
|
||||||
|
getPercent(30, screen.heightPixels),
|
||||||
|
getPercent(10, screen.widthPixels),
|
||||||
|
getPercent(10, screen.heightPixels)
|
||||||
|
);
|
||||||
|
|
||||||
|
controller.addElement(createDigitalButton(
|
||||||
|
ControllerPacket.X_FLAG, 0, 1, "X", -1, controller, context),
|
||||||
|
getPercent(65, screen.widthPixels),
|
||||||
|
getPercent(30, screen.heightPixels),
|
||||||
|
getPercent(10, screen.widthPixels),
|
||||||
|
getPercent(10, screen.heightPixels)
|
||||||
|
);
|
||||||
|
|
||||||
|
controller.addElement(createDigitalButton(
|
||||||
|
ControllerPacket.Y_FLAG, 0, 1, "Y", -1, controller, context),
|
||||||
|
getPercent(75, screen.widthPixels),
|
||||||
|
getPercent(20, screen.heightPixels),
|
||||||
|
getPercent(10, screen.widthPixels),
|
||||||
|
getPercent(10, screen.heightPixels)
|
||||||
|
);
|
||||||
|
|
||||||
|
controller.addElement(createLeftTrigger(
|
||||||
|
0, "LT", -1, controller, context),
|
||||||
|
getPercent(65, screen.widthPixels),
|
||||||
|
getPercent(20, screen.heightPixels),
|
||||||
|
getPercent(10, screen.widthPixels),
|
||||||
|
getPercent(10, screen.heightPixels)
|
||||||
|
);
|
||||||
|
|
||||||
|
controller.addElement(createRightTrigger(
|
||||||
|
0, "RT", -1, controller, context),
|
||||||
|
getPercent(85, screen.widthPixels),
|
||||||
|
getPercent(20, screen.heightPixels),
|
||||||
|
getPercent(10, screen.widthPixels),
|
||||||
|
getPercent(10, screen.heightPixels)
|
||||||
|
);
|
||||||
|
|
||||||
|
controller.addElement(createLeftStick(controller, context),
|
||||||
|
getPercent(5, screen.widthPixels),
|
||||||
|
getPercent(50, screen.heightPixels),
|
||||||
|
getPercent(40, screen.widthPixels),
|
||||||
|
getPercent(50, screen.heightPixels)
|
||||||
|
);
|
||||||
|
|
||||||
|
controller.addElement(createRightStick(controller, context),
|
||||||
|
getPercent(55, screen.widthPixels),
|
||||||
|
getPercent(50, screen.heightPixels),
|
||||||
|
getPercent(40, screen.widthPixels),
|
||||||
|
getPercent(50, screen.heightPixels)
|
||||||
|
);
|
||||||
|
|
||||||
|
controller.addElement(createDigitalButton(
|
||||||
|
ControllerPacket.SPECIAL_BUTTON_FLAG, 0, 2, "SELECT", -1, controller, context),
|
||||||
|
getPercent(40, screen.widthPixels),
|
||||||
|
getPercent(90, screen.heightPixels),
|
||||||
|
getPercent(10, screen.widthPixels),
|
||||||
|
getPercent(10, screen.heightPixels)
|
||||||
|
);
|
||||||
|
|
||||||
|
controller.addElement(createDigitalButton(
|
||||||
|
ControllerPacket.PLAY_FLAG, 0, 3, "PLAY", -1, controller, context),
|
||||||
|
getPercent(50, screen.widthPixels),
|
||||||
|
getPercent(90, screen.heightPixels),
|
||||||
|
getPercent(10, screen.widthPixels),
|
||||||
|
getPercent(10, screen.heightPixels)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
NOT IMPLEMENTED YET,
|
||||||
|
this should later be used to store and load a profile for the virtual controller
|
||||||
|
public static void saveProfile(final String name,
|
||||||
|
final VirtualController controller,
|
||||||
|
final Context context) {
|
||||||
|
|
||||||
|
SharedPreferences preferences = context.getSharedPreferences(PROFILE_PATH + "/" +
|
||||||
|
name, Activity.MODE_PRIVATE);
|
||||||
|
|
||||||
|
JSONArray elementConfigurations = new JSONArray();
|
||||||
|
for (VirtualControllerElement element : controller.getElements()) {
|
||||||
|
JSONObject elementConfiguration = new JSONObject();
|
||||||
|
try {
|
||||||
|
elementConfiguration.put("TYPE", element.getClass().getName());
|
||||||
|
elementConfiguration.put("CONFIGURATION", element.getConfiguration());
|
||||||
|
elementConfigurations.put(elementConfiguration);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SharedPreferences.Editor editor= preferences.edit();
|
||||||
|
editor.putString("ELEMENTS", elementConfigurations.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void loadFromPreferences(final VirtualController controller) {
|
||||||
|
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
@ -1,45 +1,280 @@
|
|||||||
|
/**
|
||||||
|
* Created by Karim Mreisi.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.limelight.binding.input.virtual_controller;
|
package com.limelight.binding.input.virtual_controller;
|
||||||
|
|
||||||
|
import android.app.AlertDialog;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.widget.RelativeLayout;
|
||||||
|
|
||||||
/**
|
import org.json.JSONObject;
|
||||||
* Created by Karim on 27.01.2015.
|
|
||||||
*/
|
//import yuku.ambilwarna.AmbilWarnaDialog;
|
||||||
public abstract class VirtualControllerElement extends View
|
|
||||||
{
|
public abstract class VirtualControllerElement extends View {
|
||||||
protected static boolean _PRINT_DEBUG_INFORMATION = false;
|
protected static boolean _PRINT_DEBUG_INFORMATION = false;
|
||||||
|
|
||||||
|
protected VirtualController virtualController;
|
||||||
|
|
||||||
protected int normalColor = 0xF0888888;
|
protected int normalColor = 0xF0888888;
|
||||||
protected int pressedColor = 0xF00000FF;
|
protected int pressedColor = 0xF00000FF;
|
||||||
|
|
||||||
protected VirtualControllerElement(Context context)
|
protected int startSize_x;
|
||||||
{
|
protected int startSize_y;
|
||||||
super(context);
|
|
||||||
|
float position_pressed_x = 0;
|
||||||
|
float position_pressed_y = 0;
|
||||||
|
|
||||||
|
private enum Mode {
|
||||||
|
Normal,
|
||||||
|
Resize,
|
||||||
|
Move
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static final void _DBG(String text)
|
private Mode currentMode = Mode.Normal;
|
||||||
{
|
|
||||||
if (_PRINT_DEBUG_INFORMATION)
|
protected VirtualControllerElement(VirtualController controller, Context context) {
|
||||||
{
|
super(context);
|
||||||
|
|
||||||
|
this.virtualController = controller;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void moveElement(int pressed_x, int pressed_y, int x, int y) {
|
||||||
|
int newPos_x = (int)getX() + x - pressed_x;
|
||||||
|
int newPos_y = (int)getY() + y - pressed_y;
|
||||||
|
|
||||||
|
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) getLayoutParams();
|
||||||
|
|
||||||
|
layoutParams.leftMargin = newPos_x > 0 ? newPos_x : 0;
|
||||||
|
layoutParams.topMargin = newPos_y > 0 ? newPos_y : 0;
|
||||||
|
layoutParams.rightMargin = 0;
|
||||||
|
layoutParams.bottomMargin = 0;
|
||||||
|
|
||||||
|
requestLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void resizeElement(int pressed_x, int pressed_y, int width, int height) {
|
||||||
|
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) getLayoutParams();
|
||||||
|
|
||||||
|
int newHeight = height + (startSize_y - pressed_y);
|
||||||
|
int newWidth = width + (startSize_x - pressed_x);
|
||||||
|
|
||||||
|
layoutParams.height = newHeight > 20 ? newHeight : 20;
|
||||||
|
layoutParams.width = newWidth > 20 ? newWidth : 20;
|
||||||
|
|
||||||
|
requestLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDraw(Canvas canvas) {
|
||||||
|
if (virtualController.getControllerMode() == VirtualController.ControllerMode.
|
||||||
|
Configuration) {
|
||||||
|
Paint paint = new Paint();
|
||||||
|
|
||||||
|
paint.setColor(pressedColor);
|
||||||
|
paint.setStrokeWidth(3);
|
||||||
|
paint.setStyle(Paint.Style.STROKE);
|
||||||
|
|
||||||
|
canvas.drawRect(0, 0,
|
||||||
|
getWidth(), getHeight(),
|
||||||
|
paint);
|
||||||
|
}
|
||||||
|
|
||||||
|
onElementDraw(canvas);
|
||||||
|
|
||||||
|
super.onDraw(canvas);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
protected void actionShowNormalColorChooser() {
|
||||||
|
AmbilWarnaDialog colorDialog = new AmbilWarnaDialog(getContext(), normalColor, true, new AmbilWarnaDialog.OnAmbilWarnaListener() {
|
||||||
|
@Override
|
||||||
|
public void onCancel(AmbilWarnaDialog dialog)
|
||||||
|
{}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onOk(AmbilWarnaDialog dialog, int color) {
|
||||||
|
normalColor = color;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
colorDialog.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void actionShowPressedColorChooser() {
|
||||||
|
AmbilWarnaDialog colorDialog = new AmbilWarnaDialog(getContext(), normalColor, true, new AmbilWarnaDialog.OnAmbilWarnaListener() {
|
||||||
|
@Override
|
||||||
|
public void onCancel(AmbilWarnaDialog dialog) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onOk(AmbilWarnaDialog dialog, int color) {
|
||||||
|
pressedColor = color;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
colorDialog.show();
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
protected void actionEnableMove() {
|
||||||
|
currentMode = Mode.Move;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void actionEnableResize() {
|
||||||
|
currentMode = Mode.Resize;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void actionCancel() {
|
||||||
|
currentMode = Mode.Normal;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void showConfigurationDialog() {
|
||||||
|
try {
|
||||||
|
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(getContext());
|
||||||
|
|
||||||
|
alertBuilder.setTitle("Configuration");
|
||||||
|
|
||||||
|
CharSequence functions[] = new CharSequence[]{
|
||||||
|
"Move",
|
||||||
|
"Resize",
|
||||||
|
/*election
|
||||||
|
"Set n
|
||||||
|
Disable color sormal color",
|
||||||
|
"Set pressed color",
|
||||||
|
*/
|
||||||
|
"Cancel"
|
||||||
|
};
|
||||||
|
|
||||||
|
alertBuilder.setItems(functions, new DialogInterface.OnClickListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
switch (which) {
|
||||||
|
case 0: { // move
|
||||||
|
actionEnableMove();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1: { // resize
|
||||||
|
actionEnableResize();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
case 2: { // set default color
|
||||||
|
actionShowNormalColorChooser();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3: { // set pressed color
|
||||||
|
actionShowPressedColorChooser();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
default: { // cancel
|
||||||
|
actionCancel();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
AlertDialog alert = alertBuilder.create();
|
||||||
|
// show menu
|
||||||
|
alert.show();
|
||||||
|
}catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onTouchEvent(MotionEvent event) {
|
||||||
|
if (virtualController.getControllerMode() == VirtualController.ControllerMode.Active) {
|
||||||
|
return onElementTouchEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (event.getActionMasked()) {
|
||||||
|
case MotionEvent.ACTION_DOWN:
|
||||||
|
case MotionEvent.ACTION_POINTER_DOWN: {
|
||||||
|
position_pressed_x = event.getX();
|
||||||
|
position_pressed_y = event.getY();
|
||||||
|
startSize_x = getWidth();
|
||||||
|
startSize_y = getHeight();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case MotionEvent.ACTION_MOVE: {
|
||||||
|
switch (currentMode) {
|
||||||
|
case Move: {
|
||||||
|
moveElement(
|
||||||
|
(int) position_pressed_x,
|
||||||
|
(int) position_pressed_y,
|
||||||
|
(int) event.getX(),
|
||||||
|
(int) event.getY());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Resize: {
|
||||||
|
resizeElement(
|
||||||
|
(int) position_pressed_x,
|
||||||
|
(int) position_pressed_y,
|
||||||
|
(int) event.getX(),
|
||||||
|
(int) event.getY());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Normal: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case MotionEvent.ACTION_CANCEL:
|
||||||
|
case MotionEvent.ACTION_UP:
|
||||||
|
case MotionEvent.ACTION_POINTER_UP: {
|
||||||
|
currentMode = Mode.Normal;
|
||||||
|
showConfigurationDialog();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract protected void onElementDraw(Canvas canvas);
|
||||||
|
abstract public boolean onElementTouchEvent(MotionEvent event);
|
||||||
|
|
||||||
|
protected static final void _DBG(String text) {
|
||||||
|
if (_PRINT_DEBUG_INFORMATION) {
|
||||||
System.out.println(text);
|
System.out.println(text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setColors(int normalColor, int pressedColor)
|
public void setColors(int normalColor, int pressedColor) {
|
||||||
{
|
|
||||||
this.normalColor = normalColor;
|
this.normalColor = normalColor;
|
||||||
this.pressedColor = pressedColor;
|
this.pressedColor = pressedColor;
|
||||||
|
|
||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final float getPercent(float value, float percent)
|
protected final float getPercent(float value, float percent) {
|
||||||
{
|
|
||||||
return value / 100 * percent;
|
return value / 100 * percent;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final int getCorrectWidth()
|
protected final int getCorrectWidth() {
|
||||||
{
|
|
||||||
return getWidth() > getHeight() ? getHeight() : getWidth();
|
return getWidth() > getHeight() ? getHeight() : getWidth();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
public JSONObject getConfiguration () {
|
||||||
|
JSONObject configuration = new JSONObject();
|
||||||
|
return configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadConfiguration (JSONObject configuration) {
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
@ -1,29 +0,0 @@
|
|||||||
package com.limelight.binding.input.virtual_controller;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.Window;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import com.limelight.R;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Karim on 26.01.2015.
|
|
||||||
*/
|
|
||||||
public class VirtualControllerSettings extends Activity
|
|
||||||
{
|
|
||||||
private VirtualController controller = null;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState)
|
|
||||||
{
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
// We don't want a title bar
|
|
||||||
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
|
||||||
|
|
||||||
// Inflate the content
|
|
||||||
setContentView(R.layout.activity_virtual_controller_settings);
|
|
||||||
|
|
||||||
Toast.makeText(getApplicationContext(), "Not implemented yet!", Toast.LENGTH_SHORT).show();
|
|
||||||
}
|
|
||||||
}
|
|
@ -188,7 +188,6 @@ public class PreferenceConfiguration {
|
|||||||
config.multiController = prefs.getBoolean(MULTI_CONTROLLER_PREF_STRING, DEFAULT_MULTI_CONTROLLER);
|
config.multiController = prefs.getBoolean(MULTI_CONTROLLER_PREF_STRING, DEFAULT_MULTI_CONTROLLER);
|
||||||
config.enable51Surround = prefs.getBoolean(ENABLE_51_SURROUND_PREF_STRING, DEFAULT_ENABLE_51_SURROUND);
|
config.enable51Surround = prefs.getBoolean(ENABLE_51_SURROUND_PREF_STRING, DEFAULT_ENABLE_51_SURROUND);
|
||||||
config.usbDriver = prefs.getBoolean(USB_DRIVER_PREF_SRING, DEFAULT_USB_DRIVER);
|
config.usbDriver = prefs.getBoolean(USB_DRIVER_PREF_SRING, DEFAULT_USB_DRIVER);
|
||||||
|
|
||||||
config.virtualController_enable = prefs.getBoolean(VIRTUAL_CONTROLLER_ENABLE, VIRTUAL_CONTROLLER_ENABLE_DEFAULT);
|
config.virtualController_enable = prefs.getBoolean(VIRTUAL_CONTROLLER_ENABLE, VIRTUAL_CONTROLLER_ENABLE_DEFAULT);
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
|
@ -11,8 +11,6 @@ import android.preference.PreferenceManager;
|
|||||||
|
|
||||||
import com.limelight.PcView;
|
import com.limelight.PcView;
|
||||||
import com.limelight.R;
|
import com.limelight.R;
|
||||||
import com.limelight.binding.input.virtual_controller.VirtualController;
|
|
||||||
import com.limelight.binding.input.virtual_controller.VirtualControllerConfiguration;
|
|
||||||
import com.limelight.utils.UiHelper;
|
import com.limelight.utils.UiHelper;
|
||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
@ -82,19 +80,6 @@ public class StreamSettings extends Activity {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Preference siteVirtualControllerButton = (Preference)findPreference("button_open_virtual_controller_configuration");
|
|
||||||
siteVirtualControllerButton.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public boolean onPreferenceClick(Preference arg0)
|
|
||||||
{
|
|
||||||
Intent virtualControllerConfiguration = new Intent(getActivity(), VirtualControllerConfiguration.class);
|
|
||||||
startActivity(virtualControllerConfiguration);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,11 @@
|
|||||||
android:title="@string/title_checkbox_xb1_driver"
|
android:title="@string/title_checkbox_xb1_driver"
|
||||||
android:summary="@string/summary_checkbox_xb1_driver"
|
android:summary="@string/summary_checkbox_xb1_driver"
|
||||||
android:defaultValue="true" />
|
android:defaultValue="true" />
|
||||||
|
<CheckBoxPreference
|
||||||
|
android:key="virtual_controller_checkbox_enable"
|
||||||
|
android:title="Enable virtual onscreen controller"
|
||||||
|
android:summary="Show virtual controller overlay on game screen"
|
||||||
|
android:defaultValue="true"/>
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
<PreferenceCategory android:title="@string/category_host_settings">
|
<PreferenceCategory android:title="@string/category_host_settings">
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
@ -90,15 +95,4 @@
|
|||||||
android:summary="@string/summary_video_format"
|
android:summary="@string/summary_video_format"
|
||||||
android:defaultValue="auto" />
|
android:defaultValue="auto" />
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
<PreferenceCategory android:title="Virtual Controller">
|
|
||||||
<CheckBoxPreference
|
|
||||||
android:key="virtual_controller_checkbox_enable"
|
|
||||||
android:title="Enable virtual controller"
|
|
||||||
android:summary="Show virtual controller overlay on game screen"
|
|
||||||
android:defaultValue="true"/>
|
|
||||||
<Preference android:title="Site virtual controller items"
|
|
||||||
android:key="button_open_virtual_controller_configuration"
|
|
||||||
android:summary="tbd"/>
|
|
||||||
</PreferenceCategory>
|
|
||||||
|
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<module external.linked.project.id="limelight-android" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
|
<module external.linked.project.id="moonlight-new" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
|
||||||
<component name="FacetManager">
|
<component name="FacetManager">
|
||||||
<facet type="java-gradle" name="Java-Gradle">
|
<facet type="java-gradle" name="Java-Gradle">
|
||||||
<configuration>
|
<configuration>
|
Loading…
x
Reference in New Issue
Block a user