Floating on-screen joystick, which can be enabled in .cfg file

This commit is contained in:
pelya
2014-06-22 01:32:17 +03:00
parent f848fb6af0
commit 48ee3af455
7 changed files with 103 additions and 14 deletions

View File

@@ -16,9 +16,6 @@ Requested features, might never get implemented, see todo.txt for features that
- Show/hide screen controls with longpress on Text Edit button.
- Floating on-screen joystick - initially invisible, it appears when you touch the screen,
centered on your finger, then it slides with your finger if you bump the joystick edge.
- Export phone vibrator to SDL - interface is available in SDL 1.3.
- Control screen brightness with SDL_SetGamma().

View File

@@ -229,13 +229,18 @@ echo >> AndroidAppSettings.cfg
echo "# Force relative (laptop) mouse movement mode, useful when both on-screen keyboard and mouse are needed (y) or (n)" >> AndroidAppSettings.cfg
echo ForceRelativeMouseMode=$ForceRelativeMouseMode >> AndroidAppSettings.cfg
echo >> AndroidAppSettings.cfg
echo "# Application needs arrow keys (y) or (n), will show on-screen dpad/joystick (y) or (n)" >> AndroidAppSettings.cfg
echo "# Show on-screen dpad/joystick, that will act as arrow keys (y) or (n)" >> AndroidAppSettings.cfg
echo AppNeedsArrowKeys=$AppNeedsArrowKeys >> AndroidAppSettings.cfg
echo >> AndroidAppSettings.cfg
echo "# On-screen dpad/joystick will appear under finger when it touches the screen (y) or (n)" >> AndroidAppSettings.cfg
echo "# Joystick always follows finger, so moving mouse requires touching the screen with other finger" >> AndroidAppSettings.cfg
echo FloatingScreenJoystick=$FloatingScreenJoystick >> AndroidAppSettings.cfg
echo >> AndroidAppSettings.cfg
echo "# Application needs text input (y) or (n), enables button for text input on screen" >> AndroidAppSettings.cfg
echo AppNeedsTextInput=$AppNeedsTextInput >> AndroidAppSettings.cfg
echo >> AndroidAppSettings.cfg
echo "# Application uses joystick (y) or (n), the on-screen DPAD will be used as joystick 0 axes 0-1" >> AndroidAppSettings.cfg
echo "# This will disable AppNeedsArrowKeys option" >> AndroidAppSettings.cfg
echo AppUsesJoystick=$AppUsesJoystick >> AndroidAppSettings.cfg
echo >> AndroidAppSettings.cfg
echo "# Application uses second on-screen joystick, as SDL joystick 0 axes 2-3 (y)/(n)" >> AndroidAppSettings.cfg
@@ -532,6 +537,12 @@ else
AppNeedsArrowKeys=false
fi
if [ "$FloatingScreenJoystick" = "y" ] ; then
FloatingScreenJoystick=true
else
FloatingScreenJoystick=false
fi
if [ "$AppNeedsTextInput" = "y" ] ; then
AppNeedsTextInput=true
else
@@ -767,6 +778,7 @@ $SEDI "s/public static boolean ForceRelativeMouseMode = .*;/public static boolea
$SEDI "s/public static boolean ShowMouseCursor = .*;/public static boolean ShowMouseCursor = $ShowMouseCursor;/" project/src/Globals.java
$SEDI "s/public static boolean GenerateSubframeTouchEvents = .*;/public static boolean GenerateSubframeTouchEvents = $GenerateSubframeTouchEvents;/" project/src/Globals.java
$SEDI "s/public static boolean AppNeedsArrowKeys = .*;/public static boolean AppNeedsArrowKeys = $AppNeedsArrowKeys;/" project/src/Globals.java
$SEDI "s/public static boolean FloatingScreenJoystick = .*;/public static boolean FloatingScreenJoystick = $FloatingScreenJoystick;/" project/src/Globals.java
$SEDI "s/public static boolean AppNeedsTextInput = .*;/public static boolean AppNeedsTextInput = $AppNeedsTextInput;/" project/src/Globals.java
$SEDI "s/public static boolean AppUsesJoystick = .*;/public static boolean AppUsesJoystick = $AppUsesJoystick;/" project/src/Globals.java
$SEDI "s/public static boolean AppUsesSecondJoystick = .*;/public static boolean AppUsesSecondJoystick = $AppUsesSecondJoystick;/" project/src/Globals.java

