Просмотр исходного кода

Merge pull request #82893 from m4gr3d/godot_android_lib_improvements

Cleanups and improvements to the Godot Android library api
Rémi Verschelde 1 год назад
Родитель
Сommit
1fe7f8a96c

+ 6 - 0
doc/classes/ProjectSettings.xml

@@ -1309,6 +1309,12 @@
 		<member name="input_devices/pen_tablet/driver.windows" type="String" setter="" getter="">
 			Override for [member input_devices/pen_tablet/driver] on Windows.
 		</member>
+		<member name="input_devices/pointing/android/enable_long_press_as_right_click" type="bool" setter="" getter="" default="false">
+			If [code]true[/code], long press events on an Android touchscreen are transformed into right click events.
+		</member>
+		<member name="input_devices/pointing/android/enable_pan_and_scale_gestures" type="bool" setter="" getter="" default="false">
+			If [code]true[/code], multi-touch pan and scale gestures are enabled on Android devices.
+		</member>
 		<member name="input_devices/pointing/emulate_mouse_from_touch" type="bool" setter="" getter="" default="true">
 			If [code]true[/code], sends mouse input events when tapping or swiping on the touchscreen.
 		</member>

+ 3 - 0
main/main.cpp

@@ -2565,6 +2565,9 @@ Error Main::setup2() {
 		id->set_emulate_mouse_from_touch(bool(GLOBAL_DEF_BASIC("input_devices/pointing/emulate_mouse_from_touch", true)));
 	}
 
+	GLOBAL_DEF_BASIC("input_devices/pointing/android/enable_long_press_as_right_click", false);
+	GLOBAL_DEF_BASIC("input_devices/pointing/android/enable_pan_and_scale_gestures", false);
+
 	MAIN_PRINT("Main: Load Translations and Remaps");
 
 	translation_server->setup(); //register translations, load them, etc.

+ 13 - 15
platform/android/java/lib/src/org/godotengine/godot/Godot.kt

@@ -84,7 +84,7 @@ class Godot(private val context: Context) : SensorEventListener {
 	}
 
 	private val pluginRegistry: GodotPluginRegistry by lazy {
-		GodotPluginRegistry.initializePluginRegistry(this)
+		GodotPluginRegistry.getPluginRegistry()
 	}
 	private val mSensorManager: SensorManager by lazy {
 		requireActivity().getSystemService(Context.SENSOR_SERVICE) as SensorManager
@@ -190,7 +190,7 @@ class Godot(private val context: Context) : SensorEventListener {
 			val activity = requireActivity()
 			val window = activity.window
 			window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON)
-			GodotPluginRegistry.initializePluginRegistry(this)
+			GodotPluginRegistry.initializePluginRegistry(this, primaryHost.getHostPlugins(this))
 			if (io == null) {
 				io = GodotIO(activity)
 			}
@@ -250,11 +250,7 @@ class Godot(private val context: Context) : SensorEventListener {
 				}
 				i++
 			}
