diff options
25 files changed, 279 insertions, 36 deletions
diff --git a/doc/classes/AudioStreamPlayer.xml b/doc/classes/AudioStreamPlayer.xml index 89fc18476b..0eadf27c4d 100644 --- a/doc/classes/AudioStreamPlayer.xml +++ b/doc/classes/AudioStreamPlayer.xml @@ -21,6 +21,7 @@ <return type="AudioStreamPlayback"> </return> <description> + Returns the [AudioStreamPlayback] object associated with this [AudioStreamPlayer]. </description> </method> <method name="play"> @@ -69,6 +70,7 @@ The [AudioStream] object to be played. </member> <member name="stream_paused" type="bool" setter="set_stream_paused" getter="get_stream_paused" default="false"> + If [code]true[/code], the playback is paused. You can resume it by setting [code]stream_paused[/code] to [code]false[/code]. </member> <member name="volume_db" type="float" setter="set_volume_db" getter="get_volume_db" default="0.0"> Volume of sound, in dB. diff --git a/doc/classes/AudioStreamPlayer2D.xml b/doc/classes/AudioStreamPlayer2D.xml index 4734aff770..ec3b7872b7 100644 --- a/doc/classes/AudioStreamPlayer2D.xml +++ b/doc/classes/AudioStreamPlayer2D.xml @@ -21,6 +21,7 @@ <return type="AudioStreamPlayback"> </return> <description> + Returns the [AudioStreamPlayback] object associated with this [AudioStreamPlayer2D]. </description> </method> <method name="play"> @@ -75,6 +76,7 @@ The [AudioStream] object to be played. </member> <member name="stream_paused" type="bool" setter="set_stream_paused" getter="get_stream_paused" default="false"> + If [code]true[/code], the playback is paused. You can resume it by setting [code]stream_paused[/code] to [code]false[/code]. </member> <member name="volume_db" type="float" setter="set_volume_db" getter="get_volume_db" default="0.0"> Base volume without dampening. diff --git a/doc/classes/AudioStreamPlayer3D.xml b/doc/classes/AudioStreamPlayer3D.xml index a73f96d082..5e12e06650 100644 --- a/doc/classes/AudioStreamPlayer3D.xml +++ b/doc/classes/AudioStreamPlayer3D.xml @@ -21,6 +21,7 @@ <return type="AudioStreamPlayback"> </return> <description> + Returns the [AudioStreamPlayback] object associated with this [AudioStreamPlayer3D]. </description> </method> <method name="play"> @@ -99,6 +100,7 @@ The [AudioStream] object to be played. </member> <member name="stream_paused" type="bool" setter="set_stream_paused" getter="get_stream_paused" default="false"> + If [code]true[/code], the playback is paused. You can resume it by setting [code]stream_paused[/code] to [code]false[/code]. </member> <member name="unit_db" type="float" setter="set_unit_db" getter="get_unit_db" default="0.0"> Base sound level unaffected by dampening, in dB. diff --git a/doc/classes/Engine.xml b/doc/classes/Engine.xml index 187e13d7bd..04e203793b 100644 --- a/doc/classes/Engine.xml +++ b/doc/classes/Engine.xml @@ -85,6 +85,7 @@ <argument index="0" name="name" type="String"> </argument> <description> + Returns a global singleton with given [code]name[/code]. Often used for plugins, e.g. GodotPayments. </description> </method> <method name="get_version_info" qualifiers="const"> @@ -116,6 +117,7 @@ <argument index="0" name="name" type="String"> </argument> <description> + Returns [code]true[/code] if a singleton with given [code]name[/code] exists in global scope. </description> </method> <method name="is_in_physics_frame" qualifiers="const"> @@ -134,6 +136,7 @@ The number of fixed iterations per second (for fixed process and physics). </member> <member name="physics_jitter_fix" type="float" setter="set_physics_jitter_fix" getter="get_physics_jitter_fix" default="0.5"> + Controls how much physic ticks are synchronized with real time. For 0 or less, the ticks are synchronized. Such values are recommended for network games, where clock synchronization matters. Higher values cause higher deviation of in-game clock and real clock, but allows to smooth out framerate jitters. The default value of 0.5 should be fine for most; values above 2 could cause the game to react to dropped frames with a noticeable delay and are not recommended. </member> <member name="target_fps" type="int" setter="set_target_fps" getter="get_target_fps" default="0"> The desired frames per second. If the hardware cannot keep up, this setting may not be respected. A value of 0 means no limit. diff --git a/doc/classes/HScrollBar.xml b/doc/classes/HScrollBar.xml index 14ace8bc76..90f14dd344 100644 --- a/doc/classes/HScrollBar.xml +++ b/doc/classes/HScrollBar.xml @@ -4,7 +4,7 @@ Horizontal scroll bar. </brief_description> <description> - Horizontal scroll bar. See [ScrollBar]. This one goes from left (min) to right (max). + Horizontal version of [ScrollBar], which goes from left (min) to right (max). </description> <tutorials> </tutorials> @@ -14,22 +14,31 @@ </constants> <theme_items> <theme_item name="decrement" type="Texture"> + Icon used as a button to scroll the [ScrollBar] left. Supports custom step using the [member ScrollBar.custom_step] property. </theme_item> <theme_item name="decrement_highlight" type="Texture"> + Displayed when the mouse cursor hovers over the decrement button. </theme_item> <theme_item name="grabber" type="StyleBox"> + Used as texture for the grabber, the draggable element representing current scroll. </theme_item> <theme_item name="grabber_highlight" type="StyleBox"> + Used when the mouse hovers over the grabber. </theme_item> <theme_item name="grabber_pressed" type="StyleBox"> + Used when the grabber is being dragged. </theme_item> <theme_item name="increment" type="Texture"> + Icon used as a button to scroll the [ScrollBar] right. Supports custom step using the [member ScrollBar.custom_step] property. </theme_item> <theme_item name="increment_highlight" type="Texture"> + Displayed when the mouse cursor hovers over the increment button. </theme_item> <theme_item name="scroll" type="StyleBox"> + Used as background of this [ScrollBar]. </theme_item> <theme_item name="scroll_focus" type="StyleBox"> + Used as background when the [ScrollBar] has the GUI focus. </theme_item> </theme_items> </class> diff --git a/doc/classes/LineEdit.xml b/doc/classes/LineEdit.xml index 78459d2839..a360010b7e 100644 --- a/doc/classes/LineEdit.xml +++ b/doc/classes/LineEdit.xml @@ -96,7 +96,7 @@ The cursor's position inside the [LineEdit]. When set, the text may scroll to accommodate it. </member> <member name="clear_button_enabled" type="bool" setter="set_clear_button_enabled" getter="is_clear_button_enabled" default="false"> - If [code]true[/code], the [LineEdit] will show a clear button if [code]text[/code] is not empty. + If [code]true[/code], the [LineEdit] will show a clear button if [code]text[/code] is not empty, which can be used to clear the text quickly. </member> <member name="context_menu_enabled" type="bool" setter="set_context_menu_enabled" getter="is_context_menu_enabled" default="true"> If [code]true[/code], the context menu will appear when right-clicked. @@ -128,8 +128,10 @@ The character to use to mask secret input (defaults to "*"). Only a single character can be used as the secret character. </member> <member name="selecting_enabled" type="bool" setter="set_selecting_enabled" getter="is_selecting_enabled" default="true"> + If [code]false[/code], it's impossible to select the text using mouse nor keyboard. </member> <member name="shortcut_keys_enabled" type="bool" setter="set_shortcut_keys_enabled" getter="is_shortcut_keys_enabled" default="true"> + If [code]false[/code], using shortcuts will be disabled. </member> <member name="text" type="String" setter="set_text" getter="get_text" default=""""> String value of the [LineEdit]. @@ -192,30 +194,43 @@ </constants> <theme_items> <theme_item name="clear" type="Texture"> + Texture for the clear button. See [member clear_button_enabled]. </theme_item> <theme_item name="clear_button_color" type="Color" default="Color( 0.88, 0.88, 0.88, 1 )"> + Color used as default tint for the clear button. </theme_item> <theme_item name="clear_button_color_pressed" type="Color" default="Color( 1, 1, 1, 1 )"> + Color used for the clear button when it's pressed. </theme_item> <theme_item name="cursor_color" type="Color" default="Color( 0.94, 0.94, 0.94, 1 )"> + Color of the [LineEdit]'s visual cursor (caret). </theme_item> <theme_item name="focus" type="StyleBox"> + Background used when [LineEdit] has GUI focus. </theme_item> <theme_item name="font" type="Font"> + Font used for the text. </theme_item> <theme_item name="font_color" type="Color" default="Color( 0.88, 0.88, 0.88, 1 )"> + Default font color. </theme_item> <theme_item name="font_color_selected" type="Color" default="Color( 0, 0, 0, 1 )"> + Font color for selected text (inside the selection rectangle). </theme_item> <theme_item name="font_color_uneditable" type="Color" default="Color( 0.88, 0.88, 0.88, 0.5 )"> + Font color when editing is disabled. </theme_item> <theme_item name="minimum_spaces" type="int" default="12"> + Minimum horizontal space for the text (not counting the clear button and content margins). </theme_item> <theme_item name="normal" type="StyleBox"> + Default background for the [LineEdit]. </theme_item> <theme_item name="read_only" type="StyleBox"> + Background used when [LineEdit] is in read-only mode ([member editable] is set to [code]false[/code]). </theme_item> <theme_item name="selection_color" type="Color" default="Color( 0.49, 0.49, 0.49, 1 )"> + Color of the selection rectangle. </theme_item> </theme_items> </class> diff --git a/doc/classes/ScrollBar.xml b/doc/classes/ScrollBar.xml index ea30b9d48c..e4ace8e8ae 100644 --- a/doc/classes/ScrollBar.xml +++ b/doc/classes/ScrollBar.xml @@ -12,6 +12,7 @@ </methods> <members> <member name="custom_step" type="float" setter="set_custom_step" getter="get_custom_step" default="-1.0"> + Overrides the step used when clicking increment and decrement buttons or when using arrow keys when the [ScrollBar] is focused. </member> <member name="size_flags_vertical" type="int" setter="set_v_size_flags" getter="get_v_size_flags" override="true" default="0" /> <member name="step" type="float" setter="set_step" getter="get_step" override="true" default="0.0" /> diff --git a/doc/classes/VScrollBar.xml b/doc/classes/VScrollBar.xml index 6240178b82..add695ef2c 100644 --- a/doc/classes/VScrollBar.xml +++ b/doc/classes/VScrollBar.xml @@ -1,9 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="VScrollBar" inherits="ScrollBar" category="Core" version="3.2"> <brief_description> - Vertical version of [ScrollBar], which goes from top (min) to bottom (max). + Vertical scroll bar. </brief_description> <description> + Vertical version of [ScrollBar], which goes from top (min) to bottom (max). </description> <tutorials> </tutorials> @@ -17,22 +18,31 @@ </constants> <theme_items> <theme_item name="decrement" type="Texture"> + Icon used as a button to scroll the [ScrollBar] up. Supports custom step using the [member ScrollBar.custom_step] property. </theme_item> <theme_item name="decrement_highlight" type="Texture"> + Displayed when the mouse cursor hovers over the decrement button. </theme_item> <theme_item name="grabber" type="StyleBox"> + Used as texture for the grabber, the draggable element representing current scroll. </theme_item> <theme_item name="grabber_highlight" type="StyleBox"> + Used when the mouse hovers over the grabber. </theme_item> <theme_item name="grabber_pressed" type="StyleBox"> + Used when the grabber is being dragged. </theme_item> <theme_item name="increment" type="Texture"> + Icon used as a button to scroll the [ScrollBar] down. Supports custom step using the [member ScrollBar.custom_step] property. </theme_item> <theme_item name="increment_highlight" type="Texture"> + Displayed when the mouse cursor hovers over the increment button. </theme_item> <theme_item name="scroll" type="StyleBox"> + Used as background of this [ScrollBar]. </theme_item> <theme_item name="scroll_focus" type="StyleBox"> + Used as background when the [ScrollBar] has the GUI focus. </theme_item> </theme_items> </class> diff --git a/doc/classes/VisibilityEnabler.xml b/doc/classes/VisibilityEnabler.xml index e3c7d05fce..56fa7b77a9 100644 --- a/doc/classes/VisibilityEnabler.xml +++ b/doc/classes/VisibilityEnabler.xml @@ -15,6 +15,7 @@ <argument index="0" name="enabler" type="int" enum="VisibilityEnabler.Enabler"> </argument> <description> + Returns whether the enabler identified by given [enum Enabler] constant is active. </description> </method> <method name="set_enabler"> @@ -25,6 +26,7 @@ <argument index="1" name="enabled" type="bool"> </argument> <description> + Sets active state of the enabler identified by given [enum Enabler] constant. </description> </method> </methods> diff --git a/doc/classes/VisibilityEnabler2D.xml b/doc/classes/VisibilityEnabler2D.xml index 96f6a42cdf..547793c385 100644 --- a/doc/classes/VisibilityEnabler2D.xml +++ b/doc/classes/VisibilityEnabler2D.xml @@ -15,6 +15,7 @@ <argument index="0" name="enabler" type="int" enum="VisibilityEnabler2D.Enabler"> </argument> <description> + Returns whether the enabler identified by given [enum Enabler] constant is active. </description> </method> <method name="set_enabler"> @@ -25,6 +26,7 @@ <argument index="1" name="enabled" type="bool"> </argument> <description> + Sets active state of the enabler identified by given [enum Enabler] constant. </description> </method> </methods> @@ -65,6 +67,7 @@ This enabler will stop the parent's _physics_process function. </constant> <constant name="ENABLER_PAUSE_ANIMATED_SPRITES" value="5" enum="Enabler"> + This enabler will stop [AnimatedSprite] nodes animations. </constant> <constant name="ENABLER_MAX" value="6" enum="Enabler"> Represents the size of the [enum Enabler] enum. diff --git a/main/main.cpp b/main/main.cpp index 7ff283bab0..5cfab3dc4a 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -1402,6 +1402,7 @@ bool Main::start() { bool hasicon = false; String doc_tool; List<String> removal_docs; + String positional_arg; String game_path; String script; String test; @@ -1429,8 +1430,18 @@ bool Main::start() { } else if (args[i] == "-p" || args[i] == "--project-manager") { project_manager = true; #endif - } else if (args[i].length() && args[i][0] != '-' && game_path == "") { - game_path = args[i]; + } else if (args[i].length() && args[i][0] != '-' && positional_arg == "") { + positional_arg = args[i]; + + if (args[i].ends_with(".scn") || args[i].ends_with(".tscn") || args[i].ends_with(".escn")) { + // Only consider the positional argument to be a scene path if it ends with + // a file extension associated with Godot scenes. This makes it possible + // for projects to parse command-line arguments for custom CLI arguments + // or other file extensions without trouble. This can be used to implement + // "drag-and-drop onto executable" logic, which can prove helpful + // for non-game applications. + game_path = args[i]; + } } //parameters that have an argument to the right else if (i < (args.size() - 1)) { @@ -1525,7 +1536,7 @@ bool Main::start() { } if (_export_preset != "") { - if (game_path == "") { + if (positional_arg == "") { String err = "Command line includes export parameter option, but no destination path was given.\n"; err += "Please specify the binary's file path to export to. Aborting export."; ERR_PRINT(err); @@ -1716,7 +1727,7 @@ bool Main::start() { sml->get_root()->add_child(editor_node); if (_export_preset != "") { - editor_node->export_preset(_export_preset, game_path, export_debug, export_pack_only); + editor_node->export_preset(_export_preset, positional_arg, export_debug, export_pack_only); game_path = ""; // Do not load anything. } } diff --git a/modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml b/modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml index 9403199398..102a9b4236 100644 --- a/modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml +++ b/modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml @@ -15,8 +15,10 @@ Contains the audio data in bytes. </member> <member name="loop" type="bool" setter="set_loop" getter="has_loop" default="false"> + If [code]true[/code], the stream will automatically loop when it reaches the end. </member> <member name="loop_offset" type="float" setter="set_loop_offset" getter="get_loop_offset" default="0.0"> + Time in seconds at which the stream starts after being looped. </member> </members> <constants> diff --git a/platform/android/dir_access_jandroid.cpp b/platform/android/dir_access_jandroid.cpp index 69178317f7..f52b511522 100644 --- a/platform/android/dir_access_jandroid.cpp +++ b/platform/android/dir_access_jandroid.cpp @@ -110,7 +110,6 @@ String DirAccessJAndroid::get_drive(int p_drive) { Error DirAccessJAndroid::change_dir(String p_dir) { JNIEnv *env = ThreadAndroid::get_env(); - p_dir = p_dir.simplify_path(); if (p_dir == "" || p_dir == "." || (p_dir == ".." && current_dir == "")) return OK; diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java index 8447af10e4..0ff37e3c37 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java @@ -100,6 +100,16 @@ public class GodotLib { public static native void hover(int type, int x, int y); /** + * Forward double_tap events from the main thread to the GL thread. + */ + public static native void double_tap(int x, int y); + + /** + * Forward scroll events from the main thread to the GL thread. + */ + public static native void scroll(int x, int y); + + /** * Forward accelerometer sensor events from the main thread to the GL thread. * @see android.hardware.SensorEventListener#onSensorChanged(SensorEvent) */ diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotView.java index 78f3763d84..f938583082 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotView.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotView.java @@ -32,8 +32,10 @@ package org.godotengine.godot; import android.annotation.SuppressLint; import android.graphics.PixelFormat; import android.opengl.GLSurfaceView; +import android.view.GestureDetector; import android.view.KeyEvent; import android.view.MotionEvent; +import org.godotengine.godot.input.GodotGestureHandler; import org.godotengine.godot.input.GodotInputHandler; import org.godotengine.godot.utils.GLUtils; import org.godotengine.godot.xr.XRMode; @@ -68,6 +70,7 @@ public class GodotView extends GLSurfaceView { private final Godot activity; private final GodotInputHandler inputHandler; + private final GestureDetector detector; private final GodotRenderer godotRenderer; public GodotView(Godot activity, XRMode xrMode, boolean p_use_gl3, boolean p_use_32_bits, boolean p_use_debug_opengl) { @@ -78,6 +81,7 @@ public class GodotView extends GLSurfaceView { this.activity = activity; this.inputHandler = new GodotInputHandler(this); + this.detector = new GestureDetector(activity, new GodotGestureHandler(this)); this.godotRenderer = new GodotRenderer(); init(xrMode, false, 16, 0); } @@ -90,6 +94,7 @@ public class GodotView extends GLSurfaceView { @Override public boolean onTouchEvent(MotionEvent event) { super.onTouchEvent(event); + this.detector.onTouchEvent(event); return activity.gotTouchEvent(event); } diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.java new file mode 100644 index 0000000000..b42b13894c --- /dev/null +++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.java @@ -0,0 +1,106 @@ +/*************************************************************************/ +/* GodotGestureHandler.java */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +package org.godotengine.godot.input; + +import android.util.Log; +import android.view.GestureDetector; +import android.view.MotionEvent; +import org.godotengine.godot.GodotLib; +import org.godotengine.godot.GodotView; + +/** + * Handles gesture input related events for the {@link GodotView} view. + * https://developer.android.com/reference/android/view/GestureDetector.SimpleOnGestureListener + */ +public class GodotGestureHandler extends GestureDetector.SimpleOnGestureListener { + + private final GodotView godotView; + + public GodotGestureHandler(GodotView godotView) { + this.godotView = godotView; + } + + private void queueEvent(Runnable task) { + godotView.queueEvent(task); + } + + @Override + public boolean onDown(MotionEvent event) { + super.onDown(event); + //Log.i("GodotGesture", "onDown"); + return true; + } + + @Override + public boolean onSingleTapConfirmed(MotionEvent event) { + super.onSingleTapConfirmed(event); + return true; + } + + @Override + public void onLongPress(MotionEvent event) { + //Log.i("GodotGesture", "onLongPress"); + } + + @Override + public boolean onDoubleTap(MotionEvent event) { + //Log.i("GodotGesture", "onDoubleTap"); + final int x = Math.round(event.getX()); + final int y = Math.round(event.getY()); + queueEvent(new Runnable() { + @Override + public void run() { + GodotLib.double_tap(x, y); + } + }); + return true; + } + + @Override + public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { + //Log.i("GodotGesture", "onScroll"); + final int x = Math.round(distanceX); + final int y = Math.round(distanceY); + queueEvent(new Runnable() { + @Override + public void run() { + GodotLib.scroll(x, y); + } + }); + return true; + } + + @Override + public boolean onFling(MotionEvent event1, MotionEvent event2, float velocityX, float velocityY) { + //Log.i("GodotGesture", "onFling"); + return true; + } +} diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp index 0a32f4423b..d3bc216608 100644 --- a/platform/android/java_godot_lib_jni.cpp +++ b/platform/android/java_godot_lib_jni.cpp @@ -835,6 +835,20 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_hover(JNIEnv *env, jo os_android->process_hover(p_type, Point2(p_x, p_y)); } +JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_double_tap(JNIEnv *env, jobject obj, jint p_x, jint p_y) { + if (step == 0) + return; + + os_android->process_double_tap(Point2(p_x, p_y)); +} + +JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_scroll(JNIEnv *env, jobject obj, jint p_x, jint p_y) { + if (step == 0) + return; + + os_android->process_scroll(Point2(p_x, p_y)); +} + /* * Android Key codes. */ diff --git a/platform/android/java_godot_lib_jni.h b/platform/android/java_godot_lib_jni.h index 8c18c52d2b..08029c3c30 100644 --- a/platform/android/java_godot_lib_jni.h +++ b/platform/android/java_godot_lib_jni.h @@ -46,6 +46,8 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, job JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_back(JNIEnv *env, jobject obj); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_touch(JNIEnv *env, jobject obj, jint ev, jint pointer, jint count, jintArray positions); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_hover(JNIEnv *env, jobject obj, jint p_type, jint p_x, jint p_y); +JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_double_tap(JNIEnv *env, jobject obj, jint p_x, jint p_y); +JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_scroll(JNIEnv *env, jobject obj, jint p_x, jint p_y); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_key(JNIEnv *env, jobject obj, jint p_scancode, jint p_unicode_char, jboolean p_pressed); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joybutton(JNIEnv *env, jobject obj, jint p_device, jint p_button, jboolean p_pressed); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyaxis(JNIEnv *env, jobject obj, jint p_device, jint p_axis, jfloat p_value); diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index 4c560273e8..bbea5e3699 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -502,6 +502,26 @@ void OS_Android::process_hover(int p_type, Point2 p_pos) { } } +void OS_Android::process_double_tap(Point2 p_pos) { + Ref<InputEventMouseButton> ev; + ev.instance(); + ev->set_position(p_pos); + ev->set_global_position(p_pos); + ev->set_pressed(true); + ev->set_doubleclick(true); + ev->set_button_index(1); + input->parse_input_event(ev); +} + +void OS_Android::process_scroll(Point2 p_pos) { + Ref<InputEventPanGesture> ev; + ev.instance(); + ev->set_position(p_pos); + ev->set_delta(p_pos - scroll_prev_pos); + input->parse_input_event(ev); + scroll_prev_pos = p_pos; +} + void OS_Android::process_accelerometer(const Vector3 &p_accelerometer) { input->set_accelerometer(p_accelerometer); diff --git a/platform/android/os_android.h b/platform/android/os_android.h index 5ac50ddef2..1cf64a2e84 100644 --- a/platform/android/os_android.h +++ b/platform/android/os_android.h @@ -70,6 +70,7 @@ public: private: Vector<TouchPos> touch; 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 bool use_gl2; bool use_apk_expansion; @@ -187,6 +188,8 @@ public: void process_gyroscope(const Vector3 &p_gyroscope); void process_touch(int p_what, int p_pointer, const Vector<TouchPos> &p_points); void process_hover(int p_type, Point2 p_pos); + void process_double_tap(Point2 p_pos); + void process_scroll(Point2 p_pos); void process_joy_event(JoypadEvent p_event); void process_event(Ref<InputEvent> p_event); void init_video_mode(int p_video_width, int p_video_height); diff --git a/platform/x11/crash_handler_x11.cpp b/platform/x11/crash_handler_x11.cpp index 3a91c62546..19c8f71d0e 100644 --- a/platform/x11/crash_handler_x11.cpp +++ b/platform/x11/crash_handler_x11.cpp @@ -107,7 +107,7 @@ static void handle_crash(int sig) { output.erase(output.length() - 1, 1); } - fprintf(stderr, "[%ld] %s (%ls)\n", i, fname, output.c_str()); + fprintf(stderr, "[%ld] %s (%ls)\n", (long int)i, fname, output.c_str()); } free(strings); diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 3fd0bef7e9..90663bd675 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -1212,7 +1212,7 @@ bool KinematicBody2D::move_and_collide(const Vector2 &p_motion, bool p_infinite_ //so, if you pass 45 as limit, avoid numerical precision errors when angle is 45. #define FLOOR_ANGLE_THRESHOLD 0.01 -Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_floor_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) { +Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_up_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) { Vector2 body_velocity = p_linear_velocity; Vector2 body_velocity_normal = body_velocity.normalized(); @@ -1234,6 +1234,7 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const on_ceiling = false; on_wall = false; colliders.clear(); + floor_normal = p_up_direction; floor_velocity = Vector2(); while (p_max_slides) { @@ -1262,25 +1263,26 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const colliders.push_back(collision); motion = collision.remainder; - if (p_floor_direction == Vector2()) { + if (p_up_direction == Vector2()) { //all is a wall on_wall = true; } else { - if (Math::acos(collision.normal.dot(p_floor_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor + if (Math::acos(collision.normal.dot(p_up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor on_floor = true; + floor_normal = collision.normal; on_floor_body = collision.collider_rid; floor_velocity = collision.collider_vel; if (p_stop_on_slope) { - if ((body_velocity_normal + p_floor_direction).length() < 0.01 && collision.travel.length() < 1) { + if ((body_velocity_normal + p_up_direction).length() < 0.01 && collision.travel.length() < 1) { Transform2D gt = get_global_transform(); - gt.elements[2] -= collision.travel.slide(p_floor_direction); + gt.elements[2] -= collision.travel.slide(p_up_direction); set_global_transform(gt); return Vector2(); } } - } else if (Math::acos(collision.normal.dot(-p_floor_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling + } else if (Math::acos(collision.normal.dot(-p_up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling on_ceiling = true; } else { on_wall = true; @@ -1301,11 +1303,11 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const return body_velocity; } -Vector2 KinematicBody2D::move_and_slide_with_snap(const Vector2 &p_linear_velocity, const Vector2 &p_snap, const Vector2 &p_floor_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) { +Vector2 KinematicBody2D::move_and_slide_with_snap(const Vector2 &p_linear_velocity, const Vector2 &p_snap, const Vector2 &p_up_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) { bool was_on_floor = on_floor; - Vector2 ret = move_and_slide(p_linear_velocity, p_floor_direction, p_stop_on_slope, p_max_slides, p_floor_max_angle, p_infinite_inertia); + Vector2 ret = move_and_slide(p_linear_velocity, p_up_direction, p_stop_on_slope, p_max_slides, p_floor_max_angle, p_infinite_inertia); if (!was_on_floor || p_snap == Vector2()) { return ret; } @@ -1315,15 +1317,16 @@ Vector2 KinematicBody2D::move_and_slide_with_snap(const Vector2 &p_linear_veloci if (move_and_collide(p_snap, p_infinite_inertia, col, false, true)) { bool apply = true; - if (p_floor_direction != Vector2()) { - if (Math::acos(p_floor_direction.normalized().dot(col.normal)) < p_floor_max_angle) { + if (p_up_direction != Vector2()) { + if (Math::acos(p_up_direction.normalized().dot(col.normal)) < p_floor_max_angle) { on_floor = true; + floor_normal = col.normal; on_floor_body = col.collider_rid; floor_velocity = col.collider_vel; if (p_stop_on_slope) { // move and collide may stray the object a bit because of pre un-stucking, // so only ensure that motion happens on floor direction in this case. - col.travel = p_floor_direction * p_floor_direction.dot(col.travel); + col.travel = p_up_direction * p_up_direction.dot(col.travel); } } else { @@ -1353,6 +1356,11 @@ bool KinematicBody2D::is_on_ceiling() const { return on_ceiling; } +Vector2 KinematicBody2D::get_floor_normal() const { + + return floor_normal; +} + Vector2 KinematicBody2D::get_floor_velocity() const { return floor_velocity; @@ -1473,6 +1481,7 @@ void KinematicBody2D::_bind_methods() { ClassDB::bind_method(D_METHOD("is_on_floor"), &KinematicBody2D::is_on_floor); ClassDB::bind_method(D_METHOD("is_on_ceiling"), &KinematicBody2D::is_on_ceiling); ClassDB::bind_method(D_METHOD("is_on_wall"), &KinematicBody2D::is_on_wall); + ClassDB::bind_method(D_METHOD("get_floor_normal"), &KinematicBody2D::get_floor_normal); ClassDB::bind_method(D_METHOD("get_floor_velocity"), &KinematicBody2D::get_floor_velocity); ClassDB::bind_method(D_METHOD("set_safe_margin", "pixels"), &KinematicBody2D::set_safe_margin); diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h index 7f2b42b554..6766bafde3 100644 --- a/scene/2d/physics_body_2d.h +++ b/scene/2d/physics_body_2d.h @@ -306,6 +306,7 @@ public: private: float margin; + Vector2 floor_normal; Vector2 floor_velocity; RID on_floor_body; bool on_floor; @@ -339,11 +340,12 @@ public: void set_safe_margin(float p_margin); float get_safe_margin() const; - Vector2 move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_floor_direction = Vector2(0, 0), bool p_stop_on_slope = false, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45), bool p_infinite_inertia = true); - Vector2 move_and_slide_with_snap(const Vector2 &p_linear_velocity, const Vector2 &p_snap, const Vector2 &p_floor_direction = Vector2(0, 0), bool p_stop_on_slope = false, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45), bool p_infinite_inertia = true); + Vector2 move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_up_direction = Vector2(0, 0), bool p_stop_on_slope = false, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45), bool p_infinite_inertia = true); + Vector2 move_and_slide_with_snap(const Vector2 &p_linear_velocity, const Vector2 &p_snap, const Vector2 &p_up_direction = Vector2(0, 0), bool p_stop_on_slope = false, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45), bool p_infinite_inertia = true); bool is_on_floor() const; bool is_on_wall() const; bool is_on_ceiling() const; + Vector2 get_floor_normal() const; Vector2 get_floor_velocity() const; int get_slide_count() const; diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index c2860c25d8..999f39c841 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -1140,7 +1140,7 @@ bool KinematicBody::move_and_collide(const Vector3 &p_motion, bool p_infinite_in //so, if you pass 45 as limit, avoid numerical precision errors when angle is 45. #define FLOOR_ANGLE_THRESHOLD 0.01 -Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_floor_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) { +Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_up_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) { Vector3 body_velocity = p_linear_velocity; Vector3 body_velocity_normal = body_velocity.normalized(); @@ -1159,6 +1159,7 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve on_ceiling = false; on_wall = false; colliders.clear(); + floor_normal = p_up_direction; floor_velocity = Vector3(); while (p_max_slides) { @@ -1187,25 +1188,26 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve colliders.push_back(collision); motion = collision.remainder; - if (p_floor_direction == Vector3()) { + if (p_up_direction == Vector3()) { //all is a wall on_wall = true; } else { - if (Math::acos(collision.normal.dot(p_floor_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor + if (Math::acos(collision.normal.dot(p_up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor on_floor = true; + floor_normal = collision.normal; on_floor_body = collision.collider_rid; floor_velocity = collision.collider_vel; if (p_stop_on_slope) { - if ((body_velocity_normal + p_floor_direction).length() < 0.01 && collision.travel.length() < 1) { + if ((body_velocity_normal + p_up_direction).length() < 0.01 && collision.travel.length() < 1) { Transform gt = get_global_transform(); - gt.origin -= collision.travel.slide(p_floor_direction); + gt.origin -= collision.travel.slide(p_up_direction); set_global_transform(gt); return Vector3(); } } - } else if (Math::acos(collision.normal.dot(-p_floor_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling + } else if (Math::acos(collision.normal.dot(-p_up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling on_ceiling = true; } else { on_wall = true; @@ -1232,11 +1234,11 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve return body_velocity; } -Vector3 KinematicBody::move_and_slide_with_snap(const Vector3 &p_linear_velocity, const Vector3 &p_snap, const Vector3 &p_floor_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) { +Vector3 KinematicBody::move_and_slide_with_snap(const Vector3 &p_linear_velocity, const Vector3 &p_snap, const Vector3 &p_up_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) { bool was_on_floor = on_floor; - Vector3 ret = move_and_slide(p_linear_velocity, p_floor_direction, p_stop_on_slope, p_max_slides, p_floor_max_angle, p_infinite_inertia); + Vector3 ret = move_and_slide(p_linear_velocity, p_up_direction, p_stop_on_slope, p_max_slides, p_floor_max_angle, p_infinite_inertia); if (!was_on_floor || p_snap == Vector3()) { return ret; } @@ -1247,15 +1249,16 @@ Vector3 KinematicBody::move_and_slide_with_snap(const Vector3 &p_linear_velocity if (move_and_collide(p_snap, p_infinite_inertia, col, false, true)) { bool apply = true; - if (p_floor_direction != Vector3()) { - if (Math::acos(p_floor_direction.normalized().dot(col.normal)) < p_floor_max_angle) { + if (p_up_direction != Vector3()) { + if (Math::acos(p_up_direction.normalized().dot(col.normal)) < p_floor_max_angle) { on_floor = true; + floor_normal = col.normal; on_floor_body = col.collider_rid; floor_velocity = col.collider_vel; if (p_stop_on_slope) { // move and collide may stray the object a bit because of pre un-stucking, // so only ensure that motion happens on floor direction in this case. - col.travel = col.travel.project(p_floor_direction); + col.travel = col.travel.project(p_up_direction); } } else { apply = false; //snapped with floor direction, but did not snap to a floor, do not snap. @@ -1284,6 +1287,11 @@ bool KinematicBody::is_on_ceiling() const { return on_ceiling; } +Vector3 KinematicBody::get_floor_normal() const { + + return floor_normal; +} + Vector3 KinematicBody::get_floor_velocity() const { return floor_velocity; @@ -1392,7 +1400,7 @@ void KinematicBody::_notification(int p_what) { void KinematicBody::_bind_methods() { ClassDB::bind_method(D_METHOD("move_and_collide", "rel_vec", "infinite_inertia", "exclude_raycast_shapes", "test_only"), &KinematicBody::_move, DEFVAL(true), DEFVAL(true), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "floor_normal", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody::move_and_slide, DEFVAL(Vector3(0, 0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)), DEFVAL(true)); + ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "up_direction", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody::move_and_slide, DEFVAL(Vector3(0, 0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)), DEFVAL(true)); ClassDB::bind_method(D_METHOD("move_and_slide_with_snap", "linear_velocity", "snap", "floor_normal", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody::move_and_slide_with_snap, DEFVAL(Vector3(0, 0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)), DEFVAL(true)); ClassDB::bind_method(D_METHOD("test_move", "from", "rel_vec", "infinite_inertia"), &KinematicBody::test_move, DEFVAL(true)); @@ -1400,6 +1408,7 @@ void KinematicBody::_bind_methods() { ClassDB::bind_method(D_METHOD("is_on_floor"), &KinematicBody::is_on_floor); ClassDB::bind_method(D_METHOD("is_on_ceiling"), &KinematicBody::is_on_ceiling); ClassDB::bind_method(D_METHOD("is_on_wall"), &KinematicBody::is_on_wall); + ClassDB::bind_method(D_METHOD("get_floor_normal"), &KinematicBody::get_floor_normal); ClassDB::bind_method(D_METHOD("get_floor_velocity"), &KinematicBody::get_floor_velocity); ClassDB::bind_method(D_METHOD("set_axis_lock", "axis", "lock"), &KinematicBody::set_axis_lock); diff --git a/scene/3d/physics_body.h b/scene/3d/physics_body.h index 06b31804b2..05bcbe22f0 100644 --- a/scene/3d/physics_body.h +++ b/scene/3d/physics_body.h @@ -300,6 +300,7 @@ private: float margin; + Vector3 floor_normal; Vector3 floor_velocity; RID on_floor_body; bool on_floor; @@ -330,11 +331,12 @@ public: void set_safe_margin(float p_margin); float get_safe_margin() const; - Vector3 move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_floor_direction = Vector3(0, 0, 0), bool p_stop_on_slope = false, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45), bool p_infinite_inertia = true); - Vector3 move_and_slide_with_snap(const Vector3 &p_linear_velocity, const Vector3 &p_snap, const Vector3 &p_floor_direction = Vector3(0, 0, 0), bool p_stop_on_slope = false, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45), bool p_infinite_inertia = true); + Vector3 move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_up_direction = Vector3(0, 0, 0), bool p_stop_on_slope = false, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45), bool p_infinite_inertia = true); + Vector3 move_and_slide_with_snap(const Vector3 &p_linear_velocity, const Vector3 &p_snap, const Vector3 &p_up_direction = Vector3(0, 0, 0), bool p_stop_on_slope = false, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45), bool p_infinite_inertia = true); bool is_on_floor() const; bool is_on_wall() const; bool is_on_ceiling() const; + Vector3 get_floor_normal() const; Vector3 get_floor_velocity() const; int get_slide_count() const; |