Android: Add support for cursor icons
This commit is contained in:
parent
169268ae20
commit
f5b5e00a01
|
@ -36,8 +36,6 @@
|
|||
#include "java_godot_wrapper.h"
|
||||
#include "os_android.h"
|
||||
|
||||
#include <android/input.h>
|
||||
|
||||
#if defined(VULKAN_ENABLED)
|
||||
#include "drivers/vulkan/rendering_device_vulkan.h"
|
||||
#include "platform/android/vulkan/vulkan_context_android.h"
|
||||
|
@ -51,7 +49,7 @@ DisplayServerAndroid *DisplayServerAndroid::get_singleton() {
|
|||
bool DisplayServerAndroid::has_feature(Feature p_feature) const {
|
||||
switch (p_feature) {
|
||||
//case FEATURE_CONSOLE_WINDOW:
|
||||
//case FEATURE_CURSOR_SHAPE:
|
||||
case FEATURE_CURSOR_SHAPE:
|
||||
//case FEATURE_CUSTOM_CURSOR_SHAPE:
|
||||
//case FEATURE_GLOBAL_MENU:
|
||||
//case FEATURE_HIDPI:
|
||||
|
@ -829,6 +827,12 @@ void DisplayServerAndroid::mouse_set_mode(MouseMode p_mode) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (p_mode == MouseMode::MOUSE_MODE_HIDDEN) {
|
||||
OS_Android::get_singleton()->get_godot_java()->get_godot_view()->set_pointer_icon(CURSOR_TYPE_NULL);
|
||||
} else {
|
||||
cursor_set_shape(cursor_shape);
|
||||
}
|
||||
|
||||
if (p_mode == MouseMode::MOUSE_MODE_CAPTURED) {
|
||||
OS_Android::get_singleton()->get_godot_java()->get_godot_view()->request_pointer_capture();
|
||||
} else {
|
||||
|
@ -870,3 +874,19 @@ int DisplayServerAndroid::_android_button_mask_to_godot_button_mask(int android_
|
|||
|
||||
return godot_button_mask;
|
||||
}
|
||||
|
||||
void DisplayServerAndroid::cursor_set_shape(DisplayServer::CursorShape p_shape) {
|
||||
if (cursor_shape == p_shape) {
|
||||
return;
|
||||
}
|
||||
|
||||
cursor_shape = p_shape;
|
||||
|
||||
if (mouse_mode == MouseMode::MOUSE_MODE_VISIBLE || mouse_mode == MouseMode::MOUSE_MODE_CONFINED) {
|
||||
OS_Android::get_singleton()->get_godot_java()->get_godot_view()->set_pointer_icon(android_cursors[cursor_shape]);
|
||||
}
|
||||
}
|
||||
|
||||
DisplayServer::CursorShape DisplayServerAndroid::cursor_get_shape() const {
|
||||
return cursor_shape;
|
||||
}
|
||||
|
|
|
@ -70,6 +70,28 @@ private:
|
|||
|
||||
int buttons_state;
|
||||
|
||||
// https://developer.android.com/reference/android/view/PointerIcon
|
||||
// mapping between Godot's cursor shape to Android's'
|
||||
int android_cursors[CURSOR_MAX] = {
|
||||
1000, //CURSOR_ARROW
|
||||
1008, //CURSOR_IBEAM
|
||||
1002, //CURSOR_POINTIN
|
||||
1007, //CURSOR_CROSS
|
||||
1004, //CURSOR_WAIT
|
||||
1004, //CURSOR_BUSY
|
||||
1021, //CURSOR_DRAG
|
||||
1021, //CURSOR_CAN_DRO
|
||||
1000, //CURSOR_FORBIDD (no corresponding icon in Android's icon so fallback to default)
|
||||
1015, //CURSOR_VSIZE
|
||||
1014, //CURSOR_HSIZE
|
||||
1017, //CURSOR_BDIAGSI
|
||||
1016, //CURSOR_FDIAGSI
|
||||
1020, //CURSOR_MOVE
|
||||
1015, //CURSOR_VSPLIT
|
||||
1014, //CURSOR_HSPLIT
|
||||
1003, //CURSOR_HELP
|
||||
};
|
||||
const int CURSOR_TYPE_NULL = 0;
|
||||
MouseMode mouse_mode;
|
||||
|
||||
bool keep_screen_on;
|
||||
|
@ -78,6 +100,8 @@ private:
|
|||
Point2 hover_prev_pos; // needed to calculate the relative position on hover events
|
||||
Point2 scroll_prev_pos; // needed to calculate the relative position on scroll events
|
||||
|
||||
CursorShape cursor_shape = CursorShape::CURSOR_ARROW;
|
||||
|
||||
#if defined(VULKAN_ENABLED)
|
||||
VulkanContextAndroid *context_vulkan;
|
||||
RenderingDeviceVulkan *rendering_device_vulkan;
|
||||
|
@ -180,6 +204,9 @@ public:
|
|||
void process_joy_event(JoypadEvent p_event);
|
||||
void process_key_event(int p_keycode, int p_scancode, int p_unicode_char, bool p_pressed);
|
||||
|
||||
virtual void cursor_set_shape(CursorShape p_shape);
|
||||
virtual CursorShape cursor_get_shape() const;
|
||||
|
||||
void mouse_set_mode(MouseMode p_mode);
|
||||
MouseMode mouse_get_mode() const;
|
||||
|
||||
|
|
|
@ -44,11 +44,15 @@ import android.annotation.SuppressLint;
|
|||
import android.content.Context;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.opengl.GLSurfaceView;
|
||||
import android.os.Build;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.PointerIcon;
|
||||
import android.view.SurfaceView;
|
||||
|
||||
import androidx.annotation.Keep;
|
||||
|
||||
/**
|
||||
* A simple GLSurfaceView sub-class that demonstrate how to perform
|
||||
* OpenGL ES 2.0 rendering into a GL Surface. Note the following important
|
||||
|
@ -72,6 +76,7 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView
|
|||
private final GodotInputHandler inputHandler;
|
||||
private final GestureDetector detector;
|
||||
private final GodotRenderer godotRenderer;
|
||||
private PointerIcon pointerIcon;
|
||||
|
||||
public GodotGLRenderView(Context context, Godot godot, XRMode xrMode, boolean p_use_32_bits,
|
||||
boolean p_use_debug_opengl) {
|
||||
|
@ -83,6 +88,9 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView
|
|||
this.inputHandler = new GodotInputHandler(this);
|
||||
this.detector = new GestureDetector(context, new GodotGestureHandler(this));
|
||||
this.godotRenderer = new GodotRenderer();
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
pointerIcon = PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_DEFAULT);
|
||||
}
|
||||
init(xrMode, false, 16, 0);
|
||||
}
|
||||
|
||||
|
@ -149,6 +157,21 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView
|
|||
return inputHandler.onGenericMotionEvent(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* called from JNI to change pointer icon
|
||||
*/
|
||||
@Keep
|
||||
public void setPointerIcon(int pointerType) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
pointerIcon = PointerIcon.getSystemIcon(getContext(), pointerType);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PointerIcon onResolvePointerIcon(MotionEvent me, int pointerIndex) {
|
||||
return pointerIcon;
|
||||
}
|
||||
|
||||
private void init(XRMode xrMode, boolean translucent, int depth, int stencil) {
|
||||
setPreserveEGLContextOnPause(true);
|
||||
setFocusableInTouchMode(true);
|
||||
|
|
|
@ -47,4 +47,6 @@ public interface GodotRenderView {
|
|||
abstract public void onBackPressed();
|
||||
|
||||
abstract public GodotInputHandler getInputHandler();
|
||||
|
||||
abstract public void setPointerIcon(int pointerType);
|
||||
}
|
||||
|
|
|
@ -37,17 +37,22 @@ import org.godotengine.godot.vulkan.VkSurfaceView;
|
|||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.InputDevice;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.PointerIcon;
|
||||
import android.view.SurfaceView;
|
||||
|
||||
import androidx.annotation.Keep;
|
||||
|
||||
public class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderView {
|
||||
private final Godot godot;
|
||||
private final GodotInputHandler mInputHandler;
|
||||
private final GestureDetector mGestureDetector;
|
||||
private final VkRenderer mRenderer;
|
||||
private PointerIcon pointerIcon;
|
||||
|
||||
public GodotVulkanRenderView(Context context, Godot godot) {
|
||||
super(context);
|
||||
|
@ -56,7 +61,9 @@ public class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderV
|
|||
mInputHandler = new GodotInputHandler(this);
|
||||
mGestureDetector = new GestureDetector(context, new GodotGestureHandler(this));
|
||||
mRenderer = new VkRenderer();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
pointerIcon = PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_DEFAULT);
|
||||
}
|
||||
setFocusableInTouchMode(true);
|
||||
startRenderer(mRenderer);
|
||||
}
|
||||
|
@ -124,6 +131,21 @@ public class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderV
|
|||
return mInputHandler.onGenericMotionEvent(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* called from JNI to change pointer icon
|
||||
*/
|
||||
@Keep
|
||||
public void setPointerIcon(int pointerType) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
pointerIcon = PointerIcon.getSystemIcon(getContext(), pointerType);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PointerIcon onResolvePointerIcon(MotionEvent me, int pointerIndex) {
|
||||
return pointerIcon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
|
|
@ -43,6 +43,7 @@ GodotJavaViewWrapper::GodotJavaViewWrapper(jobject godot_view) {
|
|||
if (android_get_device_api_level() >= __ANDROID_API_O__) {
|
||||
_request_pointer_capture = env->GetMethodID(_cls, "requestPointerCapture", "()V");
|
||||
_release_pointer_capture = env->GetMethodID(_cls, "releasePointerCapture", "()V");
|
||||
_set_pointer_icon = env->GetMethodID(_cls, "setPointerIcon", "(I)V");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,6 +65,15 @@ void GodotJavaViewWrapper::release_pointer_capture() {
|
|||
}
|
||||
}
|
||||
|
||||
void GodotJavaViewWrapper::set_pointer_icon(int pointer_type) {
|
||||
if (_set_pointer_icon != 0) {
|
||||
JNIEnv *env = get_jni_env();
|
||||
ERR_FAIL_COND(env == nullptr);
|
||||
|
||||
env->CallVoidMethod(_godot_view, _set_pointer_icon, pointer_type);
|
||||
}
|
||||
}
|
||||
|
||||
GodotJavaViewWrapper::~GodotJavaViewWrapper() {
|
||||
JNIEnv *env = get_jni_env();
|
||||
ERR_FAIL_COND(env == nullptr);
|
||||
|
|
|
@ -45,12 +45,14 @@ private:
|
|||
|
||||
jmethodID _request_pointer_capture = 0;
|
||||
jmethodID _release_pointer_capture = 0;
|
||||
jmethodID _set_pointer_icon = 0;
|
||||
|
||||
public:
|
||||
GodotJavaViewWrapper(jobject godot_view);
|
||||
|
||||
void request_pointer_capture();
|
||||
void release_pointer_capture();
|
||||
void set_pointer_icon(int pointer_type);
|
||||
|
||||
~GodotJavaViewWrapper();
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue