feat: modules moved and engine moved to submodule
This commit is contained in:
parent
dfb5e645cd
commit
c33d2130cc
5136 changed files with 225275 additions and 64485 deletions
|
|
@ -29,15 +29,6 @@
|
|||
android:enabled="true"
|
||||
tools:targetApi="29" />
|
||||
|
||||
<!-- Records the version of the Godot editor used for building -->
|
||||
<meta-data
|
||||
android:name="org.godotengine.editor.version"
|
||||
android:value="${godotEditorVersion}" />
|
||||
<!-- Records the rendering method used by the Godot engine -->
|
||||
<meta-data
|
||||
android:name="org.godotengine.rendering.method"
|
||||
android:value="${godotRenderingMethod}"/>
|
||||
|
||||
<activity
|
||||
android:name=".GodotApp"
|
||||
android:label="@string/godot_project_name_string"
|
||||
|
|
@ -46,7 +37,7 @@
|
|||
android:excludeFromRecents="false"
|
||||
android:exported="true"
|
||||
android:screenOrientation="landscape"
|
||||
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|density|keyboard|navigation|screenLayout|uiMode"
|
||||
android:configChanges="layoutDirection|locale|orientation|keyboardHidden|screenSize|smallestScreenSize|density|keyboard|navigation|screenLayout|uiMode"
|
||||
android:resizeableActivity="false"
|
||||
tools:ignore="UnusedAttribute" >
|
||||
|
||||
|
|
|
|||
|
|
@ -105,11 +105,6 @@ android {
|
|||
abiFilters export_abi_list
|
||||
}
|
||||
|
||||
manifestPlaceholders = [
|
||||
godotEditorVersion: getGodotEditorVersion(),
|
||||
godotRenderingMethod: getGodotRenderingMethod()
|
||||
]
|
||||
|
||||
// Feel free to modify the application id to your own.
|
||||
applicationId getExportPackageName()
|
||||
versionCode getExportVersionCode()
|
||||
|
|
|
|||
|
|
@ -71,25 +71,6 @@ ext.getExportTargetSdkVersion = { ->
|
|||
}
|
||||
}
|
||||
|
||||
ext.getGodotRenderingMethod = { ->
|
||||
String renderingMethod = project.hasProperty("godot_rendering_method") ? project.property("godot_rendering_method") : ""
|
||||
return renderingMethod
|
||||
}
|
||||
|
||||
ext.getGodotEditorVersion = { ->
|
||||
String editorVersion = project.hasProperty("godot_editor_version") ? project.property("godot_editor_version") : ""
|
||||
if (editorVersion == null || editorVersion.isEmpty()) {
|
||||
// Try the library version first
|
||||
editorVersion = getGodotLibraryVersionName()
|
||||
|
||||
if (editorVersion.isEmpty()) {
|
||||
// Fallback value.
|
||||
editorVersion = "custom_build"
|
||||
}
|
||||
}
|
||||
return editorVersion
|
||||
}
|
||||
|
||||
ext.getGodotLibraryVersionCode = { ->
|
||||
String versionName = ""
|
||||
int versionCode = 1
|
||||
|
|
|
|||
|
|
@ -90,6 +90,8 @@
|
|||
<!-- Enable passthrough background during the splash screen -->
|
||||
<meta-data android:name="com.oculus.ossplash.background" android:value="passthrough-contextual"/>
|
||||
|
||||
<meta-data android:name="com.oculus.handtracking.version" android:value="V2.0" />
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@
|
|||
|
||||
<activity
|
||||
android:name=".GodotEditor"
|
||||
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|density|keyboard|navigation|screenLayout|uiMode"
|
||||
android:configChanges="layoutDirection|locale|orientation|keyboardHidden|screenSize|smallestScreenSize|density|keyboard|navigation|screenLayout|uiMode"
|
||||
android:exported="true"
|
||||
android:icon="@mipmap/themed_icon"
|
||||
android:launchMode="singleTask"
|
||||
|
|
@ -59,7 +59,7 @@
|
|||
</activity>
|
||||
<activity
|
||||
android:name=".GodotGame"
|
||||
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|density|keyboard|navigation|screenLayout|uiMode"
|
||||
android:configChanges="layoutDirection|locale|orientation|keyboardHidden|screenSize|smallestScreenSize|density|keyboard|navigation|screenLayout|uiMode"
|
||||
android:exported="false"
|
||||
android:icon="@mipmap/ic_play_window"
|
||||
android:label="@string/godot_game_activity_name"
|
||||
|
|
@ -74,7 +74,7 @@
|
|||
</activity>
|
||||
<activity
|
||||
android:name=".embed.EmbeddedGodotGame"
|
||||
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|density|keyboard|navigation|screenLayout|uiMode"
|
||||
android:configChanges="layoutDirection|locale|orientation|keyboardHidden|screenSize|smallestScreenSize|density|keyboard|navigation|screenLayout|uiMode"
|
||||
android:exported="false"
|
||||
android:icon="@mipmap/ic_play_window"
|
||||
android:label="@string/godot_game_activity_name"
|
||||
|
|
@ -87,7 +87,7 @@
|
|||
android:screenOrientation="userLandscape" />
|
||||
<activity
|
||||
android:name=".GodotXRGame"
|
||||
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|density|keyboard|navigation|screenLayout|uiMode"
|
||||
android:configChanges="layoutDirection|locale|orientation|keyboardHidden|screenSize|smallestScreenSize|density|keyboard|navigation|screenLayout|uiMode"
|
||||
android:process=":GodotXRGame"
|
||||
android:launchMode="singleTask"
|
||||
android:icon="@mipmap/ic_play_window"
|
||||
|
|
|
|||
|
|
@ -37,7 +37,11 @@ import android.content.ComponentName
|
|||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.*
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.Debug
|
||||
import android.os.Environment
|
||||
import android.os.Process
|
||||
import android.preference.PreferenceManager
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
|
|
@ -138,6 +142,7 @@ abstract class BaseGodotEditor : GodotActivity(), GameMenuFragment.GameMenuListe
|
|||
internal const val GAME_MENU_ACTION_RESET_CAMERA_2D_POSITION = "resetCamera2DPosition"
|
||||
internal const val GAME_MENU_ACTION_RESET_CAMERA_3D_POSITION = "resetCamera3DPosition"
|
||||
internal const val GAME_MENU_ACTION_EMBED_GAME_ON_PLAY = "embedGameOnPlay"
|
||||
internal const val GAME_MENU_ACTION_SET_DEBUG_MUTE_AUDIO = "setDebugMuteAudio"
|
||||
|
||||
private const val GAME_WORKSPACE = "Game"
|
||||
|
||||
|
|
@ -258,12 +263,14 @@ abstract class BaseGodotEditor : GodotActivity(), GameMenuFragment.GameMenuListe
|
|||
super.onGodotSetupCompleted()
|
||||
val longPressEnabled = enableLongPressGestures()
|
||||
val panScaleEnabled = enablePanAndScaleGestures()
|
||||
val overrideVolumeButtonsEnabled = overrideVolumeButtons()
|
||||
|
||||
runOnUiThread {
|
||||
// Enable long press, panning and scaling gestures
|
||||
godotFragment?.godot?.renderView?.inputHandler?.apply {
|
||||
enableLongPress(longPressEnabled)
|
||||
enablePanningAndScalingGestures(panScaleEnabled)
|
||||
setOverrideVolumeButtons(overrideVolumeButtonsEnabled)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -482,12 +489,19 @@ abstract class BaseGodotEditor : GodotActivity(), GameMenuFragment.GameMenuListe
|
|||
*/
|
||||
protected open fun overrideOrientationRequest() = true
|
||||
|
||||
protected open fun overrideVolumeButtons() = false
|
||||
|
||||
/**
|
||||
* Enable long press gestures for the Godot Android editor.
|
||||
*/
|
||||
protected open fun enableLongPressGestures() =
|
||||
java.lang.Boolean.parseBoolean(GodotLib.getEditorSetting("interface/touchscreen/enable_long_press_as_right_click"))
|
||||
|
||||
/**
|
||||
* Disable scroll deadzone for the Godot Android editor.
|
||||
*/
|
||||
protected open fun disableScrollDeadzone() = true
|
||||
|
||||
/**
|
||||
* Enable pan and scale gestures for the Godot Android editor.
|
||||
*/
|
||||
|
|
@ -749,6 +763,10 @@ abstract class BaseGodotEditor : GodotActivity(), GameMenuFragment.GameMenuListe
|
|||
val embedded = actionData.getBoolean(KEY_GAME_MENU_ACTION_PARAM1)
|
||||
embedGameOnPlay(embedded)
|
||||
}
|
||||
GAME_MENU_ACTION_SET_DEBUG_MUTE_AUDIO -> {
|
||||
val enabled = actionData.getBoolean(KEY_GAME_MENU_ACTION_PARAM1)
|
||||
muteAudio(enabled)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -812,6 +830,13 @@ abstract class BaseGodotEditor : GodotActivity(), GameMenuFragment.GameMenuListe
|
|||
}
|
||||
}
|
||||
|
||||
override fun muteAudio(enabled: Boolean) {
|
||||
gameMenuState.putBoolean(GAME_MENU_ACTION_SET_DEBUG_MUTE_AUDIO, enabled)
|
||||
godot?.runOnRenderThread {
|
||||
GameMenuUtils.setDebugMuteAudio(enabled)
|
||||
}
|
||||
}
|
||||
|
||||
override fun embedGameOnPlay(embedded: Boolean) {
|
||||
gameMenuState.putBoolean(GAME_MENU_ACTION_EMBED_GAME_ON_PLAY, embedded)
|
||||
godot?.runOnRenderThread {
|
||||
|
|
|
|||
|
|
@ -46,10 +46,14 @@ abstract class BaseGodotGame: GodotEditor() {
|
|||
private val TAG = BaseGodotGame::class.java.simpleName
|
||||
}
|
||||
|
||||
override fun overrideVolumeButtons() = java.lang.Boolean.parseBoolean(GodotLib.getGlobal("input_devices/pointing/android/override_volume_buttons"))
|
||||
|
||||
override fun enableLongPressGestures() = java.lang.Boolean.parseBoolean(GodotLib.getGlobal("input_devices/pointing/android/enable_long_press_as_right_click"))
|
||||
|
||||
override fun enablePanAndScaleGestures() = java.lang.Boolean.parseBoolean(GodotLib.getGlobal("input_devices/pointing/android/enable_pan_and_scale_gestures"))
|
||||
|
||||
override fun disableScrollDeadzone() = java.lang.Boolean.parseBoolean(GodotLib.getGlobal("input_devices/pointing/android/disable_scroll_deadzone"))
|
||||
|
||||
override fun onGodotSetupCompleted() {
|
||||
super.onGodotSetupCompleted()
|
||||
Log.v(TAG, "OnGodotSetupCompleted")
|
||||
|
|
|
|||
|
|
@ -206,6 +206,14 @@ open class GodotGame : BaseGodotGame() {
|
|||
editorMessageDispatcher.dispatchGameMenuAction(EDITOR_MAIN_INFO, actionBundle)
|
||||
}
|
||||
|
||||
override fun muteAudio(enabled: Boolean) {
|
||||
val actionBundle = Bundle().apply {
|
||||
putString(KEY_GAME_MENU_ACTION, GAME_MENU_ACTION_SET_DEBUG_MUTE_AUDIO)
|
||||
putBoolean(KEY_GAME_MENU_ACTION_PARAM1, enabled)
|
||||
}
|
||||
editorMessageDispatcher.dispatchGameMenuAction(EDITOR_MAIN_INFO, actionBundle)
|
||||
}
|
||||
|
||||
override fun embedGameOnPlay(embedded: Boolean) {
|
||||
val actionBundle = Bundle().apply {
|
||||
putString(KEY_GAME_MENU_ACTION, GAME_MENU_ACTION_EMBED_GAME_ON_PLAY)
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@ class GameMenuFragment : Fragment(), PopupMenu.OnMenuItemClickListener {
|
|||
fun reset2DCamera()
|
||||
fun reset3DCamera()
|
||||
fun manipulateCamera(mode: CameraMode)
|
||||
fun muteAudio(enabled: Boolean)
|
||||
|
||||
fun isGameEmbeddingSupported(): Boolean
|
||||
fun embedGameOnPlay(embedded: Boolean)
|
||||
|
|
@ -148,6 +149,9 @@ class GameMenuFragment : Fragment(), PopupMenu.OnMenuItemClickListener {
|
|||
private val listSelectButton: RadioButton? by lazy {
|
||||
view?.findViewById(R.id.game_menu_list_select_button)
|
||||
}
|
||||
private val audioMuteButton: View? by lazy {
|
||||
view?.findViewById(R.id.game_menu_audio_mute_button)
|
||||
}
|
||||
private val optionsButton: View? by lazy {
|
||||
view?.findViewById(R.id.game_menu_options_button)
|
||||
}
|
||||
|
|
@ -319,6 +323,13 @@ class GameMenuFragment : Fragment(), PopupMenu.OnMenuItemClickListener {
|
|||
}
|
||||
}
|
||||
}
|
||||
audioMuteButton?.apply{
|
||||
setOnClickListener {
|
||||
val isActivated = !it.isActivated
|
||||
menuListener?.muteAudio(isActivated)
|
||||
it.isActivated = isActivated
|
||||
}
|
||||
}
|
||||
optionsButton?.setOnClickListener {
|
||||
popupMenu.show()
|
||||
}
|
||||
|
|
@ -351,6 +362,8 @@ class GameMenuFragment : Fragment(), PopupMenu.OnMenuItemClickListener {
|
|||
toolSelectButton?.isChecked = selectMode == GameMenuListener.SelectMode.SINGLE
|
||||
listSelectButton?.isChecked = selectMode == GameMenuListener.SelectMode.LIST
|
||||
|
||||
audioMuteButton?.isActivated = gameMenuState.getBoolean(BaseGodotEditor.GAME_MENU_ACTION_SET_DEBUG_MUTE_AUDIO, false)
|
||||
|
||||
popupMenu.menu.apply {
|
||||
if (menuListener?.isGameEmbeddingSupported() == false) {
|
||||
setGroupEnabled(R.id.group_menu_embed_options, false)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="16dp"
|
||||
android:height="16dp"
|
||||
android:viewportWidth="2.4"
|
||||
android:viewportHeight="2.4">
|
||||
|
||||
<path
|
||||
android:pathData="M1.252 0.15 a0.1 0.1 0 0 0-0.082 0.03 L0.6 0.75 H0.318C0.225 0.75 0.15 0.817 0.15 0.9 v0.6c0 0.083 0.075 0.15 0.168 0.15H0.6l0.57 0.57 c0.066 0.067 0.18 0.02 0.18-0.074V0.256A0.106 0.106 0 0 0 1.252 0.15"
|
||||
android:fillColor="@color/game_menu_icons_color_state"/>
|
||||
<path
|
||||
android:strokeWidth=".165"
|
||||
android:strokeLineCap="round"
|
||||
android:pathData="M1.575 0.675 c0.45 0.525 0 1.05 0 1.05m0.3-1.35c0.675 0.825 0 1.65 0 1.65"
|
||||
android:strokeColor="@color/game_menu_icons_color_state"/>
|
||||
</vector>
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/audio_player_muted" android:state_activated="true" />
|
||||
<item android:drawable="@drawable/audio_player" />
|
||||
</selector>
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="16dp"
|
||||
android:height="16dp"
|
||||
android:viewportWidth="2.4"
|
||||
android:viewportHeight="2.4">
|
||||
|
||||
<path
|
||||
android:pathData="M 1.2518555 0.15 A 0.1 0.1 0 0 0 1.1701172 0.17988281 L 0.6 0.75 L 0.31787109 0.75 C 0.22487119 0.75 0.15 0.81700008 0.15 0.9 L 0.15 1.5 C 0.15 1.5424221 0.16969512 1.5805593 0.20126953 1.6078125 L 1.35 0.45527344 L 1.35 0.25605469 A 0.106 0.106 0 0 0 1.2518555 0.15 z M 1.35 1.6438477 L 0.97236328 2.0223633 L 1.1701172 2.2201172 C 1.2361171 2.2871171 1.35 2.239996 1.35 2.1459961 L 1.35 1.6438477 z"
|
||||
android:fillColor="@color/game_menu_icons_color_state"/>
|
||||
<path
|
||||
android:pathData="M 2.1984375 0.79306641 L 2.0660156 0.92578125 C 2.1142629 1.1320246 2.0935608 1.3239034 2.0487305 1.4882812 C 1.9692536 1.7796963 1.8105469 1.9725586 1.8105469 1.9725586 A 0.0825 0.0825 0 0 0 1.8222656 2.0879883 A 0.0825 0.0825 0 0 0 1.9394531 2.0780273 C 1.9394531 2.0780273 2.1176607 1.8586814 2.2069336 1.5313477 C 2.2638362 1.3227069 2.2834498 1.0648044 2.1984375 0.79306641 z M 1.8539062 1.1384766 L 1.6790039 1.3136719 C 1.6747238 1.3346601 1.6697313 1.3550615 1.6640625 1.3749023 C 1.6131343 1.5531513 1.5117188 1.6719727 1.5117187 1.6719727 A 0.0825 0.0825 0 0 0 1.5213867 1.7871094 A 0.0825 0.0825 0 0 0 1.6368164 1.7791992 C 1.6368164 1.7791992 1.7606941 1.6355198 1.8222656 1.4200195 C 1.8460259 1.3368593 1.8597024 1.2410136 1.8539062 1.1384766 z"
|
||||
android:fillColor="@color/game_menu_icons_color_state"/>
|
||||
<path
|
||||
android:pathData="M0.08295 2.0529 2.0502 0.07965 2.31705 0.34725 0.34965 2.32035ZM-1.2804596 3.0939027 3.0879072-1.2877874Z"
|
||||
android:fillColor="#fc7f7f"/>
|
||||
</vector>
|
||||
|
|
@ -128,6 +128,15 @@
|
|||
android:drawableStart="@drawable/list_select"
|
||||
android:padding="15dp" />
|
||||
</RadioGroup>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/game_menu_audio_mute_button"
|
||||
style="?android:attr/borderlessButtonStyle"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:background="@drawable/game_menu_button_bg"
|
||||
android:src="@drawable/audio_player_icon_selector" />
|
||||
|
||||
</LinearLayout>
|
||||
</HorizontalScrollView>
|
||||
|
||||
|
|
|
|||
|
|
@ -77,7 +77,6 @@ import org.godotengine.godot.xr.XRMode
|
|||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.InputStream
|
||||
import java.lang.Exception
|
||||
import java.security.MessageDigest
|
||||
import java.util.*
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
|
@ -714,11 +713,15 @@ class Godot(private val context: Context) {
|
|||
val longPressEnabled = java.lang.Boolean.parseBoolean(GodotLib.getGlobal("input_devices/pointing/android/enable_long_press_as_right_click"))
|
||||
val panScaleEnabled = java.lang.Boolean.parseBoolean(GodotLib.getGlobal("input_devices/pointing/android/enable_pan_and_scale_gestures"))
|
||||
val rotaryInputAxisValue = GodotLib.getGlobal("input_devices/pointing/android/rotary_input_scroll_axis")
|
||||
val overrideVolumeButtons = java.lang.Boolean.parseBoolean(GodotLib.getGlobal("input_devices/pointing/android/override_volume_buttons"))
|
||||
val scrollDeadzoneDisabled = java.lang.Boolean.parseBoolean(GodotLib.getGlobal("input_devices/pointing/android/disable_scroll_deadzone"))
|
||||
|
||||
runOnUiThread {
|
||||
renderView?.inputHandler?.apply {
|
||||
enableLongPress(longPressEnabled)
|
||||
enablePanningAndScalingGestures(panScaleEnabled)
|
||||
setOverrideVolumeButtons(overrideVolumeButtons)
|
||||
disableScrollDeadzone(scrollDeadzoneDisabled)
|
||||
try {
|
||||
setRotaryInputAxis(Integer.parseInt(rotaryInputAxisValue))
|
||||
} catch (e: NumberFormatException) {
|
||||
|
|
|
|||
|
|
@ -268,6 +268,11 @@ public class GodotLib {
|
|||
*/
|
||||
public static native void onNightModeChanged();
|
||||
|
||||
/**
|
||||
* Invoked on the hardware keyboard connected/disconnected.
|
||||
*/
|
||||
public static native void hardwareKeyboardConnected(boolean connected);
|
||||
|
||||
/**
|
||||
* Invoked on the file picker closed.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -265,13 +265,6 @@ public class GodotEditText extends EditText {
|
|||
}
|
||||
|
||||
public boolean hasHardwareKeyboard() {
|
||||
Configuration config = getResources().getConfiguration();
|
||||
boolean hasHardwareKeyboardConfig = config.keyboard != Configuration.KEYBOARD_NOKEYS &&
|
||||
config.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO;
|
||||
if (hasHardwareKeyboardConfig) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return mRenderView.getInputHandler().hasHardwareKeyboard();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,6 +55,8 @@ internal class GodotGestureHandler(private val inputHandler: GodotInputHandler)
|
|||
*/
|
||||
var panningAndScalingEnabled = false
|
||||
|
||||
var scrollDeadzoneDisabled = false
|
||||
|
||||
private var nextDownIsDoubleTap = false
|
||||
private var dragInProgress = false
|
||||
private var scaleInProgress = false
|
||||
|
|
@ -153,7 +155,7 @@ internal class GodotGestureHandler(private val inputHandler: GodotInputHandler)
|
|||
if (contextClickInProgress) {
|
||||
inputHandler.handleMouseEvent(event, event.actionMasked, MotionEvent.BUTTON_SECONDARY, false)
|
||||
return true
|
||||
} else if (!scaleInProgress) {
|
||||
} else if (scrollDeadzoneDisabled && !scaleInProgress) {
|
||||
// The 'onScroll' event is triggered with a long delay.
|
||||
// Force the 'InputEventScreenDrag' event earlier here.
|
||||
// We don't toggle 'dragInProgress' here so that the scaling logic can override the drag operation if needed.
|
||||
|
|
@ -191,7 +193,7 @@ internal class GodotGestureHandler(private val inputHandler: GodotInputHandler)
|
|||
distanceY: Float
|
||||
): Boolean {
|
||||
if (scaleInProgress) {
|
||||
if (dragInProgress || lastDragX != 0.0f || lastDragY != 0.0f) {
|
||||
if (dragInProgress || (scrollDeadzoneDisabled && (lastDragX != 0.0f || lastDragY != 0.0f))) {
|
||||
if (originEvent != null) {
|
||||
// Cancel the drag
|
||||
inputHandler.handleMotionEvent(originEvent, MotionEvent.ACTION_CANCEL)
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ import androidx.annotation.NonNull;
|
|||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* Handles input related events for the {@link GodotRenderView} view.
|
||||
|
|
@ -83,11 +84,13 @@ public class GodotInputHandler implements InputManager.InputDeviceListener, Sens
|
|||
/**
|
||||
* Used to decide whether mouse capture can be enabled.
|
||||
*/
|
||||
private int lastSeenToolType = MotionEvent.TOOL_TYPE_UNKNOWN;
|
||||
private AtomicInteger lastSeenToolType = new AtomicInteger(MotionEvent.TOOL_TYPE_UNKNOWN);
|
||||
|
||||
private int rotaryInputAxis = ROTARY_INPUT_VERTICAL_AXIS;
|
||||
|
||||
private int cachedRotation = -1;
|
||||
private boolean overrideVolumeButtons = false;
|
||||
private boolean hasHardwareKeyboardConfig = false;
|
||||
|
||||
public GodotInputHandler(Context context, Godot godot) {
|
||||
this.godot = godot;
|
||||
|
|
@ -103,6 +106,9 @@ public class GodotInputHandler implements InputManager.InputDeviceListener, Sens
|
|||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
this.scaleGestureDetector.setStylusScaleEnabled(true);
|
||||
}
|
||||
Configuration config = context.getResources().getConfiguration();
|
||||
hasHardwareKeyboardConfig = config.keyboard != Configuration.KEYBOARD_NOKEYS &&
|
||||
config.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -112,6 +118,13 @@ public class GodotInputHandler implements InputManager.InputDeviceListener, Sens
|
|||
this.gestureDetector.setIsLongpressEnabled(enable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable scroll deadzone. This is false by default.
|
||||
*/
|
||||
public void disableScrollDeadzone(boolean disable) {
|
||||
this.godotGestureHandler.setScrollDeadzoneDisabled(disable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable multi-fingers pan & scale gestures. This is false by default.
|
||||
* <p>
|
||||
|
|
@ -136,7 +149,14 @@ public class GodotInputHandler implements InputManager.InputDeviceListener, Sens
|
|||
rotaryInputAxis = axis;
|
||||
}
|
||||
|
||||
public void setOverrideVolumeButtons(boolean value) {
|
||||
overrideVolumeButtons = value;
|
||||
}
|
||||
|
||||
boolean hasHardwareKeyboard() {
|
||||
if (hasHardwareKeyboardConfig) {
|
||||
return true;
|
||||
}
|
||||
return !mHardwareKeyboardIds.isEmpty();
|
||||
}
|
||||
|
||||
|
|
@ -149,7 +169,8 @@ public class GodotInputHandler implements InputManager.InputDeviceListener, Sens
|
|||
}
|
||||
|
||||
public boolean canCapturePointer() {
|
||||
return lastSeenToolType == MotionEvent.TOOL_TYPE_MOUSE;
|
||||
return lastSeenToolType.get() == MotionEvent.TOOL_TYPE_MOUSE ||
|
||||
lastSeenToolType.get() == MotionEvent.TOOL_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
public void onPointerCaptureChange(boolean hasCapture) {
|
||||
|
|
@ -157,10 +178,6 @@ public class GodotInputHandler implements InputManager.InputDeviceListener, Sens
|
|||
}
|
||||
|
||||
public boolean onKeyUp(final int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_VOLUME_UP || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int source = event.getSource();
|
||||
if (isKeyEventGameDevice(source)) {
|
||||
// Check if the device exists
|
||||
|
|
@ -178,14 +195,14 @@ public class GodotInputHandler implements InputManager.InputDeviceListener, Sens
|
|||
handleKeyEvent(physical_keycode, unicode, key_label, false, event.getRepeatCount() > 0);
|
||||
};
|
||||
|
||||
if (keyCode == KeyEvent.KEYCODE_VOLUME_UP || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
|
||||
return overrideVolumeButtons;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean onKeyDown(final int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_VOLUME_UP || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int source = event.getSource();
|
||||
|
||||
final int deviceId = event.getDeviceId();
|
||||
|
|
@ -206,11 +223,15 @@ public class GodotInputHandler implements InputManager.InputDeviceListener, Sens
|
|||
handleKeyEvent(physical_keycode, unicode, key_label, true, event.getRepeatCount() > 0);
|
||||
}
|
||||
|
||||
if (keyCode == KeyEvent.KEYCODE_VOLUME_UP || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
|
||||
return overrideVolumeButtons;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean onTouchEvent(final MotionEvent event) {
|
||||
lastSeenToolType = getEventToolType(event);
|
||||
lastSeenToolType.set(getEventToolType(event));
|
||||
|
||||
this.scaleGestureDetector.onTouchEvent(event);
|
||||
if (this.gestureDetector.onTouchEvent(event)) {
|
||||
|
|
@ -236,7 +257,7 @@ public class GodotInputHandler implements InputManager.InputDeviceListener, Sens
|
|||
}
|
||||
|
||||
public boolean onGenericMotionEvent(MotionEvent event) {
|
||||
lastSeenToolType = getEventToolType(event);
|
||||
lastSeenToolType.set(getEventToolType(event));
|
||||
|
||||
if (event.isFromSource(InputDevice.SOURCE_JOYSTICK) && event.getActionMasked() == MotionEvent.ACTION_MOVE) {
|
||||
// Check if the device exists
|
||||
|
|
@ -790,5 +811,12 @@ public class GodotInputHandler implements InputManager.InputDeviceListener, Sens
|
|||
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
updateCachedRotation();
|
||||
|
||||
boolean newHardwareKeyboardConfig = newConfig.keyboard != Configuration.KEYBOARD_NOKEYS &&
|
||||
newConfig.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO;
|
||||
if (hasHardwareKeyboardConfig != newHardwareKeyboardConfig) {
|
||||
hasHardwareKeyboardConfig = newHardwareKeyboardConfig;
|
||||
GodotLib.hardwareKeyboardConnected(hasHardwareKeyboard());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,6 +66,8 @@ internal class AssetData(context: Context, private val filePath: String, accessF
|
|||
}
|
||||
|
||||
fun fileLastModified(path: String) = 0L
|
||||
fun fileLastAccessed(path: String) = 0L
|
||||
fun fileSize(path: String) = -1L
|
||||
|
||||
fun delete(path: String) = false
|
||||
|
||||
|
|
|
|||
|
|
@ -132,6 +132,24 @@ internal abstract class DataAccess {
|
|||
}
|
||||
}
|
||||
|
||||
fun fileLastAccessed(storageScope: StorageScope, context: Context, path: String): Long {
|
||||
return when(storageScope) {
|
||||
StorageScope.APP -> FileData.fileLastAccessed(path)
|
||||
StorageScope.ASSETS -> AssetData.fileLastAccessed(path)
|
||||
StorageScope.SHARED -> MediaStoreData.fileLastAccessed(context, path)
|
||||
StorageScope.UNKNOWN -> 0L
|
||||
}
|
||||
}
|
||||
|
||||
fun fileSize(storageScope: StorageScope, context: Context, path: String): Long {
|
||||
return when(storageScope) {
|
||||
StorageScope.APP -> FileData.fileSize(path)
|
||||
StorageScope.ASSETS -> AssetData.fileSize(path)
|
||||
StorageScope.SHARED -> MediaStoreData.fileSize(context, path)
|
||||
StorageScope.UNKNOWN -> -1L
|
||||
}
|
||||
}
|
||||
|
||||
fun removeFile(storageScope: StorageScope, context: Context, path: String): Boolean {
|
||||
return when(storageScope) {
|
||||
StorageScope.APP -> FileData.delete(path)
|
||||
|
|
|
|||
|
|
@ -228,6 +228,21 @@ class FileAccessHandler(val context: Context) {
|
|||
}
|
||||
}
|
||||
|
||||
fun fileLastAccessed(filepath: String?): Long {
|
||||
val storageScope = storageScopeIdentifier.identifyStorageScope(filepath)
|
||||
if (storageScope == StorageScope.UNKNOWN) {
|
||||
return 0L
|
||||
}
|
||||
|
||||
return try {
|
||||
filepath?.let {
|
||||
DataAccess.fileLastAccessed(storageScope, context, it)
|
||||
} ?: 0L
|
||||
} catch (e: SecurityException) {
|
||||
0L
|
||||
}
|
||||
}
|
||||
|
||||
fun fileResize(fileId: Int, length: Long): Int {
|
||||
if (!hasFileId(fileId)) {
|
||||
return Error.FAILED.toNativeValue()
|
||||
|
|
@ -236,6 +251,21 @@ class FileAccessHandler(val context: Context) {
|
|||
return files[fileId].resize(length).toNativeValue()
|
||||
}
|
||||
|
||||
fun fileSize(filepath: String?): Long {
|
||||
val storageScope = storageScopeIdentifier.identifyStorageScope(filepath)
|
||||
if (storageScope == StorageScope.UNKNOWN) {
|
||||
return -1L
|
||||
}
|
||||
|
||||
return try {
|
||||
filepath?.let {
|
||||
DataAccess.fileSize(storageScope, context, it)
|
||||
} ?: -1L
|
||||
} catch (e: SecurityException) {
|
||||
-1L
|
||||
}
|
||||
}
|
||||
|
||||
fun fileGetPosition(fileId: Int): Long {
|
||||
if (!hasFileId(fileId)) {
|
||||
return 0L
|
||||
|
|
|
|||
|
|
@ -30,10 +30,16 @@
|
|||
|
||||
package org.godotengine.godot.io.file
|
||||
|
||||
import android.os.*
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.io.RandomAccessFile
|
||||
import java.nio.channels.FileChannel
|
||||
import java.nio.file.attribute.BasicFileAttributes
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.FileSystems
|
||||
import java.nio.file.Path
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
/**
|
||||
* Implementation of [DataAccess] which handles regular (not scoped) file access and interactions.
|
||||
|
|
@ -59,6 +65,30 @@ internal class FileData(filePath: String, accessFlag: FileAccessFlags) : DataAcc
|
|||
}
|
||||
}
|
||||
|
||||
fun fileLastAccessed(filepath: String): Long {
|
||||
return try {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
Files.readAttributes<BasicFileAttributes>(FileSystems.getDefault().getPath(filepath), BasicFileAttributes::class.java).lastAccessTime().to(TimeUnit.SECONDS)
|
||||
} else {
|
||||
0L
|
||||
}
|
||||
} catch (e: SecurityException) {
|
||||
0L
|
||||
}
|
||||
}
|
||||
|
||||
fun fileSize(filepath: String): Long {
|
||||
return try {
|
||||
if (File(filepath).isFile) {
|
||||
File(filepath).length()
|
||||
} else {
|
||||
-1L
|
||||
}
|
||||
} catch (e: SecurityException) {
|
||||
-1L
|
||||
}
|
||||
}
|
||||
|
||||
fun delete(filepath: String): Boolean {
|
||||
return try {
|
||||
File(filepath).delete()
|
||||
|
|
|
|||
|
|
@ -212,6 +212,20 @@ internal class MediaStoreData(context: Context, filePath: String, accessFlag: Fi
|
|||
return dataItem.dateModified.toLong() / 1000L
|
||||
}
|
||||
|
||||
fun fileLastAccessed(@Suppress("UNUSED_PARAMETER") context: Context, @Suppress("UNUSED_PARAMETER") path: String): Long {
|
||||
return 0L
|
||||
}
|
||||
|
||||
fun fileSize(context: Context, path: String): Long {
|
||||
val result = queryByPath(context, path)
|
||||
if (result.isEmpty()) {
|
||||
return -1L
|
||||
}
|
||||
|
||||
val dataItem = result[0]
|
||||
return dataItem.size.toLong()
|
||||
}
|
||||
|
||||
fun rename(context: Context, from: String, to: String): Boolean {
|
||||
// Ensure the source exists.
|
||||
val sources = queryByPath(context, from)
|
||||
|
|
|
|||
|
|
@ -90,6 +90,9 @@ object GameMenuUtils {
|
|||
@JvmStatic
|
||||
external fun playMainScene()
|
||||
|
||||
@JvmStatic
|
||||
external fun setDebugMuteAudio(enabled: Boolean)
|
||||
|
||||
/**
|
||||
* Returns [GameEmbedMode] stored in the editor settings.
|
||||
*
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue