summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--SConstruct5
-rw-r--r--core/class_db.cpp22
-rw-r--r--core/class_db.h1
-rw-r--r--core/global_constants.cpp2
-rw-r--r--core/input_map.cpp4
-rw-r--r--core/node_path.cpp (renamed from core/path_db.cpp)2
-rw-r--r--core/node_path.h (renamed from core/path_db.h)0
-rw-r--r--core/object.cpp21
-rw-r--r--core/object.h5
-rw-r--r--core/os/keyboard.cpp4
-rw-r--r--core/os/keyboard.h4
-rw-r--r--core/project_settings.cpp4
-rw-r--r--core/resource.cpp1
-rw-r--r--core/script_language.cpp33
-rw-r--r--core/variant.h2
-rw-r--r--doc/base/classes.xml4
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp6
-rw-r--r--drivers/gles3/shaders/scene.glsl2
-rw-r--r--drivers/rtaudio/audio_driver_rtaudio.cpp20
-rw-r--r--editor/editor_file_system.cpp4
-rw-r--r--editor/editor_help.cpp18
-rw-r--r--editor/editor_help.h1
-rw-r--r--editor/editor_name_dialog.cpp4
-rw-r--r--editor/editor_themes.cpp11
-rw-r--r--editor/import/editor_scene_importer_gltf.cpp545
-rw-r--r--editor/import/editor_scene_importer_gltf.h50
-rw-r--r--editor/plugins/script_editor_plugin.cpp105
-rw-r--r--editor/plugins/tile_map_editor_plugin.cpp2
-rw-r--r--editor/project_manager.cpp2
-rw-r--r--editor/property_editor.cpp2
-rw-r--r--modules/gdnative/gdnative.cpp10
-rw-r--r--modules/gdnative/gdnative.h1
-rw-r--r--modules/gdnative/godot/dictionary.cpp3
-rw-r--r--modules/gdnative/godot/node_path.cpp2
-rw-r--r--modules/gdnative/godot/variant.cpp1
-rw-r--r--modules/nativescript/nativescript.cpp16
-rw-r--r--modules/visual_script/visual_script_nodes.cpp2
-rw-r--r--platform/android/build.gradle.template4
-rw-r--r--platform/android/java/gradle.properties17
-rw-r--r--platform/android/java/gradle/wrapper/gradle-wrapper.jarbin49896 -> 53636 bytes
-rw-r--r--platform/android/java/gradle/wrapper/gradle-wrapper.properties5
-rwxr-xr-xplatform/android/java/gradlew10
-rw-r--r--platform/haiku/key_mapping_haiku.cpp2
-rw-r--r--platform/javascript/dom_keys.h2
-rw-r--r--platform/osx/os_osx.mm4
-rw-r--r--platform/uwp/joypad_uwp.cpp75
-rw-r--r--platform/uwp/joypad_uwp.h8
-rw-r--r--platform/windows/key_mapping_win.cpp2
-rw-r--r--platform/windows/os_windows.cpp6
-rw-r--r--platform/x11/key_mapping_x11.cpp4
-rw-r--r--platform/x11/os_x11.cpp4
-rw-r--r--scene/2d/animated_sprite.cpp1
-rw-r--r--scene/2d/node_2d.cpp4
-rw-r--r--scene/2d/node_2d.h2
-rw-r--r--scene/2d/physics_body_2d.cpp34
-rw-r--r--scene/2d/physics_body_2d.h3
-rw-r--r--scene/2d/sprite.cpp4
-rw-r--r--scene/2d/visibility_notifier_2d.cpp1
-rw-r--r--scene/3d/physics_body.cpp31
-rw-r--r--scene/3d/physics_body.h2
-rw-r--r--scene/3d/sprite_3d.cpp4
-rw-r--r--scene/3d/visibility_notifier.cpp2
-rw-r--r--scene/animation/animation_player.cpp2
-rw-r--r--scene/gui/base_button.cpp2
-rw-r--r--scene/gui/line_edit.cpp4
-rw-r--r--scene/gui/popup_menu.cpp4
-rw-r--r--scene/gui/text_edit.cpp6
-rw-r--r--scene/gui/tree.cpp8
-rwxr-xr-xscene/main/node.cpp71
-rw-r--r--scene/main/node.h2
-rw-r--r--scene/resources/packed_scene.cpp3
-rw-r--r--scene/resources/texture.cpp3
-rw-r--r--scene/scene_string_names.cpp8
-rw-r--r--scene/scene_string_names.h4
-rw-r--r--servers/audio_server.cpp5
75 files changed, 1046 insertions, 228 deletions
diff --git a/SConstruct b/SConstruct
index 4085f713b7..45765976cd 100644
--- a/SConstruct
+++ b/SConstruct
@@ -461,7 +461,8 @@ screen = sys.stdout
node_count = 0
node_count_max = 0
node_count_interval = 1
-node_count_fname = str(env.Dir('#')) + '/.scons_node_count'
+if ('env' in locals()):
+ node_count_fname = str(env.Dir('#')) + '/.scons_node_count'
def progress_function(node):
global node_count, node_count_max, node_count_interval, node_count_fname
@@ -481,7 +482,7 @@ def progress_finish(target, source, env):
with open(node_count_fname, 'w') as f:
f.write('%d\n' % node_count)
-if (env["progress"] == "yes"):
+if ('env' in locals() and env["progress"] == "yes"):
try:
with open(node_count_fname) as f:
node_count_max = int(f.readline())
diff --git a/core/class_db.cpp b/core/class_db.cpp
index 6b8c290a99..24d71f86b0 100644
--- a/core/class_db.cpp
+++ b/core/class_db.cpp
@@ -937,6 +937,28 @@ bool ClassDB::get_property(Object *p_object, const StringName &p_property, Varia
return false;
}
+int ClassDB::get_property_index(const StringName &p_class, const StringName &p_property, bool *r_is_valid) {
+
+ ClassInfo *type = classes.getptr(p_class);
+ ClassInfo *check = type;
+ while (check) {
+ const PropertySetGet *psg = check->property_setget.getptr(p_property);
+ if (psg) {
+
+ if (r_is_valid)
+ *r_is_valid = true;
+
+ return psg->index;
+ }
+
+ check = check->inherits_ptr;
+ }
+ if (r_is_valid)
+ *r_is_valid = false;
+
+ return -1;
+}
+
Variant::Type ClassDB::get_property_type(const StringName &p_class, const StringName &p_property, bool *r_is_valid) {
ClassInfo *type = classes.getptr(p_class);
diff --git a/core/class_db.h b/core/class_db.h
index 4f00a16e91..02eac0dbbc 100644
--- a/core/class_db.h
+++ b/core/class_db.h
@@ -480,6 +480,7 @@ public:
static bool set_property(Object *p_object, const StringName &p_property, const Variant &p_value, bool *r_valid = NULL);
static bool get_property(Object *p_object, const StringName &p_property, Variant &r_value);
static bool has_property(const StringName &p_class, const StringName &p_property, bool p_no_inheritance = false);
+ static int get_property_index(const StringName &p_class, const StringName &p_property, bool *r_is_valid = NULL);
static Variant::Type get_property_type(const StringName &p_class, const StringName &p_property, bool *r_is_valid = NULL);
static StringName get_property_setter(StringName p_class, const StringName p_property);
static StringName get_property_getter(StringName p_class, const StringName p_property);
diff --git a/core/global_constants.cpp b/core/global_constants.cpp
index 18071d7748..9e745ecb98 100644
--- a/core/global_constants.cpp
+++ b/core/global_constants.cpp
@@ -67,8 +67,8 @@ static _GlobalConstant _global_constants[] = {
BIND_GLOBAL_CONSTANT(KEY_TAB),
BIND_GLOBAL_CONSTANT(KEY_BACKTAB),
BIND_GLOBAL_CONSTANT(KEY_BACKSPACE),
- BIND_GLOBAL_CONSTANT(KEY_RETURN),
BIND_GLOBAL_CONSTANT(KEY_ENTER),
+ BIND_GLOBAL_CONSTANT(KEY_KP_ENTER),
BIND_GLOBAL_CONSTANT(KEY_INSERT),
BIND_GLOBAL_CONSTANT(KEY_DELETE),
BIND_GLOBAL_CONSTANT(KEY_PAUSE),
diff --git a/core/input_map.cpp b/core/input_map.cpp
index 24d0624e98..85e627f352 100644
--- a/core/input_map.cpp
+++ b/core/input_map.cpp
@@ -219,11 +219,11 @@ void InputMap::load_default() {
add_action("ui_accept");
key.instance();
- key->set_scancode(KEY_RETURN);
+ key->set_scancode(KEY_ENTER);
action_add_event("ui_accept", key);
key.instance();
- key->set_scancode(KEY_ENTER);
+ key->set_scancode(KEY_KP_ENTER);
action_add_event("ui_accept", key);
key.instance();
diff --git a/core/path_db.cpp b/core/node_path.cpp
index d5c84a2457..11df9670f2 100644
--- a/core/path_db.cpp
+++ b/core/node_path.cpp
@@ -27,7 +27,7 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "path_db.h"
+#include "node_path.h"
#include "print_string.h"
diff --git a/core/path_db.h b/core/node_path.h
index 1aed7535ca..1aed7535ca 100644
--- a/core/path_db.h
+++ b/core/node_path.h
diff --git a/core/object.cpp b/core/object.cpp
index 316c624268..5824084151 100644
--- a/core/object.cpp
+++ b/core/object.cpp
@@ -1182,10 +1182,10 @@ Variant Object::_emit_signal(const Variant **p_args, int p_argcount, Variant::Ca
return Variant();
}
-void Object::emit_signal(const StringName &p_name, const Variant **p_args, int p_argcount) {
+Error Object::emit_signal(const StringName &p_name, const Variant **p_args, int p_argcount) {
if (_block_signals)
- return; //no emit, signals blocked
+ return ERR_CANT_AQUIRE_RESOURCE; //no emit, signals blocked
Signal *s = signal_map.getptr(p_name);
if (!s) {
@@ -1194,11 +1194,11 @@ void Object::emit_signal(const StringName &p_name, const Variant **p_args, int p
//check in script
if (!signal_is_valid && !script.is_null() && !Ref<Script>(script)->has_script_signal(p_name)) {
ERR_EXPLAIN("Can't emit non-existing signal " + String("\"") + p_name + "\".");
- ERR_FAIL();
+ ERR_FAIL_V(ERR_UNAVAILABLE);
}
#endif
//not connected? just return
- return;
+ return ERR_UNAVAILABLE;
}
List<_ObjectSignalDisconnectData> disconnect_data;
@@ -1214,6 +1214,8 @@ void Object::emit_signal(const StringName &p_name, const Variant **p_args, int p
Vector<const Variant *> bind_mem;
+ Error err = OK;
+
for (int i = 0; i < ssize; i++) {
const Connection &c = slot_map.getv(i).conn;
@@ -1249,12 +1251,14 @@ void Object::emit_signal(const StringName &p_name, const Variant **p_args, int p
} else {
Variant::CallError ce;
target->call(c.method, args, argc, ce);
+
if (ce.error != Variant::CallError::CALL_OK) {
if (ce.error == Variant::CallError::CALL_ERROR_INVALID_METHOD && !ClassDB::class_exists(target->get_class_name())) {
//most likely object is not initialized yet, do not throw error.
} else {
ERR_PRINTS("Error calling method from signal '" + String(p_name) + "': " + Variant::get_call_error_text(target, c.method, args, argc, ce));
+ err = ERR_METHOD_NOT_FOUND;
}
}
}
@@ -1274,21 +1278,24 @@ void Object::emit_signal(const StringName &p_name, const Variant **p_args, int p
disconnect(dd.signal, dd.target, dd.method);
disconnect_data.pop_front();
}
+
+ return err;
}
-void Object::emit_signal(const StringName &p_name, VARIANT_ARG_DECLARE) {
+Error Object::emit_signal(const StringName &p_name, VARIANT_ARG_DECLARE) {
VARIANT_ARGPTRS;
int argc = 0;
for (int i = 0; i < VARIANT_ARG_MAX; i++) {
+
if (argptr[i]->get_type() == Variant::NIL)
break;
argc++;
}
- emit_signal(p_name, argptr, argc);
+ return emit_signal(p_name, argptr, argc);
}
void Object::_add_user_signal(const String &p_name, const Array &p_args) {
@@ -2008,7 +2015,7 @@ void ObjectDB::cleanup() {
String node_name;
if (instances[*K]->is_class("Node"))
node_name = " - Node Name: " + String(instances[*K]->call("get_name"));
- if (instances[*K]->is_class("Resoucre"))
+ if (instances[*K]->is_class("Resource"))
node_name = " - Resource Name: " + String(instances[*K]->call("get_name")) + " Path: " + String(instances[*K]->call("get_path"));
print_line("Leaked Instance: " + String(instances[*K]->get_class()) + ":" + itos(*K) + node_name);
}
diff --git a/core/object.h b/core/object.h
index 148a73fbc4..fd3bb624ec 100644
--- a/core/object.h
+++ b/core/object.h
@@ -105,6 +105,7 @@ enum PropertyUsageFlags {
PROPERTY_USAGE_STORE_IF_NULL = 16384,
PROPERTY_USAGE_ANIMATE_AS_TRIGGER = 32768,
PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED = 65536,
+ PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE = 1 << 17,
PROPERTY_USAGE_DEFAULT = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_NETWORK,
PROPERTY_USAGE_DEFAULT_INTL = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_NETWORK | PROPERTY_USAGE_INTERNATIONALIZED,
@@ -654,8 +655,8 @@ public:
void set_script_and_instance(const RefPtr &p_script, ScriptInstance *p_instance); //some script languages can't control instance creation, so this function eases the process
void add_user_signal(const MethodInfo &p_signal);
- void emit_signal(const StringName &p_name, VARIANT_ARG_LIST);
- void emit_signal(const StringName &p_name, const Variant **p_args, int p_argcount);
+ Error emit_signal(const StringName &p_name, VARIANT_ARG_LIST);
+ Error emit_signal(const StringName &p_name, const Variant **p_args, int p_argcount);
void get_signal_list(List<MethodInfo> *p_signals) const;
void get_signal_connection_list(const StringName &p_signal, List<Connection> *p_connections) const;
void get_all_signal_connections(List<Connection> *p_connections) const;
diff --git a/core/os/keyboard.cpp b/core/os/keyboard.cpp
index e154b1934d..9b3e376ea6 100644
--- a/core/os/keyboard.cpp
+++ b/core/os/keyboard.cpp
@@ -42,8 +42,8 @@ static const _KeyCodeText _keycodes[] = {
{KEY_TAB ,"Tab"},
{KEY_BACKTAB ,"BackTab"},
{KEY_BACKSPACE ,"BackSpace"},
- {KEY_RETURN ,"Return"},
{KEY_ENTER ,"Enter"},
+ {KEY_KP_ENTER ,"Kp Enter"},
{KEY_INSERT ,"Insert"},
{KEY_DELETE ,"Delete"},
{KEY_PAUSE ,"Pause"},
@@ -294,8 +294,8 @@ bool keycode_has_unicode(uint32_t p_keycode) {
case KEY_TAB:
case KEY_BACKTAB:
case KEY_BACKSPACE:
- case KEY_RETURN:
case KEY_ENTER:
+ case KEY_KP_ENTER:
case KEY_INSERT:
case KEY_DELETE:
case KEY_PAUSE:
diff --git a/core/os/keyboard.h b/core/os/keyboard.h
index c6985c887d..1ed93e3540 100644
--- a/core/os/keyboard.h
+++ b/core/os/keyboard.h
@@ -57,8 +57,8 @@ enum KeyList {
KEY_TAB = SPKEY | 0x02,
KEY_BACKTAB = SPKEY | 0x03,
KEY_BACKSPACE = SPKEY | 0x04,
- KEY_RETURN = SPKEY | 0x05,
- KEY_ENTER = SPKEY | 0x06,
+ KEY_ENTER = SPKEY | 0x05,
+ KEY_KP_ENTER = SPKEY | 0x06,
KEY_INSERT = SPKEY | 0x07,
KEY_DELETE = SPKEY | 0x08,
KEY_PAUSE = SPKEY | 0x09,
diff --git a/core/project_settings.cpp b/core/project_settings.cpp
index b31f78ec20..f6e0d2e991 100644
--- a/core/project_settings.cpp
+++ b/core/project_settings.cpp
@@ -925,10 +925,10 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF("application/config/use_shared_user_dir", true);
key.instance();
- key->set_scancode(KEY_RETURN);
+ key->set_scancode(KEY_ENTER);
va.push_back(key);
key.instance();
- key->set_scancode(KEY_ENTER);
+ key->set_scancode(KEY_KP_ENTER);
va.push_back(key);
key.instance();
key->set_scancode(KEY_SPACE);
diff --git a/core/resource.cpp b/core/resource.cpp
index 5625784396..86069bf2e9 100644
--- a/core/resource.cpp
+++ b/core/resource.cpp
@@ -32,6 +32,7 @@
#include "core_string_names.h"
#include "io/resource_loader.h"
#include "os/file_access.h"
+#include "scene/main/node.h" //only so casting works
#include "script_language.h"
#include <stdio.h>
diff --git a/core/script_language.cpp b/core/script_language.cpp
index aeb1573840..bb99e0abae 100644
--- a/core/script_language.cpp
+++ b/core/script_language.cpp
@@ -280,8 +280,23 @@ ScriptDebugger::ScriptDebugger() {
bool PlaceHolderScriptInstance::set(const StringName &p_name, const Variant &p_value) {
if (values.has(p_name)) {
+ Variant defval;
+ if (script->get_property_default_value(p_name, defval)) {
+ if (defval == p_value) {
+ values.erase(p_name);
+ return true;
+ }
+ }
values[p_name] = p_value;
return true;
+ } else {
+ Variant defval;
+ if (script->get_property_default_value(p_name, defval)) {
+ if (defval != p_value) {
+ values[p_name] = p_value;
+ }
+ return true;
+ }
}
return false;
}
@@ -291,12 +306,22 @@ bool PlaceHolderScriptInstance::get(const StringName &p_name, Variant &r_ret) co
r_ret = values[p_name];
return true;
}
+
+ Variant defval;
+ if (script->get_property_default_value(p_name, defval)) {
+ r_ret = defval;
+ return true;
+ }
return false;
}
void PlaceHolderScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const {
for (const List<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) {
+ PropertyInfo pinfo = E->get();
+ if (!values.has(pinfo.name)) {
+ pinfo.usage |= PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE;
+ }
p_properties->push_back(E->get());
}
}
@@ -336,6 +361,14 @@ void PlaceHolderScriptInstance::update(const List<PropertyInfo> &p_properties, c
if (!new_values.has(E->key()))
to_remove.push_back(E->key());
+
+ Variant defval;
+ if (script->get_property_default_value(E->key(), defval)) {
+ //remove because it's the same as the default value
+ if (defval == E->get()) {
+ to_remove.push_back(E->key());
+ }
+ }
}
while (to_remove.size()) {
diff --git a/core/variant.h b/core/variant.h
index 661d31cf16..95782d9619 100644
--- a/core/variant.h
+++ b/core/variant.h
@@ -42,8 +42,8 @@
#include "io/ip_address.h"
#include "math_2d.h"
#include "matrix3.h"
+#include "node_path.h"
#include "os/power.h"
-#include "path_db.h"
#include "plane.h"
#include "quat.h"
#include "rect3.h"
diff --git a/doc/base/classes.xml b/doc/base/classes.xml
index 268bfeca1a..cd5b950f57 100644
--- a/doc/base/classes.xml
+++ b/doc/base/classes.xml
@@ -846,10 +846,10 @@
<constant name="KEY_BACKSPACE" value="16777220">
Backspace Key
</constant>
- <constant name="KEY_RETURN" value="16777221">
+ <constant name="KEY_ENTER" value="16777221">
Return Key (On Main Keyboard)
</constant>
- <constant name="KEY_ENTER" value="16777222">
+ <constant name="KEY_KP_ENTER" value="16777222">
Enter Key (On Numpad)
</constant>
<constant name="KEY_INSERT" value="16777223">
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index 89bea1e8cc..f7ecc3b158 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -6902,17 +6902,19 @@ void RasterizerStorageGLES3::initialize() {
config.use_fast_texture_filter = int(ProjectSettings::get_singleton()->get("rendering/quality/filters/use_nearest_mipmap_filter"));
config.use_anisotropic_filter = config.extensions.has("rendering/quality/filters/anisotropic_filter_level");
- config.s3tc_supported = config.extensions.has("GL_EXT_texture_compression_dxt1") || config.extensions.has("GL_EXT_texture_compression_s3tc") || config.extensions.has("WEBGL_compressed_texture_s3tc");
config.etc_supported = config.extensions.has("GL_OES_compressed_ETC1_RGB8_texture");
config.latc_supported = config.extensions.has("GL_EXT_texture_compression_latc");
- config.rgtc_supported = config.extensions.has("GL_EXT_texture_compression_rgtc");
config.bptc_supported = config.extensions.has("GL_ARB_texture_compression_bptc");
#ifdef GLES_OVER_GL
config.hdr_supported = true;
config.etc2_supported = false;
+ config.s3tc_supported = true;
+ config.rgtc_supported = true; //RGTC - core since OpenGL version 3.0
#else
config.etc2_supported = true;
config.hdr_supported = false;
+ config.s3tc_supported = config.extensions.has("GL_EXT_texture_compression_dxt1") || config.extensions.has("GL_EXT_texture_compression_s3tc") || config.extensions.has("WEBGL_compressed_texture_s3tc");
+ config.rgtc_supported = config.extensions.has("GL_EXT_texture_compression_rgtc") || config.extensions.has("GL_ARB_texture_compression_rgtc");
#endif
config.pvrtc_supported = config.extensions.has("GL_IMG_texture_compression_pvrtc");
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index 340a1f24d2..efb82441f4 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -1929,7 +1929,7 @@ FRAGMENT_SHADER_CODE
if (fog_depth_enabled) {
- float fog_z = smoothstep(fog_depth_begin,z_far,-vertex.z);
+ float fog_z = smoothstep(fog_depth_begin,z_far,length(vertex));
fog_amount = pow(fog_z,fog_depth_curve);
if (fog_transmit_enabled) {
diff --git a/drivers/rtaudio/audio_driver_rtaudio.cpp b/drivers/rtaudio/audio_driver_rtaudio.cpp
index da998db66f..3de25c32ad 100644
--- a/drivers/rtaudio/audio_driver_rtaudio.cpp
+++ b/drivers/rtaudio/audio_driver_rtaudio.cpp
@@ -79,7 +79,7 @@ int AudioDriverRtAudio::callback(void *outputBuffer, void *inputBuffer, unsigned
Error AudioDriverRtAudio::init() {
active = false;
- mutex = NULL;
+ mutex = Mutex::create(true);
dac = memnew(RtAudio);
ERR_EXPLAIN("Cannot initialize RtAudio audio driver: No devices present.")
@@ -136,7 +136,6 @@ Error AudioDriverRtAudio::init() {
try {
dac->openStream(&parameters, NULL, RTAUDIO_SINT32, mix_rate, &buffer_size, &callback, this, &options);
- mutex = Mutex::create(true);
active = true;
break;
@@ -162,6 +161,7 @@ Error AudioDriverRtAudio::init() {
try {
dac->closeStream();
+ active = false;
} catch (RtAudioError &e) {
ERR_PRINT(e.what());
ERR_FAIL_V(ERR_UNAVAILABLE);
@@ -212,17 +212,27 @@ void AudioDriverRtAudio::unlock() {
void AudioDriverRtAudio::finish() {
- if (active && dac->isStreamOpen())
+ lock();
+ if (active && dac->isStreamOpen()) {
dac->closeStream();
- if (mutex)
+ active = false;
+ }
+ unlock();
+
+ if (mutex) {
memdelete(mutex);
- if (dac)
+ mutex = NULL;
+ }
+ if (dac) {
memdelete(dac);
+ dac = NULL;
+ }
}
AudioDriverRtAudio::AudioDriverRtAudio() {
mutex = NULL;
+ dac = NULL;
mix_rate = 44100;
speaker_mode = SPEAKER_MODE_STEREO;
}
diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp
index ed58116304..0fd643d031 100644
--- a/editor/editor_file_system.cpp
+++ b/editor/editor_file_system.cpp
@@ -512,6 +512,8 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, DirAccess
if (FileAccess::exists(cd.plus_file(f).plus_file("project.godot"))) // skip if another project inside this
continue;
+ if (FileAccess::exists(cd.plus_file(f).plus_file(".gdignore"))) // skip if another project inside this
+ continue;
dirs.push_back(f);
@@ -691,6 +693,8 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir, const
if (FileAccess::exists(cd.plus_file(f).plus_file("project.godot"))) // skip if another project inside this
continue;
+ if (FileAccess::exists(cd.plus_file(f).plus_file(".gdignore"))) // skip if another project inside this
+ continue;
EditorFileSystemDirectory *efd = memnew(EditorFileSystemDirectory);
diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp
index e890082ee1..f80c4ee0e2 100644
--- a/editor/editor_help.cpp
+++ b/editor/editor_help.cpp
@@ -1621,12 +1621,18 @@ void EditorHelp::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_READY: {
-
//forward->set_icon(get_icon("Forward","EditorIcons"));
//back->set_icon(get_icon("Back","EditorIcons"));
_update_doc();
+ } break;
+ case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
+ Ref<StyleBoxFlat> style(memnew(StyleBoxFlat));
+ style->set_bg_color(EditorSettings::get_singleton()->get("text_editor/highlighting/background_color"));
+ background_panel->add_style_override("panel", style);
} break;
+
+ default: break;
}
}
@@ -1695,14 +1701,14 @@ EditorHelp::EditorHelp() {
//class_list->set_selection_enabled(true);
{
- Panel *pc = memnew(Panel);
+ background_panel = memnew(Panel);
Ref<StyleBoxFlat> style(memnew(StyleBoxFlat));
style->set_bg_color(EditorSettings::get_singleton()->get("text_editor/highlighting/background_color"));
- pc->set_v_size_flags(SIZE_EXPAND_FILL);
- pc->add_style_override("panel", style); //get_stylebox("normal","TextEdit"));
- vbc->add_child(pc);
+ background_panel->set_v_size_flags(SIZE_EXPAND_FILL);
+ background_panel->add_style_override("panel", style); //get_stylebox("normal","TextEdit"));
+ vbc->add_child(background_panel);
class_desc = memnew(RichTextLabel);
- pc->add_child(class_desc);
+ background_panel->add_child(class_desc);
class_desc->set_area_as_parent_rect(8);
class_desc->connect("meta_clicked", this, "_class_desc_select");
class_desc->connect("gui_input", this, "_class_desc_input");
diff --git a/editor/editor_help.h b/editor/editor_help.h
index 46d83490f4..de30b543fc 100644
--- a/editor/editor_help.h
+++ b/editor/editor_help.h
@@ -129,6 +129,7 @@ class EditorHelp : public VBoxContainer {
HSplitContainer *h_split;
static DocData *doc;
+ Panel *background_panel;
ConfirmationDialog *search_dialog;
LineEdit *search;
diff --git a/editor/editor_name_dialog.cpp b/editor/editor_name_dialog.cpp
index 7435e9a9f7..6ebfcbf313 100644
--- a/editor/editor_name_dialog.cpp
+++ b/editor/editor_name_dialog.cpp
@@ -42,8 +42,8 @@ void EditorNameDialog::_line_gui_input(const Ref<InputEvent> &p_event) {
return;
switch (k->get_scancode()) {
- case KEY_ENTER:
- case KEY_RETURN: {
+ case KEY_KP_ENTER:
+ case KEY_ENTER: {
if (get_hide_on_ok())
hide();
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index df16de947e..59c438c94d 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -143,7 +143,7 @@ Ref<Theme> create_editor_theme() {
Color light_color_1 = base_color.linear_interpolate(Color(1, 1, 1, 1), contrast);
Color light_color_2 = base_color.linear_interpolate(Color(1, 1, 1, 1), contrast * 1.5);
- const int border_width = (border_size % 3) * EDSCALE;
+ const int border_width = CLAMP(border_size, 0, 3) * EDSCALE;
Color title_color_hl = base_color;
if (highlight_tabs)
@@ -287,12 +287,12 @@ Ref<Theme> create_editor_theme() {
// PopupMenu
Ref<StyleBoxFlat> style_popup_menu = make_flat_stylebox(dark_color_1, 8, 8, 8, 8);
- style_popup_menu->set_border_size(border_width);
+ style_popup_menu->set_border_size(MAX(EDSCALE, border_width));
style_popup_menu->set_light_color(light_color_1);
style_popup_menu->set_dark_color(light_color_1);
style_popup_menu->set_border_blend(false);
theme->set_stylebox("panel", "PopupMenu", style_popup_menu);
- theme->set_stylebox("separator", "PopupMenu", make_line_stylebox(separator_color, border_width, 8 - border_width));
+ theme->set_stylebox("separator", "PopupMenu", make_line_stylebox(separator_color, MAX(EDSCALE, border_width), 8 - MAX(EDSCALE, border_width)));
// Tree & ItemList background
Ref<StyleBoxFlat> style_tree_bg = make_flat_stylebox(dark_color_1, 2, 4, 2, 4);
@@ -431,7 +431,7 @@ Ref<Theme> create_editor_theme() {
// WindowDialog
Ref<StyleBoxFlat> style_window = make_flat_stylebox(dark_color_2, 4, 4, 4, 4);
- style_window->set_border_size(border_width);
+ style_window->set_border_size(MAX(EDSCALE, border_width));
style_window->set_border_blend(false);
style_window->set_light_color(title_color_hl);
style_window->set_dark_color(title_color_hl);
@@ -478,6 +478,9 @@ Ref<Theme> create_editor_theme() {
theme->set_icon("grabber", "VSlider", theme->get_icon("GuiSliderGrabber", "EditorIcons"));
theme->set_icon("grabber_highlight", "VSlider", theme->get_icon("GuiSliderGrabberHl", "EditorIcons"));
+ //RichTextLabel
+ theme->set_stylebox("focus", "RichTextLabel", make_empty_stylebox());
+
// Panel
theme->set_stylebox("panel", "Panel", style_panel);
diff --git a/editor/import/editor_scene_importer_gltf.cpp b/editor/import/editor_scene_importer_gltf.cpp
index 35b31b56b4..1c42bcef8a 100644
--- a/editor/import/editor_scene_importer_gltf.cpp
+++ b/editor/import/editor_scene_importer_gltf.cpp
@@ -4,6 +4,7 @@
#include "os/os.h"
#include "scene/3d/camera.h"
#include "scene/3d/mesh_instance.h"
+#include "scene/animation/animation_player.h"
#include "scene/resources/surface_tool.h"
#include "thirdparty/misc/base64.h"
@@ -14,7 +15,7 @@ uint32_t EditorSceneImporterGLTF::get_import_flags() const {
void EditorSceneImporterGLTF::get_extensions(List<String> *r_extensions) const {
r_extensions->push_back("gltf");
- r_extensions->push_back("gfb");
+ r_extensions->push_back("glb");
}
Error EditorSceneImporterGLTF::_parse_json(const String &p_path, GLTFState &state) {
@@ -44,6 +45,60 @@ Error EditorSceneImporterGLTF::_parse_json(const String &p_path, GLTFState &stat
return OK;
}
+Error EditorSceneImporterGLTF::_parse_glb(const String &p_path, GLTFState &state) {
+
+ Error err;
+ FileAccessRef f = FileAccess::open(p_path, FileAccess::READ, &err);
+ if (!f) {
+ return err;
+ }
+
+ uint32_t magic = f->get_32();
+ ERR_FAIL_COND_V(magic != 0x46546C67, ERR_FILE_UNRECOGNIZED); //glTF
+ uint32_t version = f->get_32();
+ uint32_t length = f->get_32();
+
+ uint32_t chunk_length = f->get_32();
+ uint32_t chunk_type = f->get_32();
+
+ ERR_FAIL_COND_V(chunk_type != 0x4E4F534A, ERR_PARSE_ERROR); //JSON
+ Vector<uint8_t> json_data;
+ json_data.resize(chunk_length);
+ uint32_t len = f->get_buffer(json_data.ptr(), chunk_length);
+ ERR_FAIL_COND_V(len != chunk_length, ERR_FILE_CORRUPT);
+
+ String text;
+ text.parse_utf8((const char *)json_data.ptr(), json_data.size());
+
+ String err_txt;
+ int err_line;
+ Variant v;
+ err = JSON::parse(text, v, err_txt, err_line);
+ if (err != OK) {
+ _err_print_error("", p_path.utf8().get_data(), err_line, err_txt.utf8().get_data(), ERR_HANDLER_SCRIPT);
+ return err;
+ }
+
+ state.json = v;
+
+ //data?
+
+ chunk_length = f->get_32();
+ chunk_type = f->get_32();
+
+ if (f->eof_reached()) {
+ return OK; //all good
+ }
+
+ ERR_FAIL_COND_V(chunk_type != 0x004E4942, ERR_PARSE_ERROR); //BIN
+
+ state.glb_data.resize(chunk_length);
+ len = f->get_buffer(state.glb_data.ptr(), chunk_length);
+ ERR_FAIL_COND_V(len != chunk_length, ERR_FILE_CORRUPT);
+
+ return OK;
+}
+
static Vector3 _arr_to_vec3(const Array &p_array) {
ERR_FAIL_COND_V(p_array.size() != 3, Vector3());
return Vector3(p_array[0], p_array[1], p_array[2]);
@@ -208,8 +263,8 @@ Error EditorSceneImporterGLTF::_parse_buffers(GLTFState &state, const String &p_
Array buffers = state.json["buffers"];
for (int i = 0; i < buffers.size(); i++) {
- if (i == 0 && state.gfb_data.size()) {
- state.buffers.push_back(state.gfb_data);
+ if (i == 0 && state.glb_data.size()) {
+ state.buffers.push_back(state.glb_data);
} else {
Dictionary buffer = buffers[i];
@@ -685,6 +740,23 @@ PoolVector<Color> EditorSceneImporterGLTF::_decode_accessor_as_color(GLTFState &
}
return ret;
}
+Vector<Quat> EditorSceneImporterGLTF::_decode_accessor_as_quat(GLTFState &state, int p_accessor, bool p_for_vertex) {
+
+ Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex);
+ Vector<Quat> ret;
+ if (attribs.size() == 0)
+ return ret;
+ ERR_FAIL_COND_V(attribs.size() % 4 != 0, ret);
+ const double *attribs_ptr = attribs.ptr();
+ int ret_size = attribs.size() / 4;
+ ret.resize(ret_size);
+ {
+ for (int i = 0; i < ret_size; i++) {
+ ret[i] = Quat(attribs_ptr[i * 4 + 0], attribs_ptr[i * 4 + 1], attribs_ptr[i * 4 + 2], attribs_ptr[i * 4 + 3]);
+ }
+ }
+ return ret;
+}
Vector<Transform2D> EditorSceneImporterGLTF::_decode_accessor_as_xform2d(GLTFState &state, int p_accessor, bool p_for_vertex) {
Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex);
@@ -1359,6 +1431,136 @@ Error EditorSceneImporterGLTF::_parse_cameras(GLTFState &state) {
state.cameras.push_back(camera);
}
+
+ print_line("total cameras: " + itos(state.cameras.size()));
+}
+
+Error EditorSceneImporterGLTF::_parse_animations(GLTFState &state) {
+
+ if (!state.json.has("animations"))
+ return OK;
+
+ Array animations = state.json["animations"];
+
+ for (int i = 0; i < animations.size(); i++) {
+
+ Dictionary d = animations[i];
+
+ GLTFAnimation animation;
+
+ if (!d.has("channels") || !d.has("samplers"))
+ continue;
+
+ Array channels = d["channels"];
+ Array samplers = d["samplers"];
+
+ if (d.has("name")) {
+ animation.name = d["name"];
+ }
+
+ for (int j = 0; j < channels.size(); j++) {
+
+ Dictionary c = channels[j];
+ if (!c.has("target"))
+ continue;
+
+ Dictionary t = c["target"];
+ if (!t.has("node") || !t.has("path")) {
+ continue;
+ }
+
+ ERR_FAIL_COND_V(!c.has("sampler"), ERR_PARSE_ERROR);
+ int sampler = c["sampler"];
+ ERR_FAIL_INDEX_V(sampler, samplers.size(), ERR_PARSE_ERROR);
+
+ int node = t["node"];
+ String path = t["path"];
+
+ ERR_FAIL_INDEX_V(node, state.nodes.size(), ERR_PARSE_ERROR);
+
+ GLTFAnimation::Track *track = NULL;
+
+ if (!animation.tracks.has(node)) {
+ animation.tracks[node] = GLTFAnimation::Track();
+ }
+
+ track = &animation.tracks[node];
+
+ Dictionary s = samplers[sampler];
+
+ ERR_FAIL_COND_V(!s.has("input"), ERR_PARSE_ERROR);
+ ERR_FAIL_COND_V(!s.has("output"), ERR_PARSE_ERROR);
+
+ int input = s["input"];
+ int output = s["output"];
+
+ GLTFAnimation::Interpolation interp = GLTFAnimation::INTERP_LINEAR;
+ if (s.has("interpolation")) {
+ String in = s["interpolation"];
+ if (in == "STEP") {
+ interp = GLTFAnimation::INTERP_STEP;
+ } else if (in == "LINEAR") {
+ interp = GLTFAnimation::INTERP_LINEAR;
+ } else if (in == "CATMULLROMSPLINE") {
+ interp = GLTFAnimation::INTERP_CATMULLROMSPLINE;
+ } else if (in == "CUBICSPLINE") {
+ interp = GLTFAnimation::INTERP_CUBIC_SPLINE;
+ }
+ }
+
+ print_line("path: " + path);
+ PoolVector<float> times = _decode_accessor_as_floats(state, input, false);
+ if (path == "translation") {
+ PoolVector<Vector3> translations = _decode_accessor_as_vec3(state, output, false);
+ track->translation_track.interpolation = interp;
+ track->translation_track.times = Variant(times); //convert via variant
+ track->translation_track.values = Variant(translations); //convert via variant
+ } else if (path == "rotation") {
+ Vector<Quat> rotations = _decode_accessor_as_quat(state, output, false);
+ track->rotation_track.interpolation = interp;
+ track->rotation_track.times = Variant(times); //convert via variant
+ track->rotation_track.values = rotations; //convert via variant
+ } else if (path == "scale") {
+ PoolVector<Vector3> scales = _decode_accessor_as_vec3(state, output, false);
+ track->scale_track.interpolation = interp;
+ track->scale_track.times = Variant(times); //convert via variant
+ track->scale_track.values = Variant(scales); //convert via variant
+ } else if (path == "weights") {
+ PoolVector<float> weights = _decode_accessor_as_floats(state, output, false);
+
+ ERR_FAIL_INDEX_V(state.nodes[node]->mesh, state.meshes.size(), ERR_PARSE_ERROR);
+ GLTFMesh *mesh = &state.meshes[state.nodes[node]->mesh];
+ ERR_FAIL_COND_V(mesh->blend_weights.size() == 0, ERR_PARSE_ERROR);
+ int wc = mesh->blend_weights.size();
+
+ track->weight_tracks.resize(wc);
+
+ int wlen = weights.size() / wc;
+ PoolVector<float>::Read r = weights.read();
+ for (int k = 0; k < wc; k++) { //separate tracks, having them together is not such a good idea
+ GLTFAnimation::Channel<float> cf;
+ cf.interpolation = interp;
+ cf.times = Variant(times);
+ Vector<float> wdata;
+ wdata.resize(wlen);
+ for (int l = 0; l < wlen; l++) {
+ wdata[l] = r[l * wc + k];
+ }
+
+ cf.values = wdata;
+ track->weight_tracks[k] = cf;
+ }
+ } else {
+ WARN_PRINTS("Invalid path: " + path);
+ }
+ }
+
+ state.animations.push_back(animation);
+ }
+
+ print_line("total animations: " + itos(state.animations.size()));
+
+ return OK;
}
void EditorSceneImporterGLTF::_assign_scene_names(GLTFState &state) {
@@ -1423,6 +1625,8 @@ void EditorSceneImporterGLTF::_generate_node(GLTFState &state, int p_node, Node
node->set_owner(p_owner);
node->set_transform(n->xform);
+ n->godot_node = node;
+
for (int i = 0; i < n->skeleton_children.size(); i++) {
Skeleton *s = skeletons[n->skeleton_children[i]];
@@ -1454,13 +1658,308 @@ void EditorSceneImporterGLTF::_generate_bone(GLTFState &state, int p_node, Vecto
}
skeletons[n->joint_skin]->set_bone_rest(bone_index, state.skins[n->joint_skin].bones[n->joint_bone].inverse_bind.affine_inverse());
+ n->godot_node = skeletons[n->joint_skin];
+ n->godot_bone_index = bone_index;
+
for (int i = 0; i < n->children.size(); i++) {
ERR_CONTINUE(state.nodes[n->children[i]]->joint_skin < 0);
_generate_bone(state, n->children[i], skeletons, bone_index);
}
}
-Spatial *EditorSceneImporterGLTF::_generate_scene(GLTFState &state) {
+template <class T>
+struct EditorSceneImporterGLTFInterpolate {
+
+ T lerp(const T &a, const T &b, float c) const {
+
+ return a + (b - a) * c;
+ }
+
+ T catmull_rom(const T &p0, const T &p1, const T &p2, const T &p3, float t) {
+
+ float t2 = t * t;
+ float t3 = t2 * t;
+
+ return 0.5f * ((2.0f * p1) + (-p0 + p2) * t + (2.0f * p0 - 5.0f * p1 + 4 * p2 - p3) * t2 + (-p0 + 3.0f * p1 - 3.0f * p2 + p3) * t3);
+ }
+
+ T bezier(T start, T control_1, T control_2, T end, float t) {
+ /* Formula from Wikipedia article on Bezier curves. */
+ real_t omt = (1.0 - t);
+ real_t omt2 = omt * omt;
+ real_t omt3 = omt2 * omt;
+ real_t t2 = t * t;
+ real_t t3 = t2 * t;
+
+ return start * omt3 + control_1 * omt2 * t * 3.0 + control_2 * omt * t2 * 3.0 + end * t3;
+ }
+};
+
+//thank you for existing, partial specialization
+template <>
+struct EditorSceneImporterGLTFInterpolate<Quat> {
+
+ Quat lerp(const Quat &a, const Quat &b, float c) const {
+
+ return a.slerp(b, c);
+ }
+
+ Quat catmull_rom(const Quat &p0, const Quat &p1, const Quat &p2, const Quat &p3, float c) {
+
+ return p1.slerp(p2, c);
+ }
+
+ Quat bezier(Quat start, Quat control_1, Quat control_2, Quat end, float t) {
+ return start.slerp(end, t);
+ }
+};
+
+template <class T>
+T EditorSceneImporterGLTF::_interpolate_track(const Vector<float> &p_times, const Vector<T> &p_values, float p_time, GLTFAnimation::Interpolation p_interp) {
+
+ //could use binary search, worth it?
+ int idx = -1;
+ for (int i = 0; i < p_times.size(); i++) {
+ if (p_times[i] > p_time)
+ break;
+ idx++;
+ }
+
+ EditorSceneImporterGLTFInterpolate<T> interp;
+
+ switch (p_interp) {
+ case GLTFAnimation::INTERP_LINEAR: {
+
+ if (idx == -1) {
+ return p_values[0];
+ } else if (idx >= p_times.size() - 1) {
+ return p_values[p_times.size() - 1];
+ }
+
+ float c = (p_time - p_times[idx]) / (p_times[idx + 1] - p_times[idx]);
+
+ return interp.lerp(p_values[idx], p_values[idx + 1], c);
+
+ } break;
+ case GLTFAnimation::INTERP_STEP: {
+
+ if (idx == -1) {
+ return p_values[0];
+ } else if (idx >= p_times.size() - 1) {
+ return p_values[p_times.size() - 1];
+ }
+
+ return p_values[idx];
+
+ } break;
+ case GLTFAnimation::INTERP_CATMULLROMSPLINE: {
+
+ if (idx == -1) {
+ return p_values[1];
+ } else if (idx >= p_times.size() - 1) {
+ return p_values[1 + p_times.size() - 1];
+ }
+
+ float c = (p_time - p_times[idx]) / (p_times[idx + 1] - p_times[idx]);
+
+ return interp.catmull_rom(p_values[idx - 1], p_values[idx], p_values[idx + 1], p_values[idx + 3], c);
+
+ } break;
+ case GLTFAnimation::INTERP_CUBIC_SPLINE: {
+
+ if (idx == -1) {
+ return p_values[1];
+ } else if (idx >= p_times.size() - 1) {
+ return p_values[(p_times.size() - 1) * 3 + 1];
+ }
+
+ float c = (p_time - p_times[idx]) / (p_times[idx + 1] - p_times[idx]);
+
+ T from = p_values[idx * 3 + 1];
+ T c1 = from + p_values[idx * 3 + 0];
+ T to = p_values[idx * 3 + 3];
+ T c2 = to + p_values[idx * 3 + 2];
+
+ return interp.bezier(from, c1, c2, to, c);
+
+ } break;
+ }
+
+ ERR_FAIL_V(p_values[0]);
+}
+
+void EditorSceneImporterGLTF::_import_animation(GLTFState &state, AnimationPlayer *ap, int index, int bake_fps, Vector<Skeleton *> skeletons) {
+
+ const GLTFAnimation &anim = state.animations[index];
+
+ String name = anim.name;
+ if (name == "") {
+ name = _gen_unique_name(state, "Animation");
+ }
+
+ Ref<Animation> animation;
+ animation.instance();
+ animation->set_name(name);
+
+ for (Map<int, GLTFAnimation::Track>::Element *E = anim.tracks.front(); E; E = E->next()) {
+
+ const GLTFAnimation::Track &track = E->get();
+ //need to find the path
+ NodePath node_path;
+
+ GLTFNode *node = state.nodes[E->key()];
+ ERR_CONTINUE(!node->godot_node);
+
+ if (node->godot_bone_index >= 0) {
+ Skeleton *sk = (Skeleton *)node->godot_node;
+ String path = ap->get_parent()->get_path_to(sk);
+ String bone = sk->get_bone_name(node->godot_bone_index);
+ node_path = path + ":" + bone;
+ } else {
+ node_path = ap->get_parent()->get_path_to(node->godot_node);
+ }
+
+ float length = 0;
+
+ for (int i = 0; i < track.rotation_track.times.size(); i++) {
+ length = MAX(length, track.rotation_track.times[i]);
+ }
+ for (int i = 0; i < track.translation_track.times.size(); i++) {
+ length = MAX(length, track.translation_track.times[i]);
+ }
+ for (int i = 0; i < track.scale_track.times.size(); i++) {
+ length = MAX(length, track.scale_track.times[i]);
+ }
+
+ for (int i = 0; i < track.weight_tracks.size(); i++) {
+ for (int j = 0; j < track.weight_tracks[i].times.size(); j++) {
+ length = MAX(length, track.weight_tracks[i].times[j]);
+ }
+ }
+
+ animation->set_length(length);
+
+ if (track.rotation_track.values.size() || track.translation_track.values.size() || track.scale_track.values.size()) {
+ //make transform track
+ int track_idx = animation->get_track_count();
+ animation->add_track(Animation::TYPE_TRANSFORM);
+ animation->track_set_path(track_idx, node_path);
+ //first determine animation length
+
+ float increment = 1.0 / float(bake_fps);
+ float time = 0.0;
+
+ Vector3 base_pos;
+ Quat base_rot;
+ Vector3 base_scale = Vector3(1, 1, 1);
+
+ if (!track.rotation_track.values.size()) {
+ base_rot = state.nodes[E->key()]->rotation;
+ }
+
+ if (!track.translation_track.values.size()) {
+ base_pos = state.nodes[E->key()]->translation;
+ }
+
+ if (!track.scale_track.values.size()) {
+ base_scale = state.nodes[E->key()]->scale;
+ }
+
+ bool last = false;
+ while (true) {
+
+ Vector3 pos = base_pos;
+ Quat rot = base_rot;
+ Vector3 scale = base_scale;
+
+ if (track.translation_track.times.size()) {
+
+ pos = _interpolate_track<Vector3>(track.translation_track.times, track.translation_track.values, time, track.translation_track.interpolation);
+ }
+
+ if (track.rotation_track.times.size()) {
+
+ rot = _interpolate_track<Quat>(track.rotation_track.times, track.rotation_track.values, time, track.rotation_track.interpolation);
+ }
+
+ if (track.scale_track.times.size()) {
+
+ scale = _interpolate_track<Vector3>(track.scale_track.times, track.scale_track.values, time, track.scale_track.interpolation);
+ }
+
+ if (node->godot_bone_index >= 0) {
+
+ Transform xform;
+ xform.basis = Basis(rot);
+ xform.basis.scale(scale);
+ xform.origin = pos;
+
+ Skeleton *skeleton = skeletons[node->joint_skin];
+ int bone = node->godot_bone_index;
+ xform = skeleton->get_bone_rest(bone).affine_inverse() * xform;
+
+ rot = xform.basis;
+ rot.normalize();
+ scale = xform.basis.get_scale();
+ pos = xform.origin;
+ }
+
+ animation->transform_track_insert_key(track_idx, time, pos, rot, scale);
+
+ if (last) {
+ break;
+ }
+ time += increment;
+ if (time >= length) {
+ last = true;
+ time = length;
+ }
+ }
+ }
+
+ for (int i = 0; i < track.weight_tracks.size(); i++) {
+ ERR_CONTINUE(node->mesh < 0 || node->mesh >= state.meshes.size());
+ const GLTFMesh &mesh = state.meshes[node->mesh];
+ String prop = "blend_shapes/" + mesh.mesh->get_blend_shape_name(i);
+ node_path = String(node_path) + ":" + prop;
+
+ int track_idx = animation->get_track_count();
+ animation->add_track(Animation::TYPE_VALUE);
+ animation->track_set_path(track_idx, node_path);
+
+ if (track.weight_tracks[i].interpolation <= GLTFAnimation::INTERP_STEP) {
+ animation->track_set_interpolation_type(track_idx, track.weight_tracks[i].interpolation == GLTFAnimation::INTERP_STEP ? Animation::INTERPOLATION_NEAREST : Animation::INTERPOLATION_NEAREST);
+ for (int j = 0; j < track.weight_tracks[i].times.size(); j++) {
+ float t = track.weight_tracks[i].times[j];
+ float w = track.weight_tracks[i].values[j];
+ animation->track_insert_key(track_idx, t, w);
+ }
+ } else {
+ //must bake, apologies.
+ float increment = 1.0 / float(bake_fps);
+ float time = 0.0;
+
+ bool last = false;
+ while (true) {
+
+ float value = _interpolate_track<float>(track.weight_tracks[i].times, track.weight_tracks[i].values, time, track.weight_tracks[i].interpolation);
+ if (last) {
+ break;
+ }
+ time += increment;
+ if (time >= length) {
+ last = true;
+ time = length;
+ }
+ }
+ }
+ }
+ }
+
+ ap->add_animation(name, animation);
+}
+
+Spatial *EditorSceneImporterGLTF::_generate_scene(GLTFState &state, int p_bake_fps) {
Spatial *root = memnew(Spatial);
root->set_name(state.scene_name);
@@ -1489,15 +1988,36 @@ Spatial *EditorSceneImporterGLTF::_generate_scene(GLTFState &state) {
skeletons[i]->localize_rests();
}
+ if (state.animations.size()) {
+ AnimationPlayer *ap = memnew(AnimationPlayer);
+ ap->set_name("AnimationPlayer");
+ root->add_child(ap);
+ ap->set_owner(root);
+
+ for (int i = 0; i < state.animations.size(); i++) {
+ _import_animation(state, ap, i, p_bake_fps, skeletons);
+ }
+ }
+
return root;
}
Node *EditorSceneImporterGLTF::import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) {
GLTFState state;
- Error err = _parse_json(p_path, state);
- if (err)
- return NULL;
+
+ if (p_path.to_lower().ends_with("glb")) {
+ //binary file
+ //text file
+ Error err = _parse_glb(p_path, state);
+ if (err)
+ return NULL;
+ } else {
+ //text file
+ Error err = _parse_json(p_path, state);
+ if (err)
+ return NULL;
+ }
ERR_FAIL_COND_V(!state.json.has("asset"), NULL);
@@ -1511,7 +2031,7 @@ Node *EditorSceneImporterGLTF::import_scene(const String &p_path, uint32_t p_fla
state.minor_version = version.get_slice(".", 1).to_int();
/* STEP 0 PARSE SCENE */
- err = _parse_scenes(state);
+ Error err = _parse_scenes(state);
if (err != OK)
return NULL;
@@ -1565,9 +2085,16 @@ Node *EditorSceneImporterGLTF::import_scene(const String &p_path, uint32_t p_fla
if (err != OK)
return NULL;
+ /* STEP 11 PARSE ANIMATIONS */
+ err = _parse_animations(state);
+ if (err != OK)
+ return NULL;
+
+ /* STEP 12 ASSIGN SCENE NAMES */
_assign_scene_names(state);
- Spatial *scene = _generate_scene(state);
+ /* STEP 13 MAKE SCENE! */
+ Spatial *scene = _generate_scene(state, p_bake_fps);
return scene;
}
diff --git a/editor/import/editor_scene_importer_gltf.h b/editor/import/editor_scene_importer_gltf.h
index ab6dc6939a..d9479fae6f 100644
--- a/editor/import/editor_scene_importer_gltf.h
+++ b/editor/import/editor_scene_importer_gltf.h
@@ -5,6 +5,8 @@
#include "scene/3d/skeleton.h"
#include "scene/3d/spatial.h"
+class AnimationPlayer;
+
class EditorSceneImporterGLTF : public EditorSceneImporter {
GDCLASS(EditorSceneImporterGLTF, EditorSceneImporter);
@@ -50,6 +52,8 @@ class EditorSceneImporterGLTF : public EditorSceneImporter {
Transform xform;
String name;
+ Node *godot_node;
+ int godot_bone_index;
int mesh;
int camera;
@@ -69,6 +73,8 @@ class EditorSceneImporterGLTF : public EditorSceneImporter {
Vector<int> children;
GLTFNode() {
+ godot_node = NULL;
+ godot_bone_index = -1;
joint_skin = -1;
joint_bone = -1;
child_of_skeleton = -1;
@@ -172,12 +178,41 @@ class EditorSceneImporterGLTF : public EditorSceneImporter {
}
};
+ struct GLTFAnimation {
+
+ enum Interpolation {
+ INTERP_LINEAR,
+ INTERP_STEP,
+ INTERP_CATMULLROMSPLINE,
+ INTERP_CUBIC_SPLINE
+ };
+
+ template <class T>
+ struct Channel {
+ Interpolation interpolation;
+ Vector<float> times;
+ Vector<T> values;
+ };
+
+ struct Track {
+
+ Channel<Vector3> translation_track;
+ Channel<Quat> rotation_track;
+ Channel<Vector3> scale_track;
+ Vector<Channel<float> > weight_tracks;
+ };
+
+ String name;
+
+ Map<int, Track> tracks;
+ };
+
struct GLTFState {
Dictionary json;
int major_version;
int minor_version;
- Vector<uint8_t> gfb_data;
+ Vector<uint8_t> glb_data;
Vector<GLTFNode *> nodes;
Vector<Vector<uint8_t> > buffers;
@@ -198,6 +233,8 @@ class EditorSceneImporterGLTF : public EditorSceneImporter {
Set<String> unique_names;
+ Vector<GLTFAnimation> animations;
+
Map<int, Vector<int> > skin_users; //cache skin users
~GLTFState() {
@@ -212,6 +249,7 @@ class EditorSceneImporterGLTF : public EditorSceneImporter {
Ref<Texture> _get_texture(GLTFState &state, int p_texture);
Error _parse_json(const String &p_path, GLTFState &state);
+ Error _parse_glb(const String &p_path, GLTFState &state);
Error _parse_scenes(GLTFState &state);
Error _parse_nodes(GLTFState &state);
@@ -226,13 +264,16 @@ class EditorSceneImporterGLTF : public EditorSceneImporter {
PoolVector<Vector2> _decode_accessor_as_vec2(GLTFState &state, int p_accessor, bool p_for_vertex);
PoolVector<Vector3> _decode_accessor_as_vec3(GLTFState &state, int p_accessor, bool p_for_vertex);
PoolVector<Color> _decode_accessor_as_color(GLTFState &state, int p_accessor, bool p_for_vertex);
+ Vector<Quat> _decode_accessor_as_quat(GLTFState &state, int p_accessor, bool p_for_vertex);
Vector<Transform2D> _decode_accessor_as_xform2d(GLTFState &state, int p_accessor, bool p_for_vertex);
Vector<Basis> _decode_accessor_as_basis(GLTFState &state, int p_accessor, bool p_for_vertex);
Vector<Transform> _decode_accessor_as_xform(GLTFState &state, int p_accessor, bool p_for_vertex);
void _generate_bone(GLTFState &state, int p_node, Vector<Skeleton *> &skeletons, int p_parent_bone);
void _generate_node(GLTFState &state, int p_node, Node *p_parent, Node *p_owner, Vector<Skeleton *> &skeletons);
- Spatial *_generate_scene(GLTFState &state);
+ void _import_animation(GLTFState &state, AnimationPlayer *ap, int index, int bake_fps, Vector<Skeleton *> skeletons);
+
+ Spatial *_generate_scene(GLTFState &state, int p_bake_fps);
Error _parse_meshes(GLTFState &state);
Error _parse_images(GLTFState &state, const String &p_base_path);
@@ -244,8 +285,13 @@ class EditorSceneImporterGLTF : public EditorSceneImporter {
Error _parse_cameras(GLTFState &state);
+ Error _parse_animations(GLTFState &state);
+
void _assign_scene_names(GLTFState &state);
+ template <class T>
+ T _interpolate_track(const Vector<float> &p_times, const Vector<T> &p_values, float p_time, GLTFAnimation::Interpolation p_interp);
+
public:
virtual uint32_t get_import_flags() const;
virtual void get_extensions(List<String> *r_extensions) const;
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index 77c540b746..1873a3f58b 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -211,9 +211,11 @@ void ScriptEditorQuickOpen::_confirmed() {
void ScriptEditorQuickOpen::_notification(int p_what) {
- if (p_what == NOTIFICATION_ENTER_TREE) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
- connect("confirmed", this, "_confirmed");
+ connect("confirmed", this, "_confirmed");
+ } break;
}
}
@@ -1064,58 +1066,73 @@ void ScriptEditor::_tab_changed(int p_which) {
void ScriptEditor::_notification(int p_what) {
- if (p_what == NOTIFICATION_ENTER_TREE) {
-
- editor->connect("play_pressed", this, "_editor_play");
- editor->connect("pause_pressed", this, "_editor_pause");
- editor->connect("stop_pressed", this, "_editor_stop");
- editor->connect("script_add_function_request", this, "_add_callback");
- editor->connect("resource_saved", this, "_res_saved_callback");
- script_list->connect("item_selected", this, "_script_selected");
- members_overview->connect("item_selected", this, "_members_overview_selected");
- script_split->connect("dragged", this, "_script_split_dragged");
- autosave_timer->connect("timeout", this, "_autosave_scripts");
- {
- float autosave_time = EditorSettings::get_singleton()->get("text_editor/files/autosave_interval_secs");
- if (autosave_time > 0) {
- autosave_timer->set_wait_time(autosave_time);
- autosave_timer->start();
- } else {
- autosave_timer->stop();
+ switch (p_what) {
+
+ case NOTIFICATION_ENTER_TREE: {
+
+ editor->connect("play_pressed", this, "_editor_play");
+ editor->connect("pause_pressed", this, "_editor_pause");
+ editor->connect("stop_pressed", this, "_editor_stop");
+ editor->connect("script_add_function_request", this, "_add_callback");
+ editor->connect("resource_saved", this, "_res_saved_callback");
+ script_list->connect("item_selected", this, "_script_selected");
+ members_overview->connect("item_selected", this, "_members_overview_selected");
+ script_split->connect("dragged", this, "_script_split_dragged");
+ autosave_timer->connect("timeout", this, "_autosave_scripts");
+ {
+ float autosave_time = EditorSettings::get_singleton()->get("text_editor/files/autosave_interval_secs");
+ if (autosave_time > 0) {
+ autosave_timer->set_wait_time(autosave_time);
+ autosave_timer->start();
+ } else {
+ autosave_timer->stop();
+ }
}
- }
- EditorSettings::get_singleton()->connect("settings_changed", this, "_editor_settings_changed");
- help_search->set_icon(get_icon("HelpSearch", "EditorIcons"));
- site_search->set_icon(get_icon("Instance", "EditorIcons"));
- class_search->set_icon(get_icon("ClassList", "EditorIcons"));
+ EditorSettings::get_singleton()->connect("settings_changed", this, "_editor_settings_changed");
+ help_search->set_icon(get_icon("HelpSearch", "EditorIcons"));
+ site_search->set_icon(get_icon("Instance", "EditorIcons"));
+ class_search->set_icon(get_icon("ClassList", "EditorIcons"));
- script_forward->set_icon(get_icon("Forward", "EditorIcons"));
- script_back->set_icon(get_icon("Back", "EditorIcons"));
- }
+ script_forward->set_icon(get_icon("Forward", "EditorIcons"));
+ script_back->set_icon(get_icon("Back", "EditorIcons"));
+ } break;
- if (p_what == NOTIFICATION_READY) {
+ case NOTIFICATION_READY: {
- get_tree()->connect("tree_changed", this, "_tree_changed");
- editor->connect("request_help", this, "_request_help");
- editor->connect("request_help_search", this, "_help_search");
- editor->connect("request_help_index", this, "_help_index");
- }
+ get_tree()->connect("tree_changed", this, "_tree_changed");
+ editor->connect("request_help", this, "_request_help");
+ editor->connect("request_help_search", this, "_help_search");
+ editor->connect("request_help_index", this, "_help_index");
+ } break;
- if (p_what == NOTIFICATION_EXIT_TREE) {
+ case NOTIFICATION_EXIT_TREE: {
- editor->disconnect("play_pressed", this, "_editor_play");
- editor->disconnect("pause_pressed", this, "_editor_pause");
- editor->disconnect("stop_pressed", this, "_editor_stop");
- }
+ editor->disconnect("play_pressed", this, "_editor_play");
+ editor->disconnect("pause_pressed", this, "_editor_pause");
+ editor->disconnect("stop_pressed", this, "_editor_stop");
+ } break;
- if (p_what == MainLoop::NOTIFICATION_WM_FOCUS_IN) {
+ case MainLoop::NOTIFICATION_WM_FOCUS_IN: {
- _test_script_times_on_disk();
- _update_modified_scripts_for_external_editor();
- }
+ _test_script_times_on_disk();
+ _update_modified_scripts_for_external_editor();
+ } break;
+
+ case NOTIFICATION_PROCESS: {
+ } break;
- if (p_what == NOTIFICATION_PROCESS) {
+ case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
+
+ tab_container->add_style_override("panel", editor->get_gui_base()->get_stylebox("ScriptPanel", "EditorStyles"));
+
+ Ref<StyleBox> sb = editor->get_gui_base()->get_stylebox("panel", "TabContainer")->duplicate();
+ sb->set_default_margin(MARGIN_TOP, 0);
+ add_style_override("panel", sb);
+ } break;
+
+ default:
+ break;
}
}
diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp
index d12b979121..e7bc8a4dab 100644
--- a/editor/plugins/tile_map_editor_plugin.cpp
+++ b/editor/plugins/tile_map_editor_plugin.cpp
@@ -330,6 +330,8 @@ PoolVector<Vector2> TileMapEditor::_bucket_fill(const Point2i &p_start, bool era
if (id == TileMap::INVALID_CELL)
return PoolVector<Vector2>();
+ } else if (prev_id == TileMap::INVALID_CELL) {
+ return PoolVector<Vector2>();
}
Rect2i r = node->get_item_rect();
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
index 82f17b80d5..d5a56f644f 100644
--- a/editor/project_manager.cpp
+++ b/editor/project_manager.cpp
@@ -573,7 +573,7 @@ void ProjectManager::_unhandled_input(const Ref<InputEvent> &p_ev) {
switch (k->get_scancode()) {
- case KEY_RETURN: {
+ case KEY_ENTER: {
_open_project();
} break;
diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp
index 42485317c1..6b02afe0c1 100644
--- a/editor/property_editor.cpp
+++ b/editor/property_editor.cpp
@@ -3858,7 +3858,7 @@ void PropertyEditor::_item_edited() {
break;
if (type == Variant::INT)
- _edit_set(name, round(item->get_range(1)), refresh_all);
+ _edit_set(name, int64_t(round(item->get_range(1))), refresh_all);
else
_edit_set(name, item->get_range(1), refresh_all);
} break;
diff --git a/modules/gdnative/gdnative.cpp b/modules/gdnative/gdnative.cpp
index 158f7fd94d..07dba921b1 100644
--- a/modules/gdnative/gdnative.cpp
+++ b/modules/gdnative/gdnative.cpp
@@ -155,7 +155,6 @@ String GDNativeLibrary::get_active_library_path() const {
}
GDNative::GDNative() {
- initialized = false;
native_handle = NULL;
}
@@ -219,6 +218,9 @@ bool GDNative::initialize() {
library_init);
if (err || !library_init) {
+ OS::get_singleton()->close_dynamic_library(native_handle);
+ native_handle = NULL;
+ ERR_PRINT("Failed to obtain godot_gdnative_init symbol");
return false;
}
@@ -272,7 +274,11 @@ bool GDNative::terminate() {
OS::get_singleton()->close_dynamic_library(native_handle);
native_handle = NULL;
- return false;
+ return true;
+}
+
+bool GDNative::is_initialized() {
+ return (native_handle != NULL);
}
void GDNativeCallRegistry::register_native_call_type(StringName p_call_type, native_call_cb p_callback) {
diff --git a/modules/gdnative/gdnative.h b/modules/gdnative/gdnative.h
index f02741f4e3..b03866f432 100644
--- a/modules/gdnative/gdnative.h
+++ b/modules/gdnative/gdnative.h
@@ -117,7 +117,6 @@ class GDNative : public Reference {
GDCLASS(GDNative, Reference)
Ref<GDNativeLibrary> library;
- bool initialized;
// TODO(karroffel): different platforms? WASM????
void *native_handle;
diff --git a/modules/gdnative/godot/dictionary.cpp b/modules/gdnative/godot/dictionary.cpp
index ce402fa008..b92c8125bb 100644
--- a/modules/gdnative/godot/dictionary.cpp
+++ b/modules/gdnative/godot/dictionary.cpp
@@ -29,9 +29,10 @@
/*************************************************************************/
#include <godot/dictionary.h>
+#include "core/variant.h"
+
#include "core/dictionary.h"
#include "core/io/json.h"
-#include "core/variant.h"
#ifdef __cplusplus
extern "C" {
diff --git a/modules/gdnative/godot/node_path.cpp b/modules/gdnative/godot/node_path.cpp
index e718a9e55f..f4179361be 100644
--- a/modules/gdnative/godot/node_path.cpp
+++ b/modules/gdnative/godot/node_path.cpp
@@ -29,7 +29,7 @@
/*************************************************************************/
#include <godot/node_path.h>
-#include "core/path_db.h"
+#include "core/node_path.h"
#include "core/variant.h"
#ifdef __cplusplus
diff --git a/modules/gdnative/godot/variant.cpp b/modules/gdnative/godot/variant.cpp
index 506614583c..d814ef913c 100644
--- a/modules/gdnative/godot/variant.cpp
+++ b/modules/gdnative/godot/variant.cpp
@@ -433,7 +433,6 @@ godot_variant GDAPI godot_variant_call(godot_variant *p_self, const godot_string
Variant *dest = (Variant *)&raw_dest;
Variant::CallError error;
memnew_placement_custom(dest, Variant, Variant(self->call(*method, args, p_argcount, error)));
- *dest = self->call(StringName(*method), args, p_argcount, r_error);
if (r_error) {
r_error->error = (godot_variant_call_error_error)error.error;
r_error->argument = error.argument;
diff --git a/modules/nativescript/nativescript.cpp b/modules/nativescript/nativescript.cpp
index 226b5effa9..fb334e573c 100644
--- a/modules/nativescript/nativescript.cpp
+++ b/modules/nativescript/nativescript.cpp
@@ -1055,13 +1055,15 @@ void NativeScriptLanguage::unregister_script(NativeScript *script) {
void NativeScriptLanguage::call_libraries_cb(const StringName &name) {
// library_gdnatives is modified only from the main thread, so it's safe not to use mutex here
for (Map<String, Ref<GDNative> >::Element *L = library_gdnatives.front(); L; L = L->next()) {
- L->get()->call_native_raw(
- _noarg_call_type,
- name,
- NULL,
- 0,
- NULL,
- NULL);
+ if (L->get()->is_initialized()) {
+ L->get()->call_native_raw(
+ _noarg_call_type,
+ name,
+ NULL,
+ 0,
+ NULL,
+ NULL);
+ }
}
}
diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp
index 69aa10ebca..d5d8b8fe6e 100644
--- a/modules/visual_script/visual_script_nodes.cpp
+++ b/modules/visual_script/visual_script_nodes.cpp
@@ -2798,7 +2798,7 @@ public:
r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
return 0;
}
- *p_outputs[0] = subcall->call(VisualScriptLanguage::singleton->_subcall, p_inputs, input_args, r_error_str);
+ *p_outputs[0] = subcall->call(VisualScriptLanguage::singleton->_subcall, p_inputs, input_args, r_error);
return 0;
}
};
diff --git a/platform/android/build.gradle.template b/platform/android/build.gradle.template
index fd0907f820..1df56ce621 100644
--- a/platform/android/build.gradle.template
+++ b/platform/android/build.gradle.template
@@ -3,7 +3,7 @@ buildscript {
jcenter()
}
dependencies {
- classpath 'com.android.tools.build:gradle:2.3.1'
+ classpath 'com.android.tools.build:gradle:2.3.3'
$$GRADLE_CLASSPATH$$
}
}
@@ -31,7 +31,7 @@ android {
}
compileSdkVersion 23
- buildToolsVersion "25.0.3"
+ buildToolsVersion "26.0.1"
useLibrary 'org.apache.http.legacy'
packagingOptions {
diff --git a/platform/android/java/gradle.properties b/platform/android/java/gradle.properties
new file mode 100644
index 0000000000..aac7c9b461
--- /dev/null
+++ b/platform/android/java/gradle.properties
@@ -0,0 +1,17 @@
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx1536m
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
diff --git a/platform/android/java/gradle/wrapper/gradle-wrapper.jar b/platform/android/java/gradle/wrapper/gradle-wrapper.jar
index 8c0fb64a86..13372aef5e 100644
--- a/platform/android/java/gradle/wrapper/gradle-wrapper.jar
+++ b/platform/android/java/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/platform/android/java/gradle/wrapper/gradle-wrapper.properties b/platform/android/java/gradle/wrapper/gradle-wrapper.properties
index a11cc1b825..ee6901c9d7 100644
--- a/platform/android/java/gradle/wrapper/gradle-wrapper.properties
+++ b/platform/android/java/gradle/wrapper/gradle-wrapper.properties
@@ -1,7 +1,6 @@
-#Fri May 12 08:50:03 KST 2017
+#Sat Jul 29 16:10:03 ICT 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-bin.zip
-org.gradle.jvmargs=-Xmx1536M
+distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
diff --git a/platform/android/java/gradlew b/platform/android/java/gradlew
index 91a7e269e1..9d82f78915 100755
--- a/platform/android/java/gradlew
+++ b/platform/android/java/gradlew
@@ -42,11 +42,6 @@ case "`uname`" in
;;
esac
-# For Cygwin, ensure paths are in UNIX format before anything is touched.
-if $cygwin ; then
- [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
-fi
-
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
@@ -61,9 +56,9 @@ while [ -h "$PRG" ] ; do
fi
done
SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >&-
+cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
-cd "$SAVED" >&-
+cd "$SAVED" >/dev/null
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
@@ -114,6 +109,7 @@ fi
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
diff --git a/platform/haiku/key_mapping_haiku.cpp b/platform/haiku/key_mapping_haiku.cpp
index 9df7b2f047..3db31fa3e4 100644
--- a/platform/haiku/key_mapping_haiku.cpp
+++ b/platform/haiku/key_mapping_haiku.cpp
@@ -83,7 +83,7 @@ static _HaikuTranslatePair _fn_to_keycode[] = {
static _HaikuTranslatePair _hb_to_keycode[] = {
{ KEY_BACKSPACE, B_BACKSPACE },
{ KEY_TAB, B_TAB },
- { KEY_RETURN, B_RETURN },
+ { KEY_ENTER, B_RETURN },
{ KEY_CAPSLOCK, B_CAPS_LOCK },
{ KEY_ESCAPE, B_ESCAPE },
{ KEY_SPACE, B_SPACE },
diff --git a/platform/javascript/dom_keys.h b/platform/javascript/dom_keys.h
index 979731d157..4b8b764c45 100644
--- a/platform/javascript/dom_keys.h
+++ b/platform/javascript/dom_keys.h
@@ -249,7 +249,7 @@ int dom2godot_scancode(int dom_keycode) {
case DOM_VK_RETURN:
case DOM_VK_ENTER: // unused according to MDN
- return KEY_RETURN;
+ return KEY_ENTER;
case DOM_VK_SHIFT: return KEY_SHIFT;
case DOM_VK_CONTROL: return KEY_CONTROL;
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index 4a01532d89..cfa039c130 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -518,7 +518,7 @@ static int translateKey(unsigned int key) {
/* 21 */ KEY_BRACELEFT,
/* 22 */ KEY_I,
/* 23 */ KEY_P,
- /* 24 */ KEY_RETURN,
+ /* 24 */ KEY_ENTER,
/* 25 */ KEY_L,
/* 26 */ KEY_J,
/* 27 */ KEY_APOSTROPHE,
@@ -558,7 +558,7 @@ static int translateKey(unsigned int key) {
/* 49 */ KEY_UNKNOWN, /* VolumeDown */
/* 4a */ KEY_UNKNOWN, /* Mute */
/* 4b */ KEY_KP_DIVIDE,
- /* 4c */ KEY_ENTER,
+ /* 4c */ KEY_KP_ENTER,
/* 4d */ KEY_UNKNOWN,
/* 4e */ KEY_KP_SUBTRACT,
/* 4f */ KEY_UNKNOWN,
diff --git a/platform/uwp/joypad_uwp.cpp b/platform/uwp/joypad_uwp.cpp
index 34e36f7b66..f3d4eb99c8 100644
--- a/platform/uwp/joypad_uwp.cpp
+++ b/platform/uwp/joypad_uwp.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "joypad_uwp.h"
+#include "core/os/os.h"
using namespace Windows::Gaming::Input;
using namespace Windows::Foundation;
@@ -45,27 +46,44 @@ void JoypadUWP::process_controllers() {
for (int i = 0; i < MAX_CONTROLLERS; i++) {
- if (!controllers[i].connected) break;
+ ControllerDevice &joy = controllers[i];
- switch (controllers[i].type) {
+ if (!joy.connected) break;
+
+ switch (joy.type) {
case ControllerType::GAMEPAD_CONTROLLER: {
- GamepadReading reading = ((Gamepad ^)controllers[i].controller_reference)->GetCurrentReading();
+ GamepadReading reading = ((Gamepad ^) joy.controller_reference)->GetCurrentReading();
int button_mask = (int)GamepadButtons::Menu;
for (int j = 0; j < 14; j++) {
- input->joy_button(controllers[i].id, j, (int)reading.Buttons & button_mask);
+ input->joy_button(joy.id, j, (int)reading.Buttons & button_mask);
button_mask *= 2;
}
- input->joy_axis(controllers[i].id, JOY_AXIS_0, axis_correct(reading.LeftThumbstickX));
- input->joy_axis(controllers[i].id, JOY_AXIS_1, axis_correct(reading.LeftThumbstickY, true));
- input->joy_axis(controllers[i].id, JOY_AXIS_2, axis_correct(reading.RightThumbstickX));
- input->joy_axis(controllers[i].id, JOY_AXIS_3, axis_correct(reading.RightThumbstickY, true));
- input->joy_axis(controllers[i].id, JOY_AXIS_4, axis_correct(reading.LeftTrigger, false, true));
- input->joy_axis(controllers[i].id, JOY_AXIS_5, axis_correct(reading.RightTrigger, false, true));
+ input->joy_axis(joy.id, JOY_AXIS_0, axis_correct(reading.LeftThumbstickX));
+ input->joy_axis(joy.id, JOY_AXIS_1, axis_correct(reading.LeftThumbstickY, true));
+ input->joy_axis(joy.id, JOY_AXIS_2, axis_correct(reading.RightThumbstickX));
+ input->joy_axis(joy.id, JOY_AXIS_3, axis_correct(reading.RightThumbstickY, true));
+ input->joy_axis(joy.id, JOY_AXIS_4, axis_correct(reading.LeftTrigger, false, true));
+ input->joy_axis(joy.id, JOY_AXIS_5, axis_correct(reading.RightTrigger, false, true));
+
+ uint64_t timestamp = input->get_joy_vibration_timestamp(joy.id);
+ if (timestamp > joy.ff_timestamp) {
+ Vector2 strength = input->get_joy_vibration_strength(joy.id);
+ float duration = input->get_joy_vibration_duration(joy.id);
+ if (strength.x == 0 && strength.y == 0) {
+ joypad_vibration_stop(i, timestamp);
+ } else {
+ joypad_vibration_start(i, strength.x, strength.y, duration, timestamp);
+ }
+ } else if (joy.vibrating && joy.ff_end_timestamp != 0) {
+ uint64_t current_time = OS::get_singleton()->get_ticks_usec();
+ if (current_time >= joy.ff_end_timestamp)
+ joypad_vibration_stop(i, current_time);
+ }
break;
}
@@ -122,15 +140,7 @@ void JoypadUWP::OnGamepadRemoved(Platform::Object ^ sender, Windows::Gaming::Inp
ERR_FAIL_COND(idx == -1);
- for (int i = idx + 1; i < MAX_CONTROLLERS - 1; i++) {
-
- if (!controllers[i].connected) {
- break;
- }
-
- controllers[i - 1] = controllers[i];
- }
- controllers[MAX_CONTROLLERS - 1] = ControllerDevice();
+ controllers[idx] = ControllerDevice();
input->joy_connection_changed(idx, false, "Xbox Controller");
}
@@ -144,3 +154,30 @@ InputDefault::JoyAxis JoypadUWP::axis_correct(double p_val, bool p_negate, bool
return jx;
}
+
+void JoypadUWP::joypad_vibration_start(int p_device, float p_weak_magnitude, float p_strong_magnitude, float p_duration, uint64_t p_timestamp) {
+ ControllerDevice &joy = controllers[p_device];
+ if (joy.connected) {
+ GamepadVibration vibration;
+ vibration.LeftMotor = p_strong_magnitude;
+ vibration.RightMotor = p_weak_magnitude;
+ ((Gamepad ^) joy.controller_reference)->Vibration = vibration;
+
+ joy.ff_timestamp = p_timestamp;
+ joy.ff_end_timestamp = p_duration == 0 ? 0 : p_timestamp + (uint64_t)(p_duration * 1000000.0);
+ joy.vibrating = true;
+ }
+}
+
+void JoypadUWP::joypad_vibration_stop(int p_device, uint64_t p_timestamp) {
+ ControllerDevice &joy = controllers[p_device];
+ if (joy.connected) {
+ GamepadVibration vibration;
+ vibration.LeftMotor = 0.0;
+ vibration.RightMotor = 0.0;
+ ((Gamepad ^) joy.controller_reference)->Vibration = vibration;
+
+ joy.ff_timestamp = p_timestamp;
+ joy.vibrating = false;
+ }
+}
diff --git a/platform/uwp/joypad_uwp.h b/platform/uwp/joypad_uwp.h
index 7337ffb3ce..c55e1e7ab7 100644
--- a/platform/uwp/joypad_uwp.h
+++ b/platform/uwp/joypad_uwp.h
@@ -62,11 +62,17 @@ private:
int id;
bool connected;
ControllerType type;
+ float ff_timestamp;
+ float ff_end_timestamp;
+ bool vibrating;
ControllerDevice() {
id = -1;
connected = false;
type = ControllerType::GAMEPAD_CONTROLLER;
+ ff_timestamp = 0.0f;
+ ff_end_timestamp = 0.0f;
+ vibrating = false;
}
};
@@ -78,6 +84,8 @@ private:
void OnGamepadRemoved(Platform::Object ^ sender, Windows::Gaming::Input::Gamepad ^ value);
InputDefault::JoyAxis axis_correct(double p_val, bool p_negate = false, bool p_trigger = false) const;
+ void joypad_vibration_start(int p_device, float p_weak_magnitude, float p_strong_magnitude, float p_duration, uint64_t p_timestamp);
+ void joypad_vibration_stop(int p_device, uint64_t p_timestamp);
};
#endif
diff --git a/platform/windows/key_mapping_win.cpp b/platform/windows/key_mapping_win.cpp
index bffacb3a82..83e2af72b2 100644
--- a/platform/windows/key_mapping_win.cpp
+++ b/platform/windows/key_mapping_win.cpp
@@ -44,7 +44,7 @@ static _WinTranslatePair _vk_to_keycode[] = {
//VK_CLEAR (0x0C)
- { KEY_RETURN, VK_RETURN }, //(0x0D)
+ { KEY_ENTER, VK_RETURN }, //(0x0D)
{ KEY_SHIFT, VK_SHIFT }, //(0x10)
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index da14d5c284..9cab19fffb 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -807,7 +807,7 @@ void OS_Windows::process_key_events() {
if ((ke.lParam & (1 << 24)) && (ke.wParam == VK_RETURN)) {
// Special case for Numpad Enter key
- k->set_scancode(KEY_ENTER);
+ k->set_scancode(KEY_KP_ENTER);
} else {
k->set_scancode(KeyMappingWindows::get_keysym(ke.wParam));
}
@@ -1192,10 +1192,6 @@ void OS_Windows::finalize() {
main_loop = NULL;
- for (int i = 0; i < get_audio_driver_count(); i++) {
- AudioDriverManager::get_driver(i)->finish();
- }
-
memdelete(joypad);
memdelete(input);
diff --git a/platform/x11/key_mapping_x11.cpp b/platform/x11/key_mapping_x11.cpp
index 1d7eb1692c..32a9806b22 100644
--- a/platform/x11/key_mapping_x11.cpp
+++ b/platform/x11/key_mapping_x11.cpp
@@ -44,7 +44,7 @@ static _XTranslatePair _xkeysym_to_keycode[] = {
{ XK_Tab, KEY_TAB },
{ XK_ISO_Left_Tab, KEY_BACKTAB },
{ XK_BackSpace, KEY_BACKSPACE },
- { XK_Return, KEY_RETURN },
+ { XK_Return, KEY_ENTER },
{ XK_Insert, KEY_INSERT },
{ XK_Delete, KEY_DELETE },
{ XK_Clear, KEY_DELETE },
@@ -78,7 +78,7 @@ static _XTranslatePair _xkeysym_to_keycode[] = {
{ XK_Help, KEY_HELP },
{ XK_KP_Space, KEY_SPACE },
{ XK_KP_Tab, KEY_TAB },
- { XK_KP_Enter, KEY_ENTER },
+ { XK_KP_Enter, KEY_KP_ENTER },
{ XK_Home, KEY_HOME },
{ XK_Left, KEY_LEFT },
{ XK_Up, KEY_UP },
diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp
index 1dde328eda..ade3a0a0c5 100644
--- a/platform/x11/os_x11.cpp
+++ b/platform/x11/os_x11.cpp
@@ -529,10 +529,6 @@ void OS_X11::finalize() {
memdelete(main_loop);
main_loop = NULL;
- for (int i = 0; i < get_audio_driver_count(); i++) {
- AudioDriverManager::get_driver(i)->finish();
- }
-
/*
if (debugger_connection_console) {
memdelete(debugger_connection_console);
diff --git a/scene/2d/animated_sprite.cpp b/scene/2d/animated_sprite.cpp
index 22649cedd7..b10ee85da5 100644
--- a/scene/2d/animated_sprite.cpp
+++ b/scene/2d/animated_sprite.cpp
@@ -346,6 +346,7 @@ void AnimatedSprite::_notification(int p_what) {
update();
_change_notify("frame");
+ emit_signal(SceneStringNames::get_singleton()->frame_changed);
}
float to_process = MIN(timeout, remaining);
diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp
index 0acc85681d..82efe1d7fb 100644
--- a/scene/2d/node_2d.cpp
+++ b/scene/2d/node_2d.cpp
@@ -243,7 +243,7 @@ void Node2D::global_translate(const Vector2 &p_amount) {
set_global_position(get_global_position() + p_amount);
}
-void Node2D::scale(const Size2 &p_amount) {
+void Node2D::apply_scale(const Size2 &p_amount) {
set_scale(get_scale() * p_amount);
}
@@ -429,7 +429,7 @@ void Node2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("move_local_y", "delta", "scaled"), &Node2D::move_y, DEFVAL(false));
ClassDB::bind_method(D_METHOD("translate", "offset"), &Node2D::translate);
ClassDB::bind_method(D_METHOD("global_translate", "offset"), &Node2D::global_translate);
- ClassDB::bind_method(D_METHOD("scale", "ratio"), &Node2D::scale);
+ ClassDB::bind_method(D_METHOD("apply_scale", "ratio"), &Node2D::apply_scale);
ClassDB::bind_method(D_METHOD("set_global_position", "pos"), &Node2D::set_global_position);
ClassDB::bind_method(D_METHOD("get_global_position"), &Node2D::get_global_position);
diff --git a/scene/2d/node_2d.h b/scene/2d/node_2d.h
index 5b3a28d5c3..df9a05ff79 100644
--- a/scene/2d/node_2d.h
+++ b/scene/2d/node_2d.h
@@ -78,7 +78,7 @@ public:
void move_y(float p_delta, bool p_scaled = false);
void translate(const Vector2 &p_amount);
void global_translate(const Vector2 &p_amount);
- void scale(const Size2 &p_amount);
+ void apply_scale(const Size2 &p_amount);
Point2 get_position() const;
float get_rotation() const;
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index 8b2653f639..d5527fc9ca 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -798,6 +798,40 @@ bool RigidBody2D::is_contact_monitor_enabled() const {
return contact_monitor != NULL;
}
+void RigidBody2D::_notification(int p_what) {
+
+#ifdef TOOLS_ENABLED
+ if (p_what == NOTIFICATION_ENTER_TREE) {
+ if (get_tree()->is_editor_hint()) {
+ set_notify_local_transform(true); //used for warnings and only in editor
+ }
+ }
+
+ if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) {
+ if (get_tree()->is_editor_hint()) {
+ update_configuration_warning();
+ }
+ }
+
+#endif
+}
+
+String RigidBody2D::get_configuration_warning() const {
+
+ Transform2D t = get_transform();
+
+ String warning = CollisionObject2D::get_configuration_warning();
+
+ if ((get_mode() == MODE_RIGID || get_mode() == MODE_CHARACTER) && (ABS(t.elements[0].length() - 1.0) > 0.05 || ABS(t.elements[1].length() - 1.0) > 0.05)) {
+ if (warning != String()) {
+ warning += "\n";
+ }
+ warning += TTR("Size changes to RigidBody2D (in character or rigid modes) will be overriden by the physics engine when running.\nChange the size in children collision shapes instead.");
+ }
+
+ return warning;
+}
+
void RigidBody2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_mode", "mode"), &RigidBody2D::set_mode);
diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h
index 8c8e4ebc77..54bd263b15 100644
--- a/scene/2d/physics_body_2d.h
+++ b/scene/2d/physics_body_2d.h
@@ -185,6 +185,7 @@ private:
bool _test_motion(const Vector2 &p_motion, float p_margin = 0.08, const Ref<Physics2DTestMotionResult> &p_result = Ref<Physics2DTestMotionResult>());
protected:
+ void _notification(int p_what);
static void _bind_methods();
public:
@@ -253,6 +254,8 @@ public:
Array get_colliding_bodies() const; //function for script
+ virtual String get_configuration_warning() const;
+
RigidBody2D();
~RigidBody2D();
};
diff --git a/scene/2d/sprite.cpp b/scene/2d/sprite.cpp
index ad34dfd63a..01d101a89c 100644
--- a/scene/2d/sprite.cpp
+++ b/scene/2d/sprite.cpp
@@ -237,7 +237,7 @@ void Sprite::set_vframes(int p_amount) {
vframes = p_amount;
update();
item_rect_changed();
- _change_notify("frame");
+ _change_notify();
}
int Sprite::get_vframes() const {
@@ -250,7 +250,7 @@ void Sprite::set_hframes(int p_amount) {
hframes = p_amount;
update();
item_rect_changed();
- _change_notify("frame");
+ _change_notify();
}
int Sprite::get_hframes() const {
diff --git a/scene/2d/visibility_notifier_2d.cpp b/scene/2d/visibility_notifier_2d.cpp
index a37c74cb07..fb71b61d45 100644
--- a/scene/2d/visibility_notifier_2d.cpp
+++ b/scene/2d/visibility_notifier_2d.cpp
@@ -33,6 +33,7 @@
#include "scene/2d/animated_sprite.h"
#include "scene/2d/physics_body_2d.h"
#include "scene/animation/animation_player.h"
+#include "scene/main/viewport.h"
#include "scene/scene_string_names.h"
#include "scene/scene_string_names.h"
diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp
index 7e599ce2f5..9feed2fe7b 100644
--- a/scene/3d/physics_body.cpp
+++ b/scene/3d/physics_body.cpp
@@ -473,6 +473,21 @@ void RigidBody::_direct_state_changed(Object *p_state) {
}
void RigidBody::_notification(int p_what) {
+
+#ifdef TOOLS_ENABLED
+ if (p_what == NOTIFICATION_ENTER_TREE) {
+ if (get_tree()->is_editor_hint()) {
+ set_notify_local_transform(true); //used for warnings and only in editor
+ }
+ }
+
+ if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) {
+ if (get_tree()->is_editor_hint()) {
+ update_configuration_warning();
+ }
+ }
+
+#endif
}
void RigidBody::set_mode(Mode p_mode) {
@@ -747,6 +762,22 @@ Array RigidBody::get_colliding_bodies() const {
return ret;
}
+String RigidBody::get_configuration_warning() const {
+
+ Transform t = get_transform();
+
+ String warning = CollisionObject::get_configuration_warning();
+
+ if ((get_mode() == MODE_RIGID || get_mode() == MODE_CHARACTER) && (ABS(t.basis.get_axis(0).length() - 1.0) > 0.05 || ABS(t.basis.get_axis(1).length() - 1.0) > 0.05 || ABS(t.basis.get_axis(0).length() - 1.0) > 0.05)) {
+ if (warning != String()) {
+ warning += "\n";
+ }
+ warning += TTR("Size changes to RigidBody (in character or rigid modes) will be overriden by the physics engine when running.\nChange the size in children collision shapes instead.");
+ }
+
+ return warning;
+}
+
void RigidBody::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_mode", "mode"), &RigidBody::set_mode);
diff --git a/scene/3d/physics_body.h b/scene/3d/physics_body.h
index f86d7d957f..83811a1d93 100644
--- a/scene/3d/physics_body.h
+++ b/scene/3d/physics_body.h
@@ -252,6 +252,8 @@ public:
void apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse);
+ virtual String get_configuration_warning() const;
+
RigidBody();
~RigidBody();
};
diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp
index 78e8e92afc..1b9b58ceb1 100644
--- a/scene/3d/sprite_3d.cpp
+++ b/scene/3d/sprite_3d.cpp
@@ -502,7 +502,7 @@ void Sprite3D::set_vframes(int p_amount) {
ERR_FAIL_COND(p_amount < 1);
vframes = p_amount;
_queue_update();
- _change_notify("frame");
+ _change_notify();
}
int Sprite3D::get_vframes() const {
@@ -514,7 +514,7 @@ void Sprite3D::set_hframes(int p_amount) {
ERR_FAIL_COND(p_amount < 1);
hframes = p_amount;
_queue_update();
- _change_notify("frame");
+ _change_notify();
}
int Sprite3D::get_hframes() const {
diff --git a/scene/3d/visibility_notifier.cpp b/scene/3d/visibility_notifier.cpp
index 5e6561adb7..cc81a4cb56 100644
--- a/scene/3d/visibility_notifier.cpp
+++ b/scene/3d/visibility_notifier.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "visibility_notifier.h"
+#include "scene/3d/camera.h"
#include "scene/3d/physics_body.h"
#include "scene/animation/animation_player.h"
#include "scene/scene_string_names.h"
@@ -42,6 +43,7 @@ void VisibilityNotifier::_enter_camera(Camera *p_camera) {
emit_signal(SceneStringNames::get_singleton()->screen_entered);
_screen_enter();
}
+
emit_signal(SceneStringNames::get_singleton()->camera_entered, p_camera);
}
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp
index 543b64bd15..85a9ada38a 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -1268,7 +1268,7 @@ void AnimationPlayer::_bind_methods() {
ClassDB::bind_method(D_METHOD("advance", "delta"), &AnimationPlayer::advance);
- ADD_GROUP("Playback", "playback_");
+ ADD_GROUP("Playback Options", "playback_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "playback_process_mode", PROPERTY_HINT_ENUM, "Fixed,Idle"), "set_animation_process_mode", "get_animation_process_mode");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "playback_default_blend_time", PROPERTY_HINT_RANGE, "0,4096,0.01"), "set_default_blend_time", "get_default_blend_time");
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "root_node"), "set_root", "get_root");
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp
index 9a5f55698e..4d55d8df75 100644
--- a/scene/gui/base_button.cpp
+++ b/scene/gui/base_button.cpp
@@ -508,7 +508,7 @@ void BaseButton::_bind_methods() {
ADD_SIGNAL(MethodInfo("toggled", PropertyInfo(Variant::BOOL, "pressed")));
ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "toggle_mode"), "set_toggle_mode", "is_toggle_mode");
- ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "is_pressed"), "set_pressed", "is_pressed");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "pressed"), "set_pressed", "is_pressed");
ADD_PROPERTYNO(PropertyInfo(Variant::INT, "action_mode", PROPERTY_HINT_ENUM, "Button Press,Button Release"), "set_action_mode", "get_action_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "enabled_focus_mode", PROPERTY_HINT_ENUM, "None,Click,All"), "set_enabled_focus_mode", "get_enabled_focus_mode");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shortcut", PROPERTY_HINT_RESOURCE_TYPE, "ShortCut"), "set_shortcut", "get_shortcut");
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index f4dd3e92cd..8556ce5db1 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -229,8 +229,8 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
bool handled = true;
switch (code) {
- case KEY_ENTER:
- case KEY_RETURN: {
+ case KEY_KP_ENTER:
+ case KEY_ENTER: {
emit_signal("text_entered", text);
if (OS::get_singleton()->has_virtual_keyboard())
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index f59a2e06eb..b673f9d68a 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -249,8 +249,8 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) {
}
}
} break;
- case KEY_RETURN:
- case KEY_ENTER: {
+ case KEY_ENTER:
+ case KEY_KP_ENTER: {
if (mouse_over >= 0 && mouse_over < items.size() && !items[mouse_over].separator) {
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 2fc3204f3a..a7c31361e8 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -1805,7 +1805,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
return;
}
- if (k->get_scancode() == KEY_ENTER || k->get_scancode() == KEY_RETURN || k->get_scancode() == KEY_TAB) {
+ if (k->get_scancode() == KEY_KP_ENTER || k->get_scancode() == KEY_ENTER || k->get_scancode() == KEY_TAB) {
_confirm_completion();
accept_event();
@@ -1974,8 +1974,8 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
switch (k->get_scancode()) {
- case KEY_ENTER:
- case KEY_RETURN: {
+ case KEY_KP_ENTER:
+ case KEY_ENTER: {
if (readonly)
break;
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 0b57841be7..9499ba9dcd 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -1917,8 +1917,8 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
void Tree::_text_editor_modal_close() {
if (Input::get_singleton()->is_key_pressed(KEY_ESCAPE) ||
- Input::get_singleton()->is_key_pressed(KEY_ENTER) ||
- Input::get_singleton()->is_key_pressed(KEY_RETURN)) {
+ Input::get_singleton()->is_key_pressed(KEY_KP_ENTER) ||
+ Input::get_singleton()->is_key_pressed(KEY_ENTER)) {
return;
}
@@ -2237,8 +2237,8 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
} break;
case KEY_F2:
- case KEY_RETURN:
- case KEY_ENTER: {
+ case KEY_ENTER:
+ case KEY_KP_ENTER: {
if (selected_item) {
//bring up editor if possible
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index c3849f79df..fcb9c1a842 100755
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -705,12 +705,12 @@ void Node::rpcp(int p_peer_id, bool p_unreliable, const StringName &p_method, co
ERR_FAIL_COND(!is_inside_tree());
bool skip_rpc = false;
+ bool call_local_native = false;
+ bool call_local_script = false;
if (p_peer_id == 0 || p_peer_id == get_tree()->get_network_unique_id() || (p_peer_id < 0 && p_peer_id != -get_tree()->get_network_unique_id())) {
//check that send mode can use local call
- bool call_local = false;
-
Map<StringName, RPCMode>::Element *E = data.rpc_methods.find(p_method);
if (E) {
@@ -724,29 +724,22 @@ void Node::rpcp(int p_peer_id, bool p_unreliable, const StringName &p_method, co
} break;
case RPC_MODE_SYNC: {
//call it, sync always results in call
- call_local = true;
+ call_local_native = true;
} break;
case RPC_MODE_MASTER: {
- call_local = is_network_master();
- if (call_local) {
+ call_local_native = is_network_master();
+ if (call_local_native) {
skip_rpc = true; //no other master so..
}
} break;
case RPC_MODE_SLAVE: {
- call_local = !is_network_master();
+ call_local_native = !is_network_master();
} break;
}
}
- if (call_local) {
- Variant::CallError ce;
- call(p_method, p_arg, p_argcount, ce);
- if (ce.error != Variant::CallError::CALL_OK) {
- String error = Variant::get_call_error_text(this, p_method, p_arg, p_argcount, ce);
- error = "rpc() aborted in local call: - " + error;
- ERR_PRINTS(error);
- return;
- }
+ if (call_local_native) {
+ // done below
} else if (get_script_instance()) {
//attempt with script
ScriptInstance::RPCMode rpc_mode = get_script_instance()->get_rpc_mode(p_method);
@@ -761,37 +754,47 @@ void Node::rpcp(int p_peer_id, bool p_unreliable, const StringName &p_method, co
} break;
case ScriptInstance::RPC_MODE_SYNC: {
//call it, sync always results in call
- call_local = true;
+ call_local_script = true;
} break;
case ScriptInstance::RPC_MODE_MASTER: {
- call_local = is_network_master();
- if (call_local) {
+ call_local_script = is_network_master();
+ if (call_local_script) {
skip_rpc = true; //no other master so..
}
} break;
case ScriptInstance::RPC_MODE_SLAVE: {
- call_local = !is_network_master();
+ call_local_script = !is_network_master();
} break;
}
-
- if (call_local) {
- Variant::CallError ce;
- ce.error = Variant::CallError::CALL_OK;
- get_script_instance()->call(p_method, p_arg, p_argcount, ce);
- if (ce.error != Variant::CallError::CALL_OK) {
- String error = Variant::get_call_error_text(this, p_method, p_arg, p_argcount, ce);
- error = "rpc() aborted in script local call: - " + error;
- ERR_PRINTS(error);
- return;
- }
- }
}
}
- if (skip_rpc)
- return;
+ if (!skip_rpc) {
+ get_tree()->_rpc(this, p_peer_id, p_unreliable, false, p_method, p_arg, p_argcount);
+ }
+
+ if (call_local_native) {
+ Variant::CallError ce;
+ call(p_method, p_arg, p_argcount, ce);
+ if (ce.error != Variant::CallError::CALL_OK) {
+ String error = Variant::get_call_error_text(this, p_method, p_arg, p_argcount, ce);
+ error = "rpc() aborted in local call: - " + error;
+ ERR_PRINTS(error);
+ return;
+ }
+ }
- get_tree()->_rpc(this, p_peer_id, p_unreliable, false, p_method, p_arg, p_argcount);
+ if (call_local_script) {
+ Variant::CallError ce;
+ ce.error = Variant::CallError::CALL_OK;
+ get_script_instance()->call(p_method, p_arg, p_argcount, ce);
+ if (ce.error != Variant::CallError::CALL_OK) {
+ String error = Variant::get_call_error_text(this, p_method, p_arg, p_argcount, ce);
+ error = "rpc() aborted in script local call: - " + error;
+ ERR_PRINTS(error);
+ return;
+ }
+ }
}
/******** RSET *********/
diff --git a/scene/main/node.h b/scene/main/node.h
index 1794cce9f6..0447deccc1 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -33,7 +33,7 @@
#include "class_db.h"
#include "map.h"
#include "object.h"
-#include "path_db.h"
+#include "node_path.h"
#include "project_settings.h"
#include "scene/main/scene_tree.h"
#include "script_language.h"
diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp
index 6bf3590c12..648900a5cd 100644
--- a/scene/resources/packed_scene.cpp
+++ b/scene/resources/packed_scene.cpp
@@ -516,6 +516,9 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Map
bool isdefault = ((E->get().usage & PROPERTY_USAGE_STORE_IF_NONZERO) && value.is_zero()) || ((E->get().usage & PROPERTY_USAGE_STORE_IF_NONONE) && value.is_one());
+ if (E->get().usage & PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE) {
+ isdefault = true; //is script default value
+ }
/*
if (nd.instance<0 && ((E->get().usage & PROPERTY_USAGE_STORE_IF_NONZERO) && value.is_zero()) || ((E->get().usage & PROPERTY_USAGE_STORE_IF_NONONE) && value.is_one())) {
continue;
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp
index fe7cd0097c..f69c83bf08 100644
--- a/scene/resources/texture.cpp
+++ b/scene/resources/texture.cpp
@@ -73,6 +73,7 @@ void Texture::_bind_methods() {
ClassDB::bind_method(D_METHOD("draw", "canvas_item", "pos", "modulate", "transpose", "normal_map:Texture"), &Texture::draw, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("draw_rect", "canvas_item", "rect", "tile", "modulate", "transpose", "normal_map:Texture"), &Texture::draw_rect, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("draw_rect_region", "canvas_item", "rect", "src_rect", "modulate", "transpose", "normal_map:Texture", "clip_uv"), &Texture::draw_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant()), DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("get_data:Image"), &Texture::get_data);
BIND_CONSTANT(FLAG_MIPMAPS);
BIND_CONSTANT(FLAG_REPEAT);
@@ -194,6 +195,7 @@ void ImageTexture::create(int p_width, int p_height, Image::Format p_format, uin
}
void ImageTexture::create_from_image(const Ref<Image> &p_image, uint32_t p_flags) {
+ ERR_FAIL_COND(p_image.is_null());
flags = p_flags;
w = p_image->get_width();
h = p_image->get_height();
@@ -352,7 +354,6 @@ void ImageTexture::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_format"), &ImageTexture::get_format);
ClassDB::bind_method(D_METHOD("load", "path"), &ImageTexture::load);
ClassDB::bind_method(D_METHOD("set_data", "image:Image"), &ImageTexture::set_data);
- ClassDB::bind_method(D_METHOD("get_data:Image", "cube_side"), &ImageTexture::get_data);
ClassDB::bind_method(D_METHOD("set_storage", "mode"), &ImageTexture::set_storage);
ClassDB::bind_method(D_METHOD("get_storage"), &ImageTexture::get_storage);
ClassDB::bind_method(D_METHOD("set_lossy_storage_quality", "quality"), &ImageTexture::set_lossy_storage_quality);
diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp
index ec71333ded..f247e7cde8 100644
--- a/scene/scene_string_names.cpp
+++ b/scene/scene_string_names.cpp
@@ -142,9 +142,9 @@ SceneStringNames::SceneStringNames() {
h_offset = StaticCString::create("h_offset");
v_offset = StaticCString::create("v_offset");
- transform_pos = StaticCString::create("transform/pos");
- transform_rot = StaticCString::create("transform/rot");
- transform_scale = StaticCString::create("transform/scale");
+ transform_pos = StaticCString::create("position");
+ transform_rot = StaticCString::create("rotation_deg");
+ transform_scale = StaticCString::create("scale");
_update_remote = StaticCString::create("_update_remote");
_update_pairs = StaticCString::create("_update_pairs");
@@ -158,8 +158,6 @@ SceneStringNames::SceneStringNames() {
line_separation = StaticCString::create("line_separation");
- play_play = StaticCString::create("play/play");
-
get_drag_data = StaticCString::create("get_drag_data");
drop_data = StaticCString::create("drop_data");
can_drop_data = StaticCString::create("can_drop_data");
diff --git a/scene/scene_string_names.h b/scene/scene_string_names.h
index 0802a73973..0b70cd36ff 100644
--- a/scene/scene_string_names.h
+++ b/scene/scene_string_names.h
@@ -30,7 +30,7 @@
#ifndef SCENE_STRING_NAMES_H
#define SCENE_STRING_NAMES_H
-#include "path_db.h"
+#include "node_path.h"
#include "string_db.h"
class SceneStringNames {
@@ -173,8 +173,6 @@ public:
StringName _get_minimum_size;
- StringName play_play;
-
StringName _im_update;
StringName _queue_update;
diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp
index 0d2550e53b..d5f351454d 100644
--- a/servers/audio_server.cpp
+++ b/servers/audio_server.cpp
@@ -772,10 +772,11 @@ void AudioServer::finish() {
buses.clear();
- if (AudioDriver::get_singleton()) {
- AudioDriver::get_singleton()->finish();
+ for (int i = 0; i < AudioDriverManager::get_driver_count(); i++) {
+ AudioDriverManager::get_driver(i)->finish();
}
}
+
void AudioServer::update() {
}