-			if (newArgs.isEmpty()) {
-				commandLine = mutableListOf()
-			} else {
-				commandLine = newArgs
-			}
+			commandLine = if (newArgs.isEmpty()) { mutableListOf() } else { newArgs }
 			if (useApkExpansion && mainPackMd5 != null && mainPackKey != null) {
 				// Build the full path to the app's expansion files
 				try {
@@ -392,6 +388,10 @@ class Godot(private val context: Context) : SensorEventListener {
 				// Fallback to openGl
 				GodotGLRenderView(host, this, xrMode, useDebugOpengl)
 			}
+
+			renderView?.inputHandler?.enableLongPress(java.lang.Boolean.parseBoolean(GodotLib.getGlobal("input_devices/pointing/android/enable_long_press_as_right_click")))
+			renderView?.inputHandler?.enablePanningAndScalingGestures(java.lang.Boolean.parseBoolean(GodotLib.getGlobal("input_devices/pointing/android/enable_pan_and_scale_gestures")))
+
 			if (host == primaryHost) {
 				renderView!!.startRenderer()
 			}
@@ -616,7 +616,7 @@ class Godot(private val context: Context) : SensorEventListener {
 
 	private fun alert(message: String, title: String, okCallback: Runnable?) {
 		val activity: Activity = getActivity() ?: return
-		runOnUiThread(Runnable {
+		runOnUiThread {
 			val builder = AlertDialog.Builder(activity)
 			builder.setMessage(message).setTitle(title)
 			builder.setPositiveButton(
@@ -627,7 +627,7 @@ class Godot(private val context: Context) : SensorEventListener {
 			}
 			val dialog = builder.create()
 			dialog.show()
-		})
+		}
 	}
 
 	/**
@@ -685,9 +685,9 @@ class Godot(private val context: Context) : SensorEventListener {
 		return false
 	}
 
-	private fun setKeepScreenOn(p_enabled: Boolean) {
+	private fun setKeepScreenOn(enabled: Boolean) {
 		runOnUiThread {
-			if (p_enabled) {
+			if (enabled) {
 				getActivity()?.window?.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
 			} else {
 				getActivity()?.window?.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
@@ -835,9 +835,7 @@ class Godot(private val context: Context) : SensorEventListener {
 		}
 	}
 
-	override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
-		// Do something here if sensor accuracy changes.
-	}
+	override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {}
 
 	/**
 	 * Used by the native code (java_godot_wrapper.h) to vibrate the device.
@@ -865,7 +863,7 @@ class Godot(private val context: Context) : SensorEventListener {
 	private fun getCommandLine(): MutableList<String> {
 		val original: MutableList<String> = parseCommandLine()
 		val hostCommandLine = primaryHost?.commandLine
-		if (hostCommandLine != null && hostCommandLine.isNotEmpty()) {
+		if (!hostCommandLine.isNullOrEmpty()) {
 			original.addAll(hostCommandLine)
 		}
 		return original

+ 4 - 0
platform/android/java/lib/src/org/godotengine/godot/GodotActivity.kt

@@ -173,6 +173,10 @@ abstract class GodotActivity : FragmentActivity(), GodotHost {
 		return this
 	}
 
+	override fun getGodot(): Godot? {
+		return godotFragment?.godot
+	}
+
 	/**
 	 * Used to initialize the Godot fragment instance in [onCreate].
 	 */

+ 12 - 0
platform/android/java/lib/src/org/godotengine/godot/GodotFragment.java

@@ -30,6 +30,7 @@
 
 package org.godotengine.godot;
 
+import org.godotengine.godot.plugin.GodotPlugin;
 import org.godotengine.godot.utils.BenchmarkUtils;
 
 import android.app.Activity;
@@ -65,6 +66,7 @@ import com.google.android.vending.expansion.downloader.IStub;
 import java.util.Collections;
 import java.util.List;
 import java.util.Locale;
+import java.util.Set;
 
 /**
  * Base fragment for Android apps intending to use Godot for part of the app's UI.
@@ -122,6 +124,7 @@ public class GodotFragment extends Fragment implements IDownloaderClient, GodotH
 	}
 	public ResultCallback resultCallback;
 
+	@Override
 	public Godot getGodot() {
 		return godot;
 	}
@@ -426,4 +429,13 @@ public class GodotFragment extends Fragment implements IDownloaderClient, GodotH
 		}
 		return 0;
 	}
+
+	@Override
+	@CallSuper
+	public Set<GodotPlugin> getHostPlugins(Godot engine) {
+		if (parentHost != null) {
+			return parentHost.getHostPlugins(engine);
+		}
+		return Collections.emptySet();
+	}
 }

+ 21 - 6
platform/android/java/lib/src/org/godotengine/godot/GodotHost.java

@@ -30,39 +30,42 @@
 
 package org.godotengine.godot;
 
+import org.godotengine.godot.plugin.GodotPlugin;
+
 import android.app.Activity;
 
 import java.util.Collections;
 import java.util.List;
+import java.util.Set;
 
 /**
  * Denotate a component (e.g: Activity, Fragment) that hosts the {@link Godot} engine.
  */
 public interface GodotHost {
 	/**
-	 * Provides a set of command line parameters to setup the engine.
+	 * Provides a set of command line parameters to setup the {@link Godot} engine.
 	 */
 	default List<String> getCommandLine() {
 		return Collections.emptyList();
 	}
 
 	/**
-	 * Invoked on the render thread when the Godot setup is complete.
+	 * Invoked on the render thread when setup of the {@link Godot} engine is complete.
 	 */
 	default void onGodotSetupCompleted() {}
 
 	/**
-	 * Invoked on the render thread when the Godot main loop has started.
+	 * Invoked on the render thread when the {@link Godot} engine main loop has started.
 	 */
 	default void onGodotMainLoopStarted() {}
 
 	/**
-	 * Invoked on the render thread to terminate the given Godot instance.
+	 * Invoked on the render thread to terminate the given {@link Godot} engine instance.
 	 */
 	default void onGodotForceQuit(Godot instance) {}
 
 	/**
-	 * Invoked on the render thread to terminate the Godot instance with the given id.
+	 * Invoked on the render thread to terminate the {@link Godot} engine instance with the given id.
 	 * @param godotInstanceId id of the Godot instance to terminate. See {@code onNewGodotInstanceRequested}
 	 *
 	 * @return true if successful, false otherwise.
@@ -90,7 +93,19 @@ public interface GodotHost {
 	}
 
 	/**
-	 * Provide access to the Activity hosting the Godot engine.
+	 * Provide access to the Activity hosting the {@link Godot} engine.
 	 */
 	Activity getActivity();
+
+	/**
+	 * Provide access to the hosted {@link Godot} engine.
+	 */
+	Godot getGodot();
+
+	/**
+	 * Returns a set of {@link GodotPlugin} to be registered with the hosted {@link Godot} engine.
+	 */
+	default Set<GodotPlugin> getHostPlugins(Godot engine) {
+		return Collections.emptySet();
+	}
 }

+ 3 - 1
platform/android/java/lib/src/org/godotengine/godot/GodotService.kt

@@ -8,8 +8,10 @@ import android.util.Log
 
 /**
  * Godot service responsible for hosting the Godot engine instance.
+ *
+ * Note: Still in development, so it's made private and inaccessible until completed.
  */
-class GodotService : Service() {
+private class GodotService : Service() {
 
 	companion object {
 		private val TAG = GodotService::class.java.simpleName

+ 1 - 1
platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java

@@ -95,7 +95,7 @@ public class GodotInputHandler implements InputManager.InputDeviceListener {
 
 	/**
 	 * Enable multi-fingers pan & scale gestures. This is false by default.
-	 *
+	 * <p>
 	 * Note: This may interfere with multi-touch handling / support.
 	 */
 	public void enablePanningAndScalingGestures(boolean enable) {

+ 17 - 7
platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginRegistry.java

@@ -42,8 +42,8 @@ import android.util.Log;
 import androidx.annotation.Nullable;
 
 import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
 import java.util.Collection;
+import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
 /**
@@ -64,9 +64,8 @@ public final class GodotPluginRegistry {
 	private static GodotPluginRegistry instance;
 	private final ConcurrentHashMap<String, GodotPlugin> registry;
 
-	private GodotPluginRegistry(Godot godot) {
+	private GodotPluginRegistry() {
 		registry = new ConcurrentHashMap<>();
-		loadPlugins(godot);
 	}
 
 	/**
@@ -93,12 +92,14 @@ public final class GodotPluginRegistry {
 	 * documentation.
 	 *
 	 * @param godot Godot instance
+	 * @param runtimePlugins Set of plugins provided at runtime for registration
 	 * @return A singleton instance of {@link GodotPluginRegistry}. This ensures that only one instance
 	 * of each Godot Android plugins is available at runtime.
 	 */
-	public static GodotPluginRegistry initializePluginRegistry(Godot godot) {
+	public static GodotPluginRegistry initializePluginRegistry(Godot godot, Set<GodotPlugin> runtimePlugins) {
 		if (instance == null) {
-			instance = new GodotPluginRegistry(godot);
+			instance = new GodotPluginRegistry();
+			instance.loadPlugins(godot, runtimePlugins);
 		}
 
 		return instance;
@@ -108,7 +109,7 @@ public final class GodotPluginRegistry {
 	 * Return the plugin registry if it's initialized.
 	 * Throws a {@link IllegalStateException} exception if not.
 	 *
-	 * @throws IllegalStateException if {@link GodotPluginRegistry#initializePluginRegistry(Godot)} has not been called prior to calling this method.
+	 * @throws IllegalStateException if {@link GodotPluginRegistry#initializePluginRegistry(Godot, Set)} has not been called prior to calling this method.
 	 */
 	public static GodotPluginRegistry getPluginRegistry() throws IllegalStateException {
 		if (instance == null) {
@@ -118,7 +119,16 @@ public final class GodotPluginRegistry {
 		return instance;
 	}
 
-	private void loadPlugins(Godot godot) {
+	private void loadPlugins(Godot godot, Set<GodotPlugin> runtimePlugins) {
+		// Register the runtime plugins
+		if (runtimePlugins != null && !runtimePlugins.isEmpty()) {
+			for (GodotPlugin plugin : runtimePlugins) {
+				Log.i(TAG, "Registering runtime plugin " + plugin.getPluginName());
+				registry.put(plugin.getPluginName(), plugin);
+			}
+		}
+
+		// Register the manifest plugins
 		try {
 			final Activity activity = godot.getActivity();
 			ApplicationInfo appInfo = activity