View File

@@ -89,6 +89,7 @@ class Globals
public static int TouchscreenKeyboardDrawSize = 1;
public static int TouchscreenKeyboardTheme = 2;
public static int TouchscreenKeyboardTransparency = 2;
public static boolean FloatingScreenJoystick = false;
public static int AccelerometerSensitivity = 2;
public static int AccelerometerCenterPos = 2;
public static int TrackballDampening = 0;
@@ -130,7 +131,6 @@ class Globals
public static String DataDir = new String("");
public static boolean VideoLinearFilter = true;
public static boolean MultiThreadedVideo = false;
public static boolean BrokenLibCMessageShown = false;
public static boolean OuyaEmulation = false; // For debugging
public static boolean RedirectStdout = false; // For debugging

View File

@@ -159,7 +159,7 @@ class Settings
out.writeInt(Globals.OptionalDataDownload.length);
for(int i = 0; i < Globals.OptionalDataDownload.length; i++)
out.writeBoolean(Globals.OptionalDataDownload[i]);
out.writeBoolean(Globals.BrokenLibCMessageShown);
out.writeBoolean(false); // Unused
out.writeInt(Globals.TouchscreenKeyboardDrawSize);
out.writeInt(p.getApplicationVersion());
out.writeFloat(AccelerometerReader.gyro.x1);
@@ -177,6 +177,7 @@ class Settings
out.writeBoolean(Globals.MoveMouseWithGyroscope);
out.writeInt(Globals.MoveMouseWithGyroscopeSpeed);
out.writeBoolean(Globals.FingerHover);
out.writeBoolean(Globals.FloatingScreenJoystick);
out.close();
settingsLoaded = true;
@@ -346,7 +347,7 @@ class Settings
Globals.OptionalDataDownload = new boolean[settingsFile.readInt()];
for(int i = 0; i < Globals.OptionalDataDownload.length; i++)
Globals.OptionalDataDownload[i] = settingsFile.readBoolean();
Globals.BrokenLibCMessageShown = settingsFile.readBoolean();
settingsFile.readBoolean(); // Unused
Globals.TouchscreenKeyboardDrawSize = settingsFile.readInt();
int cfgVersion = settingsFile.readInt();
AccelerometerReader.gyro.x1 = settingsFile.readFloat();
@@ -364,6 +365,7 @@ class Settings
Globals.MoveMouseWithGyroscope = settingsFile.readBoolean();
Globals.MoveMouseWithGyroscopeSpeed = settingsFile.readInt();
Globals.FingerHover = settingsFile.readBoolean();
Globals.FloatingScreenJoystick = settingsFile.readBoolean();
settingsLoaded = true;
@@ -560,7 +562,8 @@ class Settings
nativeSetupScreenKeyboard( Globals.TouchscreenKeyboardSize,
Globals.TouchscreenKeyboardDrawSize,
Globals.TouchscreenKeyboardTheme,
Globals.TouchscreenKeyboardTransparency );
Globals.TouchscreenKeyboardTransparency,
Globals.FloatingScreenJoystick ? 1 : 0 );
SetupTouchscreenKeyboardGraphics(p);
for( int i = 0; i < Globals.RemapScreenKbKeycode.length; i++ )
nativeSetKeymapKeyScreenKb(i, SDL_Keys.values[Globals.RemapScreenKbKeycode[i]]);
@@ -844,7 +847,7 @@ class Settings
private static native void nativeSetCompatibilityHacks();
private static native void nativeSetVideoMultithreaded();
private static native void nativeSetVideoForceSoftwareMode();
private static native void nativeSetupScreenKeyboard(int size, int drawsize, int theme, int transparency);
private static native void nativeSetupScreenKeyboard(int size, int drawsize, int theme, int transparency, int floatingScreenJoystick);
private static native void nativeSetupScreenKeyboardButtons(byte[] img);
private static native void nativeInitKeymap();
private static native int nativeGetKeymapKey(int key);

