diff --git a/app/app.iml b/app/app.iml
index 4a3b7889..f7cfabed 100644
--- a/app/app.iml
+++ b/app/app.iml
@@ -8,10 +8,12 @@
-
-
-
-
+
+
+
+
+
+
@@ -21,22 +23,28 @@
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -51,13 +59,13 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index f0221cf3..1dcb1ae1 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -76,6 +76,12 @@
android:theme="@style/StreamTheme"
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection" >
+
+
diff --git a/app/src/main/java/com/limelight/Game.java b/app/src/main/java/com/limelight/Game.java
index 661d60d6..baabc55e 100644
--- a/app/src/main/java/com/limelight/Game.java
+++ b/app/src/main/java/com/limelight/Game.java
@@ -205,7 +205,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
{
FrameLayout frameLayout = (FrameLayout) findViewById(R.id.frameLayout);
- virtualController = new VirtualController(conn, frameLayout, getApplicationContext(), getWindowManager());
+ virtualController = new VirtualController(conn, frameLayout, getApplicationContext());
}
// The connection will be started when the surface gets created
diff --git a/app/src/main/java/com/limelight/binding/input/virtual_controller/AnalogStick.java b/app/src/main/java/com/limelight/binding/input/virtual_controller/AnalogStick.java
index 19abe5a0..024c4fe5 100644
--- a/app/src/main/java/com/limelight/binding/input/virtual_controller/AnalogStick.java
+++ b/app/src/main/java/com/limelight/binding/input/virtual_controller/AnalogStick.java
@@ -8,6 +8,7 @@ import android.view.MotionEvent;
import android.view.View;
import java.util.ArrayList;
+import java.util.Date;
import java.util.List;
/**
@@ -21,11 +22,20 @@ public class AnalogStick extends View
MOVED
}
+ private enum _CLICK_STATE
+ {
+ SINGLE,
+ DOUBLE
+ }
+
private static final boolean _PRINT_DEBUG_INFORMATION = false;
public interface AnalogStickListener
{
void onMovement(float x, float y);
+ void onClick();
+ void onRevoke();
+ void onDoubleClick();
}
public void addAnalogStickListener (AnalogStickListener listener)
@@ -46,8 +56,11 @@ public class AnalogStick extends View
}
}
- private int normalColor = 0xF0888888;
- private int pressedColor = 0xF00000FF;
+ private int normalColor = 0xF0888888;
+ private int pressedColor = 0xF00000FF;
+
+ private long timeoutDoubleClick = 250;
+ private long timeLastClick = 0;
float radius_complete = 0;
float radius_dead_zone = 0;
@@ -56,8 +69,10 @@ public class AnalogStick extends View
float position_stick_x = 0;
float position_stick_y = 0;
- boolean pressed = false;
+ boolean viewPressed = false;
+ boolean analogStickActive = false;
_STICK_STATE stick_state = _STICK_STATE.NO_MOVEMENT;
+ _CLICK_STATE click_state = _CLICK_STATE.SINGLE;
List listeners = new ArrayList();
OnTouchListener onTouchListener = null;
@@ -69,8 +84,10 @@ public class AnalogStick extends View
position_stick_x = getWidth() / 2;
position_stick_y = getHeight() / 2;
- stick_state = _STICK_STATE.NO_MOVEMENT;
- pressed = false;
+ stick_state = _STICK_STATE.NO_MOVEMENT;
+ click_state = _CLICK_STATE.SINGLE;
+ viewPressed = false;
+ analogStickActive = false;
}
@@ -125,16 +142,25 @@ public class AnalogStick extends View
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(getPercent(getCorrectWidth() / 2, 2));
- paint.setColor(normalColor);
+ // draw outer circle
+ if (!viewPressed || click_state == _CLICK_STATE.SINGLE)
+ {
+ paint.setColor(normalColor);
+ }
+ else
+ {
+ paint.setColor(pressedColor);
+ }
- // draw outer circle
- canvas.drawCircle(getWidth() / 2, getHeight() / 2, radius_complete, paint);
+ canvas.drawCircle(getWidth() / 2, getHeight() / 2, radius_complete, paint);
+
+ paint.setColor(normalColor);
// draw dead zone
canvas.drawCircle(getWidth() / 2, getHeight() / 2, radius_dead_zone, paint);
// draw stick depending on state (no movement, moved, active(out of dead zone))
- if (pressed)
+ if (analogStickActive)
{
switch (stick_state)
{
@@ -232,7 +258,41 @@ public class AnalogStick extends View
}
}
- private void updatePosition(float x, float 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(float x, float y)
{
float way_x = -(getWidth() / 2 - x);
float way_y = -(getHeight() / 2 - y);
@@ -282,33 +342,65 @@ public class AnalogStick extends View
}
// get masked (not specific to a pointer) action
- int action = event.getActionMasked();
+ int action = event.getActionMasked();
+ _CLICK_STATE lastClickState = click_state;
+ boolean wasPressed = analogStickActive;
switch (action)
{
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
+ {
+ viewPressed = true;
+ // check for double click
+ if (lastClickState == _CLICK_STATE.SINGLE && timeLastClick + timeoutDoubleClick > System.currentTimeMillis())
+ {
+ click_state = _CLICK_STATE.DOUBLE;
+
+ doubleClickActionCallback();
+ }
+ else
+ {
+ click_state = _CLICK_STATE.SINGLE;
+
+ clickActionCallback();
+ }
+
+ timeLastClick = System.currentTimeMillis();
+
+ break;
+ }
case MotionEvent.ACTION_MOVE:
- {
- pressed = true;
+ {
+ if (analogStickActive || timeLastClick + timeoutDoubleClick < System.currentTimeMillis())
+ {
+ analogStickActive = true;
+ }
break;
}
- default:
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_POINTER_UP:
{
- pressed = false;
+ analogStickActive = false;
+ viewPressed = false;
+
+ revokeActionCallback();
break;
}
}
- if (pressed)
+ if (analogStickActive)
{ // when is pressed calculate new positions (will trigger movement if necessary)
updatePosition(event.getX(), event.getY());
}
else
{ // no longer pressed reset movement
- moveActionCallback(0, 0);
+ if (wasPressed)
+ {
+ moveActionCallback(0, 0);
+ }
}
// to get view refreshed
diff --git a/app/src/main/java/com/limelight/binding/input/virtual_controller/DigitalButton.java b/app/src/main/java/com/limelight/binding/input/virtual_controller/DigitalButton.java
index fdd58995..05c8f86b 100644
--- a/app/src/main/java/com/limelight/binding/input/virtual_controller/DigitalButton.java
+++ b/app/src/main/java/com/limelight/binding/input/virtual_controller/DigitalButton.java
@@ -4,28 +4,44 @@ import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
+import android.graphics.drawable.Drawable;
import android.view.MotionEvent;
import android.view.View;
import java.util.ArrayList;
import java.util.List;
+import java.util.Timer;
+import java.util.TimerTask;
/**
* Created by Karim on 24.01.2015.
*/
public class DigitalButton extends View
{
+ private class TimerLongClickTimerTask extends TimerTask
+ {
+ @Override
+ public void run()
+ {
+ onLongClickCallback();
+ }
+ }
private static final boolean _PRINT_DEBUG_INFORMATION = false;
- private int normalColor = 0xF0888888;
- private int pressedColor = 0xF00000FF;
- private String text;
+ private int normalColor = 0xF0888888;
+ private int pressedColor = 0xF00000FF;
+ private String text = "";
+ private int icon = -1;
+
+ private long timerLongClickTimeout = 3000;
+ private Timer timerLongClick = null;
+ private TimerLongClickTimerTask longClickTimerTask = null;
public interface DigitalButtonListener
{
void onClick();
-
+ void onLongClick();
void onRelease();
}
@@ -72,6 +88,13 @@ public class DigitalButton extends View
invalidate();
}
+ public void setIcon(int id)
+ {
+ this.icon = id;
+
+ invalidate();
+ }
+
private float getPercent(float value, float percent)
{
return value / 100 * percent;
@@ -102,10 +125,19 @@ public class DigitalButton extends View
paint
);
- paint.setStyle(Paint.Style.FILL_AND_STROKE);
- canvas.drawText(text,
- getPercent(getWidth(), 50), getPercent(getHeight(), 73),
- paint);
+ if (icon != -1)
+ {
+ Drawable d = getResources().getDrawable(icon);
+ d.setBounds(5, 5, getWidth() - 5, getHeight() - 5);
+ d.draw(canvas);
+ }
+ else
+ {
+ paint.setStyle(Paint.Style.FILL_AND_STROKE);
+ canvas.drawText(text,
+ getPercent(getWidth(), 50), getPercent(getHeight(), 73),
+ paint);
+ }
super.onDraw(canvas);
}
@@ -119,6 +151,22 @@ public class DigitalButton extends View
{
listener.onClick();
}
+
+ timerLongClick = new Timer();
+ longClickTimerTask = new TimerLongClickTimerTask();
+
+ timerLongClick.schedule(longClickTimerTask, timerLongClickTimeout);
+ }
+
+ private void onLongClickCallback()
+ {
+ _DBG("long click");
+
+ // notify listeners
+ for (DigitalButtonListener listener : listeners)
+ {
+ listener.onLongClick();
+ }
}
private void onReleaseCallback()
@@ -130,6 +178,9 @@ public class DigitalButton extends View
{
listener.onRelease();
}
+
+ timerLongClick.cancel();
+ longClickTimerTask.cancel();
}
diff --git a/app/src/main/java/com/limelight/binding/input/virtual_controller/VirtualController.java b/app/src/main/java/com/limelight/binding/input/virtual_controller/VirtualController.java
index e6fd571d..8942c0ea 100644
--- a/app/src/main/java/com/limelight/binding/input/virtual_controller/VirtualController.java
+++ b/app/src/main/java/com/limelight/binding/input/virtual_controller/VirtualController.java
@@ -1,11 +1,16 @@
package com.limelight.binding.input.virtual_controller;
import android.content.Context;
+import android.content.Intent;
+import android.view.MenuInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.FrameLayout;
+import android.widget.PopupMenu;
import android.widget.RelativeLayout;
+import android.widget.Toast;
+import com.limelight.R;
import com.limelight.nvstream.NvConnection;
import com.limelight.nvstream.input.ControllerPacket;
@@ -37,7 +42,6 @@ public class VirtualController
private RelativeLayout.LayoutParams layoutParamsButtonStart = null;
private RelativeLayout.LayoutParams layoutParamsButtonSelect = null;
-// private RelativeLayout.LayoutParams layoutParamsButtonEscape = null;
private RelativeLayout.LayoutParams layoutParamsDPad = null;
@@ -50,12 +54,13 @@ public class VirtualController
private RelativeLayout.LayoutParams layoutParamsButtonLB = null;
private RelativeLayout.LayoutParams layoutParamsButtonRB = null;
- private RelativeLayout.LayoutParams layoutParamsParamsStick = null;
- private RelativeLayout.LayoutParams layoutParamsParamsStick2 = null;
+ private RelativeLayout.LayoutParams layoutParamsStick = null;
+ private RelativeLayout.LayoutParams layoutParamsStick2 = null;
+
+ private RelativeLayout.LayoutParams layoutParamsButtonConfigure = null;
private DigitalButton buttonStart = null;
private DigitalButton buttonSelect = null;
-// private DigitalButton buttonEscape = null;
private DigitalPad digitalPad = null;
@@ -71,6 +76,8 @@ public class VirtualController
private AnalogStick stick = null;
private AnalogStick stick2 = null;
+ private DigitalButton buttonConfigure = null;
+
NvConnection connection = null;
private int getPercentageV(int percent)
@@ -99,8 +106,8 @@ public class VirtualController
layoutParamsDPad = new RelativeLayout.LayoutParams(getPercentageV(30), getPercentageV(30));
- layoutParamsParamsStick = new RelativeLayout.LayoutParams(getPercentageV(40), getPercentageV(40));
- layoutParamsParamsStick2 = new RelativeLayout.LayoutParams(getPercentageV(40), getPercentageV(40));
+ 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));
@@ -115,10 +122,12 @@ public class VirtualController
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(layoutParamsParamsStick, 22, 78);
- setPercentilePosition(layoutParamsParamsStick2, 78, 78);
+ setPercentilePosition(layoutParamsStick, 22, 78);
+ setPercentilePosition(layoutParamsStick2, 78, 78);
setPercentilePosition(layoutParamsButtonA, 85, 52);
setPercentilePosition(layoutParamsButtonB, 92, 47);
@@ -134,11 +143,12 @@ public class VirtualController
setPercentilePosition(layoutParamsButtonSelect, 43, 94);
setPercentilePosition(layoutParamsButtonStart, 57, 94);
+ setPercentilePosition(layoutParamsButtonConfigure, 93, 7);
relative_layout.addView(digitalPad, layoutParamsDPad);
- relative_layout.addView(stick, layoutParamsParamsStick);
- relative_layout.addView(stick2, layoutParamsParamsStick2);
+ relative_layout.addView(stick, layoutParamsStick);
+ relative_layout.addView(stick2, layoutParamsStick2);
relative_layout.addView(buttonA, layoutParamsButtonA);
relative_layout.addView(buttonB, layoutParamsButtonB);
@@ -151,6 +161,8 @@ public class VirtualController
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)
@@ -164,6 +176,12 @@ public class VirtualController
sendControllerInputPacket();
}
+ @Override
+ public void onLongClick()
+ {
+
+ }
+
@Override
public void onRelease() {
inputMap &= ~key;
@@ -174,7 +192,7 @@ public class VirtualController
return button;
}
- public VirtualController(final NvConnection conn, FrameLayout layout, Context context, WindowManager window_manager)
+ public VirtualController(final NvConnection conn, FrameLayout layout, final Context context)
{
this.connection = conn;
frame_layout = layout;
@@ -253,6 +271,12 @@ public class VirtualController
sendControllerInputPacket();
}
+ @Override
+ public void onLongClick()
+ {
+
+ }
+
@Override
public void onRelease()
{
@@ -274,6 +298,12 @@ public class VirtualController
sendControllerInputPacket();
}
+ @Override
+ public void onLongClick()
+ {
+
+ }
+
@Override
public void onRelease()
{
@@ -299,6 +329,27 @@ public class VirtualController
_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);
@@ -313,11 +364,58 @@ public class VirtualController
_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(context);
+ buttonConfigure.setIcon(R.drawable.settings);
+ buttonConfigure.addDigitalButtonListener(new DigitalButton.DigitalButtonListener()
+ {
+ @Override
+ public void onClick() {
+
+ }
+
+ @Override
+ public void onLongClick()
+ {
+ Intent virtualControllerConfiguration = new Intent(context,VirtualControllerSettings.class);
+
+ virtualControllerConfiguration.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ context.startActivity(virtualControllerConfiguration);
+
+ }
+
+ @Override
+ public void onRelease() {
+
+ }
+ });
+
refreshLayout();
}
diff --git a/app/src/main/java/com/limelight/binding/input/virtual_controller/VirtualControllerConfiguration.java b/app/src/main/java/com/limelight/binding/input/virtual_controller/VirtualControllerConfiguration.java
index a1b41938..6d8ecbd9 100644
--- a/app/src/main/java/com/limelight/binding/input/virtual_controller/VirtualControllerConfiguration.java
+++ b/app/src/main/java/com/limelight/binding/input/virtual_controller/VirtualControllerConfiguration.java
@@ -37,7 +37,7 @@ public class VirtualControllerConfiguration extends Activity
FrameLayout frameLayout = (FrameLayout) findViewById(R.id.configure_virtual_controller_frameLayout);
// start with configuration constructor
- virtualController = new VirtualController(null, frameLayout, this, getWindowManager());
+ virtualController = new VirtualController(null, frameLayout, this);
Toast.makeText(getApplicationContext(), "Not implemented yet!", Toast.LENGTH_SHORT).show();
}
diff --git a/app/src/main/java/com/limelight/binding/input/virtual_controller/VirtualControllerSettings.java b/app/src/main/java/com/limelight/binding/input/virtual_controller/VirtualControllerSettings.java
new file mode 100644
index 00000000..3432b63e
--- /dev/null
+++ b/app/src/main/java/com/limelight/binding/input/virtual_controller/VirtualControllerSettings.java
@@ -0,0 +1,47 @@
+package com.limelight.binding.input.virtual_controller;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.MenuInflater;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+import android.widget.PopupMenu;
+import android.widget.Toast;
+
+import com.limelight.R;
+
+import org.apache.http.util.VersionInfo;
+
+/**
+ * Created by Karim on 26.01.2015.
+ */
+public class VirtualControllerSettings extends Activity
+{
+ private static VirtualController controller = null;
+ private static View view = null;
+
+ static void setController(VirtualController value)
+ {
+ controller = value;
+ }
+
+ static void setView(View value)
+ {
+ view = value;
+ }
+
+ @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();
+ }
+}
diff --git a/app/src/main/res/layout/activity_virtual_controller_settings.xml b/app/src/main/res/layout/activity_virtual_controller_settings.xml
new file mode 100644
index 00000000..f864ca91
--- /dev/null
+++ b/app/src/main/res/layout/activity_virtual_controller_settings.xml
@@ -0,0 +1,143 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file