View File

@@ -119,13 +119,18 @@ GenerateSubframeTouchEvents=n
# Force relative (laptop) mouse movement mode, useful when both on-screen keyboard and mouse are needed (y) or (n)
ForceRelativeMouseMode=n
# Application needs arrow keys (y) or (n), will show on-screen dpad/joystick (y) or (n)
# Show on-screen dpad/joystick, that will act as arrow keys (y) or (n)
AppNeedsArrowKeys=y
# On-screen dpad/joystick will appear under finger when it touches the screen (y) or (n)
# Joystick always follows finger, so moving mouse requires touching the screen with other finger
FloatingScreenJoystick=y
# Application needs text input (y) or (n), enables button for text input on screen
AppNeedsTextInput=y
# Application uses joystick (y) or (n), the on-screen DPAD will be used as joystick 0 axes 0-1
# This will disable AppNeedsArrowKeys option
AppUsesJoystick=y
# Application uses second on-screen joystick, as SDL joystick 0 axes 2-3 (y)/(n)
@@ -208,7 +213,7 @@ FirstStartMenuOptions='SettingsMenu.DummyMenu'
# Specify architectures to compile, 'all' or 'y' to compile for all architectures.
# Available architectures: armeabi armeabi-v7a armeabi-v7a-hard x86 mips
MultiABI='armeabi-v7a-hard x86 mips armeabi'
MultiABI='armeabi-v7a'
# Minimum amount of RAM application requires, in Mb, SDL will print warning to user if it's lower
AppMinimumRAM=0

View File

@@ -88,6 +88,7 @@ enum { MOUSE_POINTER_W = 32, MOUSE_POINTER_H = 32, MOUSE_POINTER_X = 5, MOUSE_PO
static int sunTheme = 0;
static int joystickTouchPoints[MAX_JOYSTICKS*2];
static int floatingScreenJoystick = 0;
static void R_DumpOpenGlState(void);
@@ -96,6 +97,39 @@ static inline int InsideRect(const SDL_Rect * r, int x, int y)
return ( x >= r->x && x <= r->x + r->w ) && ( y >= r->y && y <= r->y + r->h );
}
// Find the intersection of a line and a rectangle,
// where on of the line points and the center of rectangle
// are both at the coordinate [0,0].
// It returns the remaining line segment outside of the rectangle.
// Do not check for border condition, we check that the line point
// is outside of the rectangle in another function.
static inline void LineAndRectangleIntersection(
int lx, int ly, // Line point, that is outside of rectangle
int rw, int rh, // Rectangle dimensions
int *x, int *y)
{
if( abs(lx) * rh > abs(ly) * rw )
{
rw /= 2;
// Intersection at the left side
if( lx < -rw )
*x = lx + rw; // lx is negative
else //if( lx > rw ) // At the right side
*x = lx - rw; // lx is positive
*y = *x * ly / lx;
}
else
{
rh /= 2;
// At the top
if( ly < -rh )
*y = ly + rh; // ly is negative
else //if( ly > rh ) // At the right side
*y = ly - rh; // ly is positive
*x = *y * lx / ly;
}
}
static struct ScreenKbGlState_t
{
GLboolean texture2d;
@@ -360,7 +394,7 @@ unsigned SDL_ANDROID_processTouchscreenKeyboard(int x, int y, int action, int po
int i, j;
unsigned processed = 0;
int joyAmount = SDL_ANDROID_joysticksAmount;
if( joyAmount == 0 && arrows[0].w > 0 )
if( joyAmount == 0 && (arrows[0].w > 0 || floatingScreenJoystick) )
joyAmount = 1;
if( !touchscreenKeyboardShown )
@@ -424,6 +458,19 @@ unsigned SDL_ANDROID_processTouchscreenKeyboard(int x, int y, int action, int po
}
}
}
if( floatingScreenJoystick && !processed && pointerInButtonRect[BUTTON_ARROWS] == -1 )
{
// Center joystick under finger, do not send any events yet
SDL_ANDROID_SetScreenKeyboardButtonShown(SDL_ANDROID_SCREENKEYBOARD_BUTTON_DPAD, 1);
arrows[0].x = x - arrows[0].w / 2;
arrows[0].y = y - arrows[0].h / 2;
arrowsDraw[0] = arrowsExtended[0] = arrows[0];
processed |= 1<<BUTTON_ARROWS;
pointerInButtonRect[BUTTON_ARROWS] = pointerId;
joystickTouchPoints[0] = x;
joystickTouchPoints[1] = y;
}
}
else
if( action == MOUSE_UP )
@@ -449,6 +496,8 @@ unsigned SDL_ANDROID_processTouchscreenKeyboard(int x, int y, int action, int po
SDL_ANDROID_MainThreadPushKeyboardKey( SDL_RELEASED, SDL_KEY(RIGHT), 0 );
oldArrows = 0;
}
if( floatingScreenJoystick && j == 0 )
SDL_ANDROID_SetScreenKeyboardButtonShown(SDL_ANDROID_SCREENKEYBOARD_BUTTON_DPAD, 0);
}
}
for( i = 0; i < MAX_BUTTONS; i++ )
@@ -489,6 +538,16 @@ unsigned SDL_ANDROID_processTouchscreenKeyboard(int x, int y, int action, int po
if( pointerInButtonRect[BUTTON_ARROWS+j] == pointerId )
{
processed |= 1<<(BUTTON_ARROWS+j);
if( floatingScreenJoystick && j == 0 && ! InsideRect( &arrows[j], x, y ) )
{
int xx = 0, yy = 0;
// Move joystick back under finger
LineAndRectangleIntersection(x - (arrows[0].x + arrows[0].w / 2), y - (arrows[0].y + arrows[0].h / 2), arrows[0].w, arrows[0].h, &xx, &yy);
//__android_log_print(ANDROID_LOG_INFO, "libSDL", "Touch %4d:%4d dpad %4d:%4d:%4d:%4d move by %4d:%4d", x, y, pointerId, action);
arrows[0].x += xx;
arrows[0].y += yy;
arrowsDraw[0] = arrowsExtended[0] = arrows[0];
}
if( ! InsideRect( &arrowsExtended[j], x, y ) )
{
pointerInButtonRect[BUTTON_ARROWS+j] = -1;
@@ -584,7 +643,8 @@ void shrinkButtonRect(SDL_Rect s, SDL_Rect * d)
}
JNIEXPORT void JNICALL
JAVA_EXPORT_NAME(Settings_nativeSetupScreenKeyboard) ( JNIEnv* env, jobject thiz, jint size, jint drawsize, jint theme, jint _transparency )
JAVA_EXPORT_NAME(Settings_nativeSetupScreenKeyboard) ( JNIEnv* env, jobject thiz,
jint size, jint drawsize, jint theme, jint _transparency, jint _floatingScreenJoystick )
{
int i, ii;
int nbuttons1row, nbuttons2row;
@@ -675,6 +735,13 @@ JAVA_EXPORT_NAME(Settings_nativeSetupScreenKeyboard) ( JNIEnv* env, jobject thi
shrinkButtonRect(buttons[i], &buttonsDraw[i]);
for( i = 0; i < SDL_ANDROID_SCREENKEYBOARD_BUTTON_NUM; i++ )
SDL_ANDROID_GetScreenKeyboardButtonPos(i, &hiddenButtons[i]);
floatingScreenJoystick = _floatingScreenJoystick;
if( floatingScreenJoystick )
{
arrowsExtended[0] = arrows[0] = arrowsDraw[0];
SDL_ANDROID_SetScreenKeyboardButtonShown(SDL_ANDROID_SCREENKEYBOARD_BUTTON_DPAD, 0);
}
};
JNIEXPORT void JNICALL

View File

@@ -19,7 +19,12 @@ TODO, which will get actually done
- SDL: control mouse with right analog gamepad stick.
- SDL: user-configurable option to set screen orientation.
- SDL: user-configurable option to set screen orientation and BPP.
- SDL: floating on-screen joystick - initially invisible, it appears when you touch the screen,
centered on your finger, then it slides with your finger if you bump the joystick edge.
- SDL: option to disable immersive mode.
- OpenTTD: All menus in the scenario editor are out of the screen.