diff options
122 files changed, 1762 insertions, 360 deletions
diff --git a/.gitignore b/.gitignore index 52937b8679..3a05ed9e7d 100644 --- a/.gitignore +++ b/.gitignore @@ -238,6 +238,7 @@ ClientBin/ *.pfx *.publishsettings node_modules/ +__pycache__/ # KDE .directory diff --git a/SConstruct b/SConstruct index f8c1c82961..628aac42af 100644 --- a/SConstruct +++ b/SConstruct @@ -349,7 +349,10 @@ if selected_platform in platform_list: else: # always enable those errors env.Append(CCFLAGS=['-Werror=return-type']) - suffix = "." + selected_platform + if (hasattr(detect, 'get_program_suffix')): + suffix = "." + detect.get_program_suffix() + else: + suffix = "." + selected_platform if (env["target"] == "release"): if env["tools"]: @@ -544,7 +547,7 @@ if 'env' in locals(): [os.remove(f) for f in files] def file_list(self): - if self.path == None: + if self.path is None: # Nothing to do return [] # Gather a list of (filename, (size, atime)) within the @@ -569,7 +572,7 @@ if 'env' in locals(): if sum > self.limit: mark = i break - if mark == None: + if mark is None: return [] else: return [x[0] for x in file_stat[mark:]] diff --git a/core/color.cpp b/core/color.cpp index 55dd1ec6b9..ac314417ec 100644 --- a/core/color.cpp +++ b/core/color.cpp @@ -468,7 +468,7 @@ String Color::to_html(bool p_alpha) const { return txt; } -Color Color::from_hsv(float p_h, float p_s, float p_v, float p_a) { +Color Color::from_hsv(float p_h, float p_s, float p_v, float p_a) const { p_h = Math::fmod(p_h * 360.0f, 360.0f); if (p_h < 0.0) diff --git a/core/color.h b/core/color.h index add61343ff..d6ad5f91c5 100644 --- a/core/color.h +++ b/core/color.h @@ -194,7 +194,7 @@ struct Color { static bool html_is_valid(const String &p_color); static Color named(const String &p_name); String to_html(bool p_alpha = true) const; - Color from_hsv(float p_h, float p_s, float p_v, float p_a); + Color from_hsv(float p_h, float p_s, float p_v, float p_a) const; static Color from_rgbe9995(uint32_t p_color); _FORCE_INLINE_ bool operator<(const Color &p_color) const; //used in set keys diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index d156a9f4bd..71b01aa94a 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -259,6 +259,10 @@ RES ResourceLoader::load(const String &p_path, const String &p_type_hint, bool p } #endif + if (_loaded_callback) { + _loaded_callback(res, p_path); + } + return res; } @@ -635,6 +639,12 @@ void ResourceLoader::clear_path_remaps() { path_remaps.clear(); } +void ResourceLoader::set_load_callback(ResourceLoadedCallback p_callback) { + _loaded_callback = p_callback; +} + +ResourceLoadedCallback ResourceLoader::_loaded_callback = NULL; + ResourceLoadErrorNotify ResourceLoader::err_notify = NULL; void *ResourceLoader::err_notify_ud = NULL; diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h index 96bc6fa8dd..7ade4a2dfc 100644 --- a/core/io/resource_loader.h +++ b/core/io/resource_loader.h @@ -78,6 +78,7 @@ typedef void (*ResourceLoadErrorNotify)(void *p_ud, const String &p_text); typedef void (*DependencyErrorNotify)(void *p_ud, const String &p_loading, const String &p_which, const String &p_type); typedef Error (*ResourceLoaderImport)(const String &p_path); +typedef void (*ResourceLoadedCallback)(RES p_resource, const String &p_path); class ResourceLoader { @@ -106,6 +107,8 @@ class ResourceLoader { //internal load function static RES _load(const String &p_path, const String &p_original_path, const String &p_type_hint, bool p_no_cache, Error *r_error); + static ResourceLoadedCallback _loaded_callback; + public: static Ref<ResourceInteractiveLoader> load_interactive(const String &p_path, const String &p_type_hint = "", bool p_no_cache = false, Error *r_error = NULL); static RES load(const String &p_path, const String &p_type_hint = "", bool p_no_cache = false, Error *r_error = NULL); @@ -150,6 +153,7 @@ public: static void load_translation_remaps(); static void clear_translation_remaps(); + static void set_load_callback(ResourceLoadedCallback p_callback); static ResourceLoaderImport import; }; diff --git a/core/io/resource_saver.cpp b/core/io/resource_saver.cpp index 5c8188f735..097e81e308 100644 --- a/core/io/resource_saver.cpp +++ b/core/io/resource_saver.cpp @@ -90,7 +90,7 @@ Error ResourceSaver::save(const String &p_path, const RES &p_resource, uint32_t rwcopy->set_path(old_path); if (save_callback && p_path.begins_with("res://")) - save_callback(p_path); + save_callback(p_resource, p_path); return OK; } else { diff --git a/core/io/resource_saver.h b/core/io/resource_saver.h index 7ed580f2d6..6134d9db57 100644 --- a/core/io/resource_saver.h +++ b/core/io/resource_saver.h @@ -46,7 +46,7 @@ public: virtual ~ResourceFormatSaver() {} }; -typedef void (*ResourceSavedCallback)(const String &p_path); +typedef void (*ResourceSavedCallback)(Ref<Resource> p_resource, const String &p_path); class ResourceSaver { diff --git a/core/math/expression.cpp b/core/math/expression.cpp index a16267cf0a..0cfb54234c 100644 --- a/core/math/expression.cpp +++ b/core/math/expression.cpp @@ -2120,6 +2120,10 @@ Error Expression::parse(const String &p_expression, const Vector<String> &p_inpu } Variant Expression::execute(Array p_inputs, Object *p_base, bool p_show_error) { + if (error_set) { + ERR_EXPLAIN("There was previously a parse error: " + error_str); + ERR_FAIL_V(Variant()); + } execution_error = false; Variant output; diff --git a/core/object.cpp b/core/object.cpp index 946040ba34..374e10726a 100644 --- a/core/object.cpp +++ b/core/object.cpp @@ -440,16 +440,6 @@ void Object::set(const StringName &p_name, const Variant &p_value, bool *r_valid if (r_valid) *r_valid = true; return; -#ifdef TOOLS_ENABLED - } else if (p_name == CoreStringNames::get_singleton()->_sections_unfolded) { - Array arr = p_value; - for (int i = 0; i < arr.size(); i++) { - editor_section_folding.insert(arr[i]); - } - if (r_valid) - *r_valid = true; - return; -#endif } //something inside the object... :| @@ -520,16 +510,7 @@ Variant Object::get(const StringName &p_name, bool *r_valid) const { if (r_valid) *r_valid = true; return ret; -#ifdef TOOLS_ENABLED - } else if (p_name == CoreStringNames::get_singleton()->_sections_unfolded) { - Array array; - for (Set<String>::Element *E = editor_section_folding.front(); E; E = E->next()) { - array.push_back(E->get()); - } - if (r_valid) - *r_valid = true; - return array; -#endif + } else { //something inside the object... :| bool success = _getv(p_name, ret); @@ -657,11 +638,6 @@ void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) cons #endif p_list->push_back(PropertyInfo(Variant::OBJECT, "script", PROPERTY_HINT_RESOURCE_TYPE, "Script", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_STORE_IF_NONZERO)); } -#ifdef TOOLS_ENABLED - if (editor_section_folding.size()) { - p_list->push_back(PropertyInfo(Variant::ARRAY, CoreStringNames::get_singleton()->_sections_unfolded, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); - } -#endif if (!metadata.empty()) p_list->push_back(PropertyInfo(Variant::DICTIONARY, "__meta__", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_STORE_IF_NONZERO)); if (script_instance && !p_reversed) { diff --git a/core/object.h b/core/object.h index b23160c1df..0fee7c2157 100644 --- a/core/object.h +++ b/core/object.h @@ -723,6 +723,9 @@ public: #ifdef TOOLS_ENABLED void editor_set_section_unfold(const String &p_section, bool p_unfolded); bool editor_is_section_unfolded(const String &p_section); + const Set<String> &editor_get_section_folding() const { return editor_section_folding; } + void editor_clear_section_folding() { editor_section_folding.clear(); } + #endif //used by script languages to store binding data diff --git a/core/set.h b/core/set.h index 744019d5b4..59aa54128e 100644 --- a/core/set.h +++ b/core/set.h @@ -595,6 +595,7 @@ public: return e; } + inline bool empty() const { return _data.size_cache == 0; } inline int size() const { return _data.size_cache; } int calculate_depth() const { diff --git a/core/ustring.cpp b/core/ustring.cpp index 1195cd0719..2191bb5e23 100644 --- a/core/ustring.cpp +++ b/core/ustring.cpp @@ -2774,16 +2774,13 @@ String String::format(const Variant &values, String placeholder) const { if (value_arr.size() == 2) { Variant v_key = value_arr[0]; - String key; - - key = v_key.get_construct_string(); + String key = v_key; if (key.left(1) == "\"" && key.right(key.length() - 1) == "\"") { key = key.substr(1, key.length() - 2); } Variant v_val = value_arr[1]; - String val; - val = v_val.get_construct_string(); + String val = v_val; if (val.left(1) == "\"" && val.right(val.length() - 1) == "\"") { val = val.substr(1, val.length() - 2); @@ -2795,8 +2792,7 @@ String String::format(const Variant &values, String placeholder) const { } } else { //Array structure ["RobotGuy","Logis","rookie"] Variant v_val = values_arr[i]; - String val; - val = v_val.get_construct_string(); + String val = v_val; if (val.left(1) == "\"" && val.right(val.length() - 1) == "\"") { val = val.substr(1, val.length() - 2); @@ -2815,8 +2811,8 @@ String String::format(const Variant &values, String placeholder) const { d.get_key_list(&keys); for (List<Variant>::Element *E = keys.front(); E; E = E->next()) { - String key = E->get().get_construct_string(); - String val = d[E->get()].get_construct_string(); + String key = E->get(); + String val = d[E->get()]; if (key.left(1) == "\"" && key.right(key.length() - 1) == "\"") { key = key.substr(1, key.length() - 2); diff --git a/doc/classes/AnimationPlayer.xml b/doc/classes/AnimationPlayer.xml index 6dc91a234a..a5be8ffc53 100644 --- a/doc/classes/AnimationPlayer.xml +++ b/doc/classes/AnimationPlayer.xml @@ -238,7 +238,7 @@ The default time in which to blend animations. Ranges from 0 to 4096 with 0.01 precision. Default value: [code]0[/code]. </member> <member name="playback_process_mode" type="int" setter="set_animation_process_mode" getter="get_animation_process_mode" enum="AnimationPlayer.AnimationProcessMode"> - The process notification in which to update animations. Default value: [enum ANIMATION_PROCESS_IDLE]. + The process notification in which to update animations. Default value: [code]ANIMATION_PROCESS_IDLE[/code]. </member> <member name="playback_speed" type="float" setter="set_speed_scale" getter="get_speed_scale"> The speed scaling ratio. For instance, if this value is 1 then the animation plays at normal speed. If it's 0.5 then it plays at half speed. If it's 2 then it plays at double speed. Default value: [code]1[/code]. diff --git a/doc/classes/AnimationTreePlayer.xml b/doc/classes/AnimationTreePlayer.xml index 8c32d5f6a3..a081c64f6d 100644 --- a/doc/classes/AnimationTreePlayer.xml +++ b/doc/classes/AnimationTreePlayer.xml @@ -618,7 +618,7 @@ Once set, Animation nodes can be added to the AnimationTreePlayer. </member> <member name="playback_process_mode" type="int" setter="set_animation_process_mode" getter="get_animation_process_mode" enum="AnimationTreePlayer.AnimationProcessMode"> - The thread in which to update animations. Default value: [enum ANIMATION_PROCESS_IDLE]. + The thread in which to update animations. Default value: [code]ANIMATION_PROCESS_IDLE[/code]. </member> </members> <constants> diff --git a/doc/classes/PackedScene.xml b/doc/classes/PackedScene.xml index 19f85fae4c..aa4459752e 100644 --- a/doc/classes/PackedScene.xml +++ b/doc/classes/PackedScene.xml @@ -52,7 +52,7 @@ <argument index="0" name="edit_state" type="int" enum="PackedScene.GenEditState" default="0"> </argument> <description> - Instantiates the scene's node hierarchy. Triggers child scene instantiation(s). Triggers the [enum Node.NOTIFICATION_INSTANCED] notification on the root node. + Instantiates the scene's node hierarchy. Triggers child scene instantiation(s). Triggers [Node]'s [code]NOTIFICATION_INSTANCED[/code] notification on the root node. </description> </method> <method name="pack"> diff --git a/doc/classes/PhysicsBody.xml b/doc/classes/PhysicsBody.xml index af00027ed3..fb145f9de9 100644 --- a/doc/classes/PhysicsBody.xml +++ b/doc/classes/PhysicsBody.xml @@ -21,6 +21,13 @@ Adds a body to the list of bodies that this body can't collide with. </description> </method> + <method name="get_collision_exceptions"> + <return type="Array"> + </return> + <description> + Returns an array of nodes that were added as collision exceptions for this body. + </description> + </method> <method name="get_collision_layer_bit" qualifiers="const"> <return type="bool"> </return> diff --git a/doc/classes/PhysicsBody2D.xml b/doc/classes/PhysicsBody2D.xml index 4278979049..440caf61e5 100644 --- a/doc/classes/PhysicsBody2D.xml +++ b/doc/classes/PhysicsBody2D.xml @@ -21,6 +21,13 @@ Adds a body to the list of bodies that this body can't collide with. </description> </method> + <method name="get_collision_exceptions"> + <return type="Array"> + </return> + <description> + Returns an array of nodes that were added as collision exceptions for this body. + </description> + </method> <method name="get_collision_layer_bit" qualifiers="const"> <return type="bool"> </return> diff --git a/doc/classes/RichTextLabel.xml b/doc/classes/RichTextLabel.xml index 357d2e7a15..3371e4d66f 100644 --- a/doc/classes/RichTextLabel.xml +++ b/doc/classes/RichTextLabel.xml @@ -111,7 +111,7 @@ <argument index="0" name="align" type="int" enum="RichTextLabel.Align"> </argument> <description> - Adds a [code][right][/code] tag to the tag stack. + Adds an alignment tag based on the given [code]align[/code] value. See [enum Align] for possible values. </description> </method> <method name="push_cell"> @@ -170,6 +170,7 @@ <return type="void"> </return> <description> + Adds a [code][s][/code] tag to the tag stack. </description> </method> <method name="push_table"> diff --git a/doc/classes/SoftBody.xml b/doc/classes/SoftBody.xml index 196d29fc60..6c3929d65b 100644 --- a/doc/classes/SoftBody.xml +++ b/doc/classes/SoftBody.xml @@ -20,6 +20,13 @@ Adds a body to the list of bodies that this body can't collide with. </description> </method> + <method name="get_collision_exceptions"> + <return type="Array"> + </return> + <description> + Returns an array of nodes that were added as collision exceptions for this body. + </description> + </method> <method name="get_collision_layer_bit" qualifiers="const"> <return type="bool"> </return> diff --git a/doc/classes/Tween.xml b/doc/classes/Tween.xml index 1dc03ed314..e792835605 100644 --- a/doc/classes/Tween.xml +++ b/doc/classes/Tween.xml @@ -14,7 +14,7 @@ tween.start() [/codeblock] Many methods require a property name, such as "position" above. You can find the correct property name by hovering over the property in the Inspector. - Many of the methods accept [code]trans_type[/code] and [code]ease_type[/code]. The first accepts an [enum TransitionType] constant, and refers to the way the timing of the animation is handled (see [code]http://easings.net/[/code] for some examples). The second accepts an [enum EaseType] constant, and controls the where [code]trans_type[/code] is applied to the interpolation (in the beginning, the end, or both). If you don't know which transition and easing to pick, you can try different [enum TransitionType] constants with [enum EASE_IN_OUT], and use the one that looks best. + Many of the methods accept [code]trans_type[/code] and [code]ease_type[/code]. The first accepts an [enum TransitionType] constant, and refers to the way the timing of the animation is handled (see [code]http://easings.net/[/code] for some examples). The second accepts an [enum EaseType] constant, and controls the where [code]trans_type[/code] is applied to the interpolation (in the beginning, the end, or both). If you don't know which transition and easing to pick, you can try different [enum TransitionType] constants with [code]EASE_IN_OUT[/code], and use the one that looks best. </description> <tutorials> </tutorials> diff --git a/doc/tools/doc_merge.py b/doc/tools/doc_merge.py index 57ac4bdcdd..496d5dcb74 100644 --- a/doc/tools/doc_merge.py +++ b/doc/tools/doc_merge.py @@ -82,7 +82,7 @@ def find_signal_descr(old_class, name): def find_constant_descr(old_class, name): - if (old_class == None): + if (old_class is None): return None constants = old_class.find("constants") if(constants != None and len(list(constants)) > 0): diff --git a/doc/tools/makerst.py b/doc/tools/makerst.py index b3d6d32c26..7b7cc52547 100755 --- a/doc/tools/makerst.py +++ b/doc/tools/makerst.py @@ -375,7 +375,7 @@ def make_method( event=False, pp=None ): - if (declare or pp == None): + if (declare or pp is None): t = '- ' else: t = "" @@ -405,7 +405,7 @@ def make_method( t += 'void' t += ' ' - if declare or pp == None: + if declare or pp is None: s = '**' + method_data.attrib['name'] + '** ' else: @@ -577,7 +577,7 @@ def make_rst_class(node): make_method(f, name, m, True, True) f.write('\n') d = m.find('description') - if d == None or d.text.strip() == '': + if d is None or d.text.strip() == '': continue f.write(rstize_text(d.text.strip(), name)) f.write("\n\n") @@ -676,7 +676,7 @@ def make_rst_class(node): make_method(f, name, m, True) f.write('\n') d = m.find('description') - if d == None or d.text.strip() == '': + if d is None or d.text.strip() == '': continue f.write(rstize_text(d.text.strip(), name)) f.write("\n\n") diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp index d5865064cf..c4c5093540 100644 --- a/drivers/gles2/rasterizer_storage_gles2.cpp +++ b/drivers/gles2/rasterizer_storage_gles2.cpp @@ -613,8 +613,72 @@ Ref<Image> RasterizerStorageGLES2::texture_get_data(RID p_texture, int p_layer) return Ref<Image>(img); #else - ERR_EXPLAIN("Sorry, It's not possible to obtain images back in OpenGL ES"); - ERR_FAIL_V(Ref<Image>()); + Image::Format real_format; + GLenum gl_format; + GLenum gl_internal_format; + GLenum gl_type; + bool compressed; + _get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, gl_format, gl_internal_format, gl_type, compressed); + + PoolVector<uint8_t> data; + + int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, Image::FORMAT_RGBA8, false); + + data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers + PoolVector<uint8_t>::Write wb = data.write(); + + GLuint temp_framebuffer; + glGenFramebuffers(1, &temp_framebuffer); + + GLuint temp_color_texture; + glGenTextures(1, &temp_color_texture); + + glBindFramebuffer(GL_FRAMEBUFFER, temp_framebuffer); + + glBindTexture(GL_TEXTURE_2D, temp_color_texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->alloc_width, texture->alloc_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, temp_color_texture, 0); + + glDepthMask(GL_FALSE); + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + glDisable(GL_BLEND); + glDepthFunc(GL_LEQUAL); + glColorMask(1, 1, 1, 1); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, texture->tex_id); + + glViewport(0, 0, texture->alloc_width, texture->alloc_height); + + shaders.copy.bind(); + + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + bind_quad_array(); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glReadPixels(0, 0, texture->alloc_width, texture->alloc_height, GL_RGBA, GL_UNSIGNED_BYTE, &wb[0]); + + glDeleteTextures(1, &temp_color_texture); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glDeleteFramebuffers(1, &temp_framebuffer); + + wb = PoolVector<uint8_t>::Write(); + + data.resize(data_size); + + Image *img = memnew(Image(texture->alloc_width, texture->alloc_height, false, Image::FORMAT_RGBA8, data)); + if (!texture->compressed) { + img->convert(real_format); + } + + return Ref<Image>(img); + #endif } diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl index b990384949..79d4eb2243 100644 --- a/drivers/gles2/shaders/canvas.glsl +++ b/drivers/gles2/shaders/canvas.glsl @@ -148,7 +148,10 @@ void main() { vec4 color = color_interp; +#if !defined(COLOR_USED) + //default behavior, texture by color color *= texture2D(color_texture, uv_interp); +#endif #ifdef SCREEN_UV_USED vec2 screen_uv = gl_FragCoord.xy * screen_pixel_size; diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 0d4c83e0db..792e9eb238 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -1428,7 +1428,16 @@ void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e, const Transfo if (particles->draw_order == VS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->particle_valid_histories[1]) { glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffer_histories[1]); //modify the buffer, this was used 2 frames ago so it should be good enough for flushing - RasterizerGLES3Particle *particle_array = (RasterizerGLES3Particle *)glMapBufferRange(GL_ARRAY_BUFFER, 0, particles->amount * 24 * sizeof(float), GL_MAP_READ_BIT | GL_MAP_WRITE_BIT); + RasterizerGLES3Particle *particle_array; +#ifndef __EMSCRIPTEN__ + particle_array = static_cast<RasterizerGLES3Particle *>(glMapBufferRange(GL_ARRAY_BUFFER, 0, particles->amount * 24 * sizeof(float), GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)); +#else + PoolVector<RasterizerGLES3Particle> particle_vector; + particle_vector.resize(particles->amount); + PoolVector<RasterizerGLES3Particle>::Write w = particle_vector.write(); + particle_array = w.ptr(); + glGetBufferSubData(GL_ARRAY_BUFFER, 0, particles->amount * sizeof(RasterizerGLES3Particle), particle_array); +#endif SortArray<RasterizerGLES3Particle, RasterizerGLES3ParticleSort> sorter; @@ -1440,7 +1449,17 @@ void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e, const Transfo sorter.sort(particle_array, particles->amount); +#ifndef __EMSCRIPTEN__ glUnmapBuffer(GL_ARRAY_BUFFER); +#else + w = PoolVector<RasterizerGLES3Particle>::Write(); + particle_array = NULL; + { + PoolVector<RasterizerGLES3Particle>::Read r = particle_vector.read(); + glBufferSubData(GL_ARRAY_BUFFER, 0, particles->amount * sizeof(RasterizerGLES3Particle), r.ptr()); + } + particle_vector = PoolVector<RasterizerGLES3Particle>(); +#endif #ifdef DEBUG_ENABLED if (state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME && s->instancing_array_wireframe_id) { glBindVertexArray(s->instancing_array_wireframe_id); // use the wireframe instancing array ID diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 406ef6af78..c06ef805a6 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -101,6 +101,28 @@ #define _EXT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E #define _EXT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F +#ifdef __EMSCRIPTEN__ +#include <emscripten/emscripten.h> + +void glGetBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data) { + + /* clang-format off */ + EM_ASM({ + GLctx.getBufferSubData($0, $1, HEAPU8, $2, $3); + }, target, offset, data, size); + /* clang-format on */ +} + +void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data) { + + /* clang-format off */ + EM_ASM({ + GLctx.bufferSubData($0, $1, HEAPU8, $2, $3); + }, target, offset, data, size); + /* clang-format on */ +} +#endif + void glTexStorage2DCustom(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type) { #ifdef GLES_OVER_GL @@ -1094,8 +1116,78 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer) return Ref<Image>(img); #else - ERR_EXPLAIN("Sorry, It's not possible to obtain images back in OpenGL ES"); - ERR_FAIL_V(Ref<Image>()); + Image::Format real_format; + GLenum gl_format; + GLenum gl_internal_format; + GLenum gl_type; + bool compressed; + bool srgb; + _get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, gl_format, gl_internal_format, gl_type, compressed, srgb); + + PoolVector<uint8_t> data; + + int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, Image::FORMAT_RGBA8, false); + + data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers + PoolVector<uint8_t>::Write wb = data.write(); + + GLuint temp_framebuffer; + glGenFramebuffers(1, &temp_framebuffer); + + GLuint temp_color_texture; + glGenTextures(1, &temp_color_texture); + + glBindFramebuffer(GL_FRAMEBUFFER, temp_framebuffer); + + glBindTexture(GL_TEXTURE_2D, temp_color_texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->alloc_width, texture->alloc_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + + print_line(itos(texture->alloc_width) + " xx " + itos(texture->alloc_height) + " -> " + itos(real_format)); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, temp_color_texture, 0); + + glDepthMask(GL_FALSE); + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + glDisable(GL_BLEND); + glDepthFunc(GL_LEQUAL); + glColorMask(1, 1, 1, 1); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, texture->tex_id); + + glViewport(0, 0, texture->alloc_width, texture->alloc_height); + + shaders.copy.bind(); + + shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, !srgb); + + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + glBindVertexArray(resources.quadie_array); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + glBindVertexArray(0); + + glReadPixels(0, 0, texture->alloc_width, texture->alloc_height, GL_RGBA, GL_UNSIGNED_BYTE, &wb[0]); + + shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, false); + + glDeleteTextures(1, &temp_color_texture); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glDeleteFramebuffers(1, &temp_framebuffer); + + wb = PoolVector<uint8_t>::Write(); + + data.resize(data_size); + + Image *img = memnew(Image(texture->alloc_width, texture->alloc_height, false, Image::FORMAT_RGBA8, data)); + if (!texture->compressed) { + img->convert(real_format); + } + + return Ref<Image>(img); #endif } @@ -3494,21 +3586,26 @@ PoolVector<uint8_t> RasterizerStorageGLES3::mesh_surface_get_array(RID p_mesh, i Surface *surface = mesh->surfaces[p_surface]; - glBindBuffer(GL_ARRAY_BUFFER, surface->vertex_id); - void *data = glMapBufferRange(GL_ARRAY_BUFFER, 0, surface->array_byte_size, GL_MAP_READ_BIT); - - ERR_FAIL_COND_V(!data, PoolVector<uint8_t>()); - PoolVector<uint8_t> ret; ret.resize(surface->array_byte_size); + glBindBuffer(GL_ARRAY_BUFFER, surface->vertex_id); +#if defined(GLES_OVER_GL) || defined(__EMSCRIPTEN__) + { + PoolVector<uint8_t>::Write w = ret.write(); + glGetBufferSubData(GL_ARRAY_BUFFER, 0, surface->array_byte_size, w.ptr()); + } +#else + void *data = glMapBufferRange(GL_ARRAY_BUFFER, 0, surface->array_byte_size, GL_MAP_READ_BIT); + ERR_FAIL_NULL_V(data, PoolVector<uint8_t>()); { - PoolVector<uint8_t>::Write w = ret.write(); copymem(w.ptr(), data, surface->array_byte_size); } glUnmapBuffer(GL_ARRAY_BUFFER); +#endif + glBindBuffer(GL_ARRAY_BUFFER, 0); return ret; } @@ -3521,22 +3618,26 @@ PoolVector<uint8_t> RasterizerStorageGLES3::mesh_surface_get_index_array(RID p_m ERR_FAIL_COND_V(surface->index_array_len == 0, PoolVector<uint8_t>()); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, surface->index_id); - void *data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, surface->index_array_byte_size, GL_MAP_READ_BIT); - - ERR_FAIL_COND_V(!data, PoolVector<uint8_t>()); - PoolVector<uint8_t> ret; ret.resize(surface->index_array_byte_size); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, surface->index_id); +#if defined(GLES_OVER_GL) || defined(__EMSCRIPTEN__) + { + PoolVector<uint8_t>::Write w = ret.write(); + glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, surface->index_array_byte_size, w.ptr()); + } +#else + void *data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, surface->index_array_byte_size, GL_MAP_READ_BIT); + ERR_FAIL_NULL_V(data, PoolVector<uint8_t>()); { - PoolVector<uint8_t>::Write w = ret.write(); copymem(w.ptr(), data, surface->index_array_byte_size); } - glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); +#endif + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); return ret; } @@ -3577,23 +3678,26 @@ Vector<PoolVector<uint8_t> > RasterizerStorageGLES3::mesh_surface_get_blend_shap for (int i = 0; i < mesh->surfaces[p_surface]->blend_shapes.size(); i++) { - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->surfaces[p_surface]->blend_shapes[i].vertex_id); - void *data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, mesh->surfaces[p_surface]->array_byte_size, GL_MAP_READ_BIT); - - ERR_FAIL_COND_V(!data, Vector<PoolVector<uint8_t> >()); - PoolVector<uint8_t> ret; ret.resize(mesh->surfaces[p_surface]->array_byte_size); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->surfaces[p_surface]->blend_shapes[i].vertex_id); +#if defined(GLES_OVER_GL) || defined(__EMSCRIPTEN__) + { + PoolVector<uint8_t>::Write w = ret.write(); + glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, mesh->surfaces[p_surface]->array_byte_size, w.ptr()); + } +#else + void *data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, mesh->surfaces[p_surface]->array_byte_size, GL_MAP_READ_BIT); + ERR_FAIL_COND_V(!data, Vector<PoolVector<uint8_t> >()); { - PoolVector<uint8_t>::Write w = ret.write(); copymem(w.ptr(), data, mesh->surfaces[p_surface]->array_byte_size); } + glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); +#endif bsarr.push_back(ret); - - glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); } return bsarr; @@ -6001,9 +6105,21 @@ AABB RasterizerStorageGLES3::particles_get_current_aabb(RID p_particles) { const Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND_V(!particles, AABB()); + const float *data; glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[0]); - float *data = (float *)glMapBufferRange(GL_ARRAY_BUFFER, 0, particles->amount * 16 * 6, GL_MAP_READ_BIT); +#if defined(GLES_OVER_GL) || defined(__EMSCRIPTEN__) + PoolVector<uint8_t> vector; + vector.resize(particles->amount * 16 * 6); + { + PoolVector<uint8_t>::Write w = vector.write(); + glGetBufferSubData(GL_ARRAY_BUFFER, 0, particles->amount * 16 * 6, w.ptr()); + } + PoolVector<uint8_t>::Read r = vector.read(); + data = reinterpret_cast<const float *>(r.ptr()); +#else + data = (float *)glMapBufferRange(GL_ARRAY_BUFFER, 0, particles->amount * 16 * 6, GL_MAP_READ_BIT); +#endif AABB aabb; Transform inv = particles->emission_transform.affine_inverse(); @@ -6020,7 +6136,13 @@ AABB RasterizerStorageGLES3::particles_get_current_aabb(RID p_particles) { aabb.expand_to(pos); } +#if defined(GLES_OVER_GL) || defined(__EMSCRIPTEN__) + r = PoolVector<uint8_t>::Read(); + vector = PoolVector<uint8_t>(); +#else glUnmapBuffer(GL_ARRAY_BUFFER); +#endif + glBindBuffer(GL_ARRAY_BUFFER, 0); float longest_axis = 0; diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index 9a4798ac2a..8c26e09037 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -43,6 +43,12 @@ #include "shaders/cubemap_filter.glsl.gen.h" #include "shaders/particles.glsl.gen.h" +// WebGL 2.0 has no MapBufferRange/UnmapBuffer, but offers a non-ES style BufferSubData API instead. +#ifdef __EMSCRIPTEN__ +void glGetBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data); +void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data); +#endif + class RasterizerCanvasGLES3; class RasterizerSceneGLES3; diff --git a/drivers/unix/net_socket_posix.cpp b/drivers/unix/net_socket_posix.cpp index 2cc2032cbb..f981be66ce 100644 --- a/drivers/unix/net_socket_posix.cpp +++ b/drivers/unix/net_socket_posix.cpp @@ -55,7 +55,7 @@ #include <netinet/tcp.h> -#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) +#if defined(__APPLE__) #define MSG_NOSIGNAL SO_NOSIGPIPE #endif diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index 7ff27be501..279274734f 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -288,6 +288,11 @@ uint64_t OS_Unix::get_ticks_usec() const { Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr) { +#ifdef __EMSCRIPTEN__ + // Don't compile this code at all to avoid undefined references. + // Actual virtual call goes to OS_JavaScript. + ERR_FAIL_V(ERR_BUG); +#else if (p_blocking && r_pipe) { String argss; @@ -354,6 +359,7 @@ Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, bo } return OK; +#endif } Error OS_Unix::kill(const ProcessID &p_pid) { diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp index 1a6188862f..218063566a 100644 --- a/editor/editor_export.cpp +++ b/editor/editor_export.cpp @@ -144,6 +144,17 @@ String EditorExportPreset::get_include_filter() const { return include_filter; } +void EditorExportPreset::set_export_path(const String &p_path) { + + export_path = p_path; + EditorExport::singleton->save_presets(); +} + +String EditorExportPreset::get_export_path() const { + + return export_path; +} + void EditorExportPreset::set_exclude_filter(const String &p_exclude) { exclude_filter = p_exclude; @@ -213,6 +224,7 @@ String EditorExportPreset::get_custom_features() const { EditorExportPreset::EditorExportPreset() { + export_path = ""; export_filter = EXPORT_ALL_RESOURCES; runnable = false; } @@ -1034,6 +1046,7 @@ void EditorExport::_save() { } config->set_value(section, "include_filter", preset->get_include_filter()); config->set_value(section, "exclude_filter", preset->get_exclude_filter()); + config->set_value(section, "export_path", preset->get_export_path()); config->set_value(section, "patch_list", preset->get_patches()); String option_section = "preset." + itos(i) + ".options"; @@ -1189,6 +1202,7 @@ void EditorExport::load_config() { preset->set_include_filter(config->get_value(section, "include_filter")); preset->set_exclude_filter(config->get_value(section, "exclude_filter")); + preset->set_export_path(config->get_value(section, "export_path", "")); Vector<String> patch_list = config->get_value(section, "patch_list"); diff --git a/editor/editor_export.h b/editor/editor_export.h index b4ee5b89e7..d1165fd042 100644 --- a/editor/editor_export.h +++ b/editor/editor_export.h @@ -57,6 +57,7 @@ private: ExportFilter export_filter; String include_filter; String exclude_filter; + String export_path; String exporter; Set<String> selected_files; @@ -114,6 +115,9 @@ public: void set_custom_features(const String &p_custom_features); String get_custom_features() const; + void set_export_path(const String &p_path); + String get_export_path() const; + const List<PropertyInfo> &get_properties() const { return properties; } EditorExportPreset(); diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index d73bf86f64..a99c9656ba 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -1305,11 +1305,6 @@ void EditorFileSystem::_save_late_updated_files() { } } -void EditorFileSystem::_resource_saved(const String &p_path) { - - EditorFileSystem::get_singleton()->update_file(p_path); -} - Vector<String> EditorFileSystem::_get_dependencies(const String &p_path) { List<String> deps; @@ -1772,7 +1767,6 @@ EditorFileSystem::EditorFileSystem() { abort_scan = false; scanning_changes = false; scanning_changes_done = false; - ResourceSaver::set_save_callback(_resource_saved); DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES); if (da->change_dir("res://.import") != OK) { diff --git a/editor/editor_file_system.h b/editor/editor_file_system.h index 47077425a1..f6eef2a152 100644 --- a/editor/editor_file_system.h +++ b/editor/editor_file_system.h @@ -204,8 +204,6 @@ class EditorFileSystem : public Node { bool _update_scan_actions(); - static void _resource_saved(const String &p_path); - void _update_extensions(); void _reimport_file(const String &p_file); diff --git a/editor/editor_folding.cpp b/editor/editor_folding.cpp new file mode 100644 index 0000000000..eec4438f96 --- /dev/null +++ b/editor/editor_folding.cpp @@ -0,0 +1,175 @@ +#include "editor_folding.h" + +#include "core/os/file_access.h" +#include "editor_settings.h" + +PoolVector<String> EditorFolding::_get_unfolds(const Object *p_object) { + + PoolVector<String> sections; + sections.resize(p_object->editor_get_section_folding().size()); + if (sections.size()) { + PoolVector<String>::Write w = sections.write(); + int idx = 0; + for (const Set<String>::Element *E = p_object->editor_get_section_folding().front(); E; E = E->next()) { + w[idx++] = E->get(); + } + } + + return sections; +} + +void EditorFolding::save_resource_folding(const RES &p_resource, const String &p_path) { + Ref<ConfigFile> config; + config.instance(); + PoolVector<String> unfolds = _get_unfolds(p_resource.ptr()); + config->set_value("folding", "sections_unfolded", unfolds); + + String path = EditorSettings::get_singleton()->get_project_settings_dir(); + String file = p_path.get_file() + "-folding-" + p_path.md5_text() + ".cfg"; + file = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(file); + config->save(file); +} + +void EditorFolding::_set_unfolds(Object *p_object, const PoolVector<String> &p_unfolds) { + + int uc = p_unfolds.size(); + PoolVector<String>::Read r = p_unfolds.read(); + p_object->editor_clear_section_folding(); + for (int i = 0; i < uc; i++) { + p_object->editor_set_section_unfold(r[i], true); + } +} + +void EditorFolding::load_resource_folding(RES p_resource, const String &p_path) { + + Ref<ConfigFile> config; + config.instance(); + + String path = EditorSettings::get_singleton()->get_project_settings_dir(); + String file = p_path.get_file() + "-folding-" + p_path.md5_text() + ".cfg"; + file = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(file); + + if (config->load(file) != OK) { + return; + } + + PoolVector<String> unfolds; + + if (config->has_section_key("folding", "sections_unfolded")) { + unfolds = config->get_value("folding", "sections_unfolded"); + } + _set_unfolds(p_resource.ptr(), unfolds); +} + +void EditorFolding::_fill_folds(const Node *p_root, const Node *p_node, Array &p_folds, Array &resource_folds, Set<RES> &resources) { + if (p_root != p_node) { + if (!p_node->get_owner()) { + return; //not owned, bye + } + if (p_node->get_owner() != p_root && !p_root->is_editable_instance(p_node)) { + return; + } + } + + PoolVector<String> unfolds = _get_unfolds(p_node); + + if (unfolds.size()) { + p_folds.push_back(p_root->get_path_to(p_node)); + p_folds.push_back(unfolds); + } + + List<PropertyInfo> plist; + p_node->get_property_list(&plist); + for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) { + if (E->get().type == Variant::OBJECT) { + RES res = p_node->get(E->get().name); + if (res.is_valid() && !resources.has(res) && res->get_path() != String() && !res->get_path().is_resource_file()) { + + PoolVector<String> res_unfolds = _get_unfolds(res.ptr()); + resource_folds.push_back(res->get_path()); + resource_folds.push_back(res_unfolds); + resources.insert(res); + } + } + } + + for (int i = 0; i < p_node->get_child_count(); i++) { + _fill_folds(p_root, p_node->get_child(i), p_folds, resource_folds, resources); + } +} +void EditorFolding::save_scene_folding(const Node *p_scene, const String &p_path) { + + Ref<ConfigFile> config; + config.instance(); + + Array unfolds, res_unfolds; + Set<RES> resources; + _fill_folds(p_scene, p_scene, unfolds, res_unfolds, resources); + + config->set_value("folding", "node_unfolds", unfolds); + config->set_value("folding", "resource_unfolds", res_unfolds); + + String path = EditorSettings::get_singleton()->get_project_settings_dir(); + String file = p_path.get_file() + "-folding-" + p_path.md5_text() + ".cfg"; + file = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(file); + config->save(file); +} +void EditorFolding::load_scene_folding(Node *p_scene, const String &p_path) { + + Ref<ConfigFile> config; + config.instance(); + + String path = EditorSettings::get_singleton()->get_project_settings_dir(); + String file = p_path.get_file() + "-folding-" + p_path.md5_text() + ".cfg"; + file = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(file); + + if (config->load(file) != OK) { + return; + } + + Array unfolds; + if (config->has_section_key("folding", "node_unfolds")) { + unfolds = config->get_value("folding", "node_unfolds"); + } + Array res_unfolds; + if (config->has_section_key("folding", "resource_unfolds")) { + res_unfolds = config->get_value("folding", "resource_unfolds"); + } + + ERR_FAIL_COND(unfolds.size() & 1); + ERR_FAIL_COND(res_unfolds.size() & 1); + + for (int i = 0; i < unfolds.size(); i += 2) { + NodePath path = unfolds[i]; + PoolVector<String> un = unfolds[i + 1]; + Node *node = p_scene->get_node(path); + if (!node) { + continue; + } + _set_unfolds(node, un); + } + + for (int i = 0; i < res_unfolds.size(); i += 2) { + String path = res_unfolds[i]; + RES res; + if (ResourceCache::has(path)) { + res = RES(ResourceCache::get(path)); + } + if (res.is_null()) { + continue; + } + + PoolVector<String> unfolds = res_unfolds[i + 1]; + _set_unfolds(res.ptr(), unfolds); + } +} + +bool EditorFolding::has_folding_data(const String &p_path) { + String path = EditorSettings::get_singleton()->get_project_settings_dir(); + String file = p_path.get_file() + "-folding-" + p_path.md5_text() + ".cfg"; + file = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(file); + return FileAccess::exists(file); +} + +EditorFolding::EditorFolding() { +} diff --git a/editor/editor_folding.h b/editor/editor_folding.h new file mode 100644 index 0000000000..cfd4b5466d --- /dev/null +++ b/editor/editor_folding.h @@ -0,0 +1,25 @@ +#ifndef EDITOR_FOLDING_H +#define EDITOR_FOLDING_H + +#include "scene/main/node.h" + +class EditorFolding { + + PoolVector<String> _get_unfolds(const Object *p_object); + void _set_unfolds(Object *p_object, const PoolVector<String> &p_unfolds); + + void _fill_folds(const Node *p_root, const Node *p_node, Array &p_folds, Array &resource_folds, Set<RES> &resources); + +public: + void save_resource_folding(const RES &p_resource, const String &p_path); + void load_resource_folding(RES p_resource, const String &p_path); + + void save_scene_folding(const Node *p_scene, const String &p_path); + void load_scene_folding(Node *p_scene, const String &p_path); + + bool has_folding_data(const String &p_path); + + EditorFolding(); +}; + +#endif // EDITOR_FOLDING_H diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 3ecaa2b136..1230588016 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -36,6 +36,50 @@ #include "multi_node_edit.h" #include "scene/resources/packed_scene.h" +EditorDefaultClassValueCache *EditorDefaultClassValueCache::singleton = NULL; + +EditorDefaultClassValueCache *EditorDefaultClassValueCache::get_singleton() { + return singleton; +} + +Variant EditorDefaultClassValueCache::get_default_value(const StringName &p_class, const StringName &p_property) { + + if (!default_values.has(p_class)) { + + default_values[p_class] = Map<StringName, Variant>(); + + if (ClassDB::can_instance(p_class)) { + + Object *c = ClassDB::instance(p_class); + List<PropertyInfo> plist; + c->get_property_list(&plist); + for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) { + if (E->get().usage & PROPERTY_USAGE_EDITOR) { + + Variant v = c->get(E->get().name); + default_values[p_class][E->get().name] = v; + } + } + memdelete(c); + } + } + + if (!default_values.has(p_class)) { + return Variant(); + } + + if (!default_values[p_class].has(p_property)) { + return Variant(); + } + + return default_values[p_class][p_property]; +} + +EditorDefaultClassValueCache::EditorDefaultClassValueCache() { + ERR_FAIL_COND(singleton != NULL); + singleton = this; +} + Size2 EditorProperty::get_minimum_size() const { Size2 ms; @@ -458,6 +502,12 @@ void EditorProperty::update_reload_status() { bool has_reload = false; + if (EditorDefaultClassValueCache::get_singleton()) { + Variant default_value = EditorDefaultClassValueCache::get_singleton()->get_default_value(object->get_class_name(), property); + if (default_value != Variant() && default_value != object->get(property)) { + has_reload = true; + } + } if (_is_instanced_node_with_original_property_different()) { has_reload = true; } @@ -651,6 +701,7 @@ void EditorProperty::_gui_input(const Ref<InputEvent> &p_event) { Variant rev = object->call("property_get_revert", property); emit_signal("property_changed", property, rev); update_property(); + return; } if (!object->get_script().is_null()) { @@ -659,6 +710,16 @@ void EditorProperty::_gui_input(const Ref<InputEvent> &p_event) { if (scr->get_property_default_value(property, orig_value)) { emit_signal("property_changed", property, orig_value); update_property(); + return; + } + } + + if (EditorDefaultClassValueCache::get_singleton()) { + Variant default_value = EditorDefaultClassValueCache::get_singleton()->get_default_value(object->get_class_name(), property); + if (default_value != Variant()) { + emit_signal("property_changed", property, default_value); + update_property(); + return; } } } @@ -1370,6 +1431,28 @@ void EditorInspector::update_tree() { // TreeItem *current_category = NULL; + bool unfold_if_edited = false; + + if (use_folding && auto_unfold_edited && get_tree()->get_edited_scene_root()) { + String path; + Node *node = Object::cast_to<Node>(object); + if (node) { + path = get_tree()->get_edited_scene_root()->get_filename(); + } + Resource *res = Object::cast_to<Resource>(object); + if (res) { + if (res->get_path().is_resource_file()) { + path = res->get_path(); + } else if (res->get_path().begins_with("res://")) { //internal resource + path = get_tree()->get_edited_scene_root()->get_filename(); + } + } + + if (!EditorNode::get_singleton()->get_editor_folding().has_folding_data(path)) { + unfold_if_edited = true; + } + } + String filter = search_box ? search_box->get_text() : ""; String group; String group_base; @@ -1380,6 +1463,8 @@ void EditorInspector::update_tree() { object->get_property_list(&plist, true); HashMap<String, VBoxContainer *> item_path; + Map<VBoxContainer *, EditorInspectorSection *> section_map; + item_path[""] = main_vbox; Color sscolor = get_color("prop_subsection", "Editor"); @@ -1542,7 +1627,9 @@ void EditorInspector::update_tree() { c.a /= level; section->setup(acc_path, path_name, object, c, use_folding); - item_path[acc_path] = section->get_vbox(); + VBoxContainer *vb = section->get_vbox(); + item_path[acc_path] = vb; + section_map[vb] = section; } current_vbox = item_path[acc_path]; level = (MIN(level + 1, 4)); @@ -1685,6 +1772,13 @@ void EditorInspector::update_tree() { if (current_selected && ep->property == current_selected) { ep->select(current_focusable); } + + if (unfold_if_edited && ep->can_revert_to_default()) { + //if edited and there is a parent section, unfold it. + if (current_vbox && section_map.has(current_vbox)) { + section_map[current_vbox]->unfold(); + } + } } } @@ -2181,6 +2275,10 @@ String EditorInspector::get_object_class() const { return object_class; } +void EditorInspector::set_auto_unfold_edited(bool p_enable) { + auto_unfold_edited = p_enable; +} + void EditorInspector::_bind_methods() { ClassDB::bind_method("_property_changed", &EditorInspector::_property_changed, DEFVAL(false)); @@ -2205,6 +2303,7 @@ void EditorInspector::_bind_methods() { ADD_SIGNAL(MethodInfo("resource_selected", PropertyInfo(Variant::OBJECT, "res"), PropertyInfo(Variant::STRING, "prop"))); ADD_SIGNAL(MethodInfo("object_id_selected", PropertyInfo(Variant::INT, "id"))); ADD_SIGNAL(MethodInfo("property_edited", PropertyInfo(Variant::STRING, "property"))); + ADD_SIGNAL(MethodInfo("property_toggled", PropertyInfo(Variant::STRING, "property"), PropertyInfo(Variant::BOOL, "checked"))); ADD_SIGNAL(MethodInfo("restart_requested")); } @@ -2236,6 +2335,7 @@ EditorInspector::EditorInspector() { set_process(true); property_focusable = -1; use_sub_inspector_bg = false; + auto_unfold_edited = false; get_v_scrollbar()->connect("value_changed", this, "_vscroll_changed"); update_scroll_request = -1; diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h index dccbdb9a73..350debcb7b 100644 --- a/editor/editor_inspector.h +++ b/editor/editor_inspector.h @@ -37,6 +37,20 @@ class UndoRedo; +class EditorDefaultClassValueCache : public Object { + GDCLASS(EditorDefaultClassValueCache, Object) + + Map<StringName, Map<StringName, Variant> > default_values; + + static EditorDefaultClassValueCache *singleton; + +public: + static EditorDefaultClassValueCache *get_singleton(); + + Variant get_default_value(const StringName &p_class, const StringName &p_property); + EditorDefaultClassValueCache(); +}; + class EditorProperty : public Container { GDCLASS(EditorProperty, Container) @@ -152,6 +166,8 @@ public: void set_draw_top_bg(bool p_draw) { draw_top_bg = p_draw; } + bool can_revert_to_default() const { return can_revert; } + EditorProperty(); }; @@ -271,6 +287,7 @@ class EditorInspector : public ScrollContainer { bool read_only; bool keying; bool use_sub_inspector_bg; + bool auto_unfold_edited; float refresh_countdown; bool update_tree_pending; @@ -365,6 +382,7 @@ public: String get_object_class() const; void set_use_sub_inspector_bg(bool p_enable); + void set_auto_unfold_edited(bool p_enable); EditorInspector(); }; diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 7155905472..e9ce2cb8ae 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -1061,6 +1061,9 @@ void EditorNode::_save_scene(String p_file, int idx) { set_current_version(editor_data.get_undo_redo().get_version()); else editor_data.set_edited_scene_version(0, idx); + + editor_folding.save_scene_folding(scene, p_file); + _update_title(); _update_scene_tabs(); } else { @@ -2907,6 +2910,8 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b _update_scene_tabs(); _add_to_recent_scenes(lpath); + editor_folding.load_scene_folding(new_scene, lpath); + prev_scene->set_disabled(previous_scenes.size() == 0); opening_prev = false; @@ -4544,6 +4549,19 @@ void EditorNode::_video_driver_selected(int p_which) { _update_video_driver_color(); } +void EditorNode::_resource_saved(RES p_resource, const String &p_path) { + if (EditorFileSystem::get_singleton()) { + EditorFileSystem::get_singleton()->update_file(p_path); + } + + singleton->editor_folding.save_resource_folding(p_resource, p_path); +} + +void EditorNode::_resource_loaded(RES p_resource, const String &p_path) { + + singleton->editor_folding.load_resource_folding(p_resource, p_path); +} + void EditorNode::_bind_methods() { ClassDB::bind_method("_menu_option", &EditorNode::_menu_option); @@ -4733,6 +4751,8 @@ EditorNode::EditorNode() { ResourceLoader::set_timestamp_on_load(true); ResourceSaver::set_timestamp_on_save(true); + default_value_cache = memnew(EditorDefaultClassValueCache); + { //register importers at the beginning, so dialogs are created with the right extensions Ref<ResourceImporterTexture> import_texture; import_texture.instance(); @@ -4844,6 +4864,7 @@ EditorNode::EditorNode() { EDITOR_DEF_RST("interface/scene_tabs/show_thumbnail_on_hover", true); EDITOR_DEF_RST("interface/inspector/capitalize_properties", true); EDITOR_DEF_RST("interface/inspector/disable_folding", false); + EDITOR_DEF_RST("interface/inspector/auto_unfold_edited", true); EDITOR_DEF("interface/inspector/horizontal_vector2_editing", false); EDITOR_DEF("interface/inspector/horizontal_vector_types_editing", true); EDITOR_DEF("interface/inspector/open_resources_in_current_inspector", true); @@ -5829,6 +5850,9 @@ EditorNode::EditorNode() { print_handler.userdata = this; add_print_handler(&print_handler); + ResourceSaver::set_save_callback(_resource_saved); + ResourceLoader::set_load_callback(_resource_loaded); + #ifdef OSX_ENABLED ED_SHORTCUT("editor/editor_2d", TTR("Open 2D Editor"), KEY_MASK_ALT | KEY_1); ED_SHORTCUT("editor/editor_3d", TTR("Open 3D Editor"), KEY_MASK_ALT | KEY_2); @@ -5857,6 +5881,7 @@ EditorNode::~EditorNode() { memdelete(editor_plugins_force_input_forwarding); memdelete(file_server); memdelete(progress_hb); + memdelete(default_value_cache); EditorSettings::destroy(); } diff --git a/editor/editor_node.h b/editor/editor_node.h index 0096748ed1..33af473de3 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -38,6 +38,7 @@ #include "editor/editor_about.h" #include "editor/editor_data.h" #include "editor/editor_export.h" +#include "editor/editor_folding.h" #include "editor/editor_inspector.h" #include "editor/editor_log.h" #include "editor/editor_name_dialog.h" @@ -271,6 +272,7 @@ private: Ref<Theme> theme; + EditorDefaultClassValueCache *default_value_cache; PopupMenu *recent_scenes; SceneTreeDock *scene_tree_dock; InspectorDock *inspector_dock; @@ -385,6 +387,7 @@ private: EditorSelection *editor_selection; ProjectExportDialog *project_export; EditorResourcePreview *resource_preview; + EditorFolding editor_folding; EditorFileServer *file_server; @@ -600,6 +603,9 @@ private: PrintHandlerList print_handler; static void _print_handler(void *p_this, const String &p_string, bool p_error); + static void _resource_saved(RES p_resource, const String &p_path); + static void _resource_loaded(RES p_resource, const String &p_path); + protected: void _notification(int p_what); static void _bind_methods(); @@ -690,6 +696,7 @@ public: void set_current_scene(int p_idx); static EditorData &get_editor_data() { return singleton->editor_data; } + static EditorFolding &get_editor_folding() { return singleton->editor_folding; } EditorHistory *get_editor_history() { return &editor_history; } static VSplitContainer *get_top_split() { return singleton->top_split; } diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index 5148c12160..7c3e6dc386 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -1802,8 +1802,13 @@ void EditorPropertyNodePath::_node_selected(const NodePath &p_path) { NodePath path = p_path; Node *base_node = Object::cast_to<Node>(get_edited_object()); - if (base_node == NULL && get_edited_object()->has_method("get_root_path")) { - base_node = get_edited_object()->call("get_root_path"); + if (base_node == NULL) { + if (Object::cast_to<Resource>(get_edited_object())) { + Node *to_node = get_node(p_path); + path = get_tree()->get_edited_scene_root()->get_path_to(to_node); + } else if (get_edited_object()->has_method("get_root_path")) { + base_node = get_edited_object()->call("get_root_path"); + } } if (base_node) { // for AnimationTrackKeyEdit path = base_node->get_path().rel_path_to(p_path); diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 6eaa2560db..34c273fbae 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -410,7 +410,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { _initial_set("text_editor/completion/add_type_hints", false); _initial_set("docks/scene_tree/start_create_dialog_fully_expanded", false); - _initial_set("docks/scene_tree/draw_relationship_lines", false); + _initial_set("docks/scene_tree/draw_relationship_lines", true); _initial_set("docks/scene_tree/relationship_line_color", Color::html("464646")); _initial_set("editors/grid_map/pick_distance", 5000.0); diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index ef960f74ea..2136211faa 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -353,7 +353,7 @@ void FileSystemDock::_notification(int p_what) { } break; case NOTIFICATION_THEME_CHANGED: { - if (tree->is_visible_in_tree()) { + if (is_visible_in_tree()) { _update_display_mode(true); } } break; diff --git a/editor/import_dock.cpp b/editor/import_dock.cpp index 31eb193461..2e68609a56 100644 --- a/editor/import_dock.cpp +++ b/editor/import_dock.cpp @@ -38,11 +38,17 @@ public: List<PropertyInfo> properties; Ref<ResourceImporter> importer; Vector<String> paths; + Set<StringName> checked; + bool checking; bool _set(const StringName &p_name, const Variant &p_value) { if (values.has(p_name)) { values[p_name] = p_value; + if (checking) { + checked.insert(p_name); + _change_notify(String(p_name).utf8().get_data()); + } return true; } @@ -63,13 +69,24 @@ public: for (const List<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) { if (!importer->get_option_visibility(E->get().name, values)) continue; - p_list->push_back(E->get()); + PropertyInfo pi = E->get(); + if (checking) { + pi.usage |= PROPERTY_USAGE_CHECKABLE; + if (checked.has(E->get().name)) { + pi.usage |= PROPERTY_USAGE_CHECKED; + } + } + p_list->push_back(pi); } } void update() { _change_notify(); } + + ImportDockParameters() { + checking = false; + } }; void ImportDock::set_edit_path(const String &p_path) { @@ -125,6 +142,8 @@ void ImportDock::_update_options(const Ref<ConfigFile> &p_config) { params->properties.clear(); params->values.clear(); + params->checking = false; + params->checked.clear(); for (List<ResourceImporter::ImportOption>::Element *E = options.front(); E; E = E->next()) { @@ -205,6 +224,8 @@ void ImportDock::set_edit_multiple_paths(const Vector<String> &p_paths) { params->properties.clear(); params->values.clear(); + params->checking = true; + params->checked.clear(); for (List<ResourceImporter::ImportOption>::Element *E = options.front(); E; E = E->next()) { @@ -360,11 +381,21 @@ void ImportDock::_reimport() { Error err = config->load(params->paths[i] + ".import"); ERR_CONTINUE(err != OK); - config->set_value("remap", "importer", params->importer->get_importer_name()); - config->erase_section("params"); + if (params->checking) { + //update only what edited (checkboxes) + for (List<PropertyInfo>::Element *E = params->properties.front(); E; E = E->next()) { + if (params->checked.has(E->get().name)) { + config->set_value("params", E->get().name, params->values[E->get().name]); + } + } + } else { + //override entirely + config->set_value("remap", "importer", params->importer->get_importer_name()); + config->erase_section("params"); - for (List<PropertyInfo>::Element *E = params->properties.front(); E; E = E->next()) { - config->set_value("params", E->get().name, params->values[E->get().name]); + for (List<PropertyInfo>::Element *E = params->properties.front(); E; E = E->next()) { + config->set_value("params", E->get().name, params->values[E->get().name]); + } } config->save(params->paths[i] + ".import"); @@ -388,11 +419,20 @@ void ImportDock::_notification(int p_what) { } break; } } + +void ImportDock::_property_toggled(const StringName &p_prop, bool p_checked) { + if (p_checked) { + params->checked.insert(p_prop); + } else { + params->checked.erase(p_prop); + } +} void ImportDock::_bind_methods() { ClassDB::bind_method(D_METHOD("_reimport"), &ImportDock::_reimport); ClassDB::bind_method(D_METHOD("_preset_selected"), &ImportDock::_preset_selected); ClassDB::bind_method(D_METHOD("_importer_selected"), &ImportDock::_importer_selected); + ClassDB::bind_method(D_METHOD("_property_toggled"), &ImportDock::_property_toggled); } void ImportDock::initialize_import_options() const { @@ -423,6 +463,7 @@ ImportDock::ImportDock() { import_opts = memnew(EditorInspector); add_child(import_opts); import_opts->set_v_size_flags(SIZE_EXPAND_FILL); + import_opts->connect("property_toggled", this, "_property_toggled"); hb = memnew(HBoxContainer); add_child(hb); diff --git a/editor/import_dock.h b/editor/import_dock.h index 41c7298d9a..632fd39700 100644 --- a/editor/import_dock.h +++ b/editor/import_dock.h @@ -60,6 +60,7 @@ class ImportDock : public VBoxContainer { void _importer_selected(int i_idx); void _update_options(const Ref<ConfigFile> &p_config = Ref<ConfigFile>()); + void _property_toggled(const StringName &p_prop, bool p_checked); void _reimport(); enum { diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp index 750fca2852..2a8885c0a4 100644 --- a/editor/inspector_dock.cpp +++ b/editor/inspector_dock.cpp @@ -593,6 +593,7 @@ InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) { inspector->set_undo_redo(&editor_data->get_undo_redo()); inspector->set_use_filter(true); // TODO: check me + inspector->set_auto_unfold_edited(bool(EDITOR_GET("interface/inspector/auto_unfold_edited"))); inspector->connect("resource_selected", this, "_resource_selected"); inspector->connect("property_keyed", this, "_property_keyed"); diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index 07a7e7952a..ac69cc0df1 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -1363,7 +1363,9 @@ void ScriptEditor::_notification(int p_what) { if (is_visible()) { find_in_files_button->show(); } else { - find_in_files->hide(); + if (find_in_files->is_visible_in_tree()) { + editor->hide_bottom_panel(); + } find_in_files_button->hide(); } @@ -2806,8 +2808,7 @@ void ScriptEditor::_start_find_in_files(bool with_replace) { find_in_files->set_with_replace(with_replace); find_in_files->start_search(); - find_in_files_button->set_pressed(true); - find_in_files->show(); + editor->make_bottom_panel_item_visible(find_in_files); } void ScriptEditor::_on_find_in_files_modified_files(PoolStringArray paths) { @@ -3174,7 +3175,6 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { add_child(find_in_files_dialog); find_in_files = memnew(FindInFilesPanel); find_in_files_button = editor->add_bottom_panel_item(TTR("Search Results"), find_in_files); - find_in_files_button->set_tooltip(TTR("Search in files")); find_in_files->set_custom_minimum_size(Size2(0, 200) * EDSCALE); find_in_files->connect(FindInFilesPanel::SIGNAL_RESULT_SELECTED, this, "_on_find_in_files_result_selected"); find_in_files->connect(FindInFilesPanel::SIGNAL_FILES_MODIFIED, this, "_on_find_in_files_modified_files"); diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp index 30246147c2..40781908fd 100644 --- a/editor/plugins/sprite_frames_editor_plugin.cpp +++ b/editor/plugins/sprite_frames_editor_plugin.cpp @@ -548,7 +548,6 @@ void SpriteFramesEditor::edit(SpriteFrames *p_frames) { } else { hide(); - //set_physics_process(false); } } @@ -816,16 +815,26 @@ SpriteFramesEditor::SpriteFramesEditor() { void SpriteFramesEditorPlugin::edit(Object *p_object) { frames_editor->set_undo_redo(&get_undo_redo()); - SpriteFrames *s = Object::cast_to<SpriteFrames>(p_object); - if (!s) - return; + + SpriteFrames *s; + AnimatedSprite *animated_sprite = Object::cast_to<AnimatedSprite>(p_object); + if (animated_sprite) { + s = *animated_sprite->get_sprite_frames(); + } else { + s = Object::cast_to<SpriteFrames>(p_object); + } frames_editor->edit(s); } bool SpriteFramesEditorPlugin::handles(Object *p_object) const { - return p_object->is_class("SpriteFrames"); + AnimatedSprite *animated_sprite = Object::cast_to<AnimatedSprite>(p_object); + if (animated_sprite && *animated_sprite->get_sprite_frames()) { + return true; + } else { + return p_object->is_class("SpriteFrames"); + } } void SpriteFramesEditorPlugin::make_visible(bool p_visible) { @@ -833,14 +842,11 @@ void SpriteFramesEditorPlugin::make_visible(bool p_visible) { if (p_visible) { button->show(); editor->make_bottom_panel_item_visible(frames_editor); - //frames_editor->set_process(true); } else { button->hide(); if (frames_editor->is_visible_in_tree()) editor->hide_bottom_panel(); - - //frames_editor->set_process(false); } } diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp index 9988d82fb8..7936b2a1e7 100644 --- a/editor/plugins/tile_set_editor_plugin.cpp +++ b/editor/plugins/tile_set_editor_plugin.cpp @@ -483,6 +483,11 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) { //--------------- helper = memnew(TilesetEditorContext(this)); tile_names_opacity = 0; + + // config scale + max_scale = 10.0f; + min_scale = 0.1f; + scale_ratio = 1.2f; } TileSetEditor::~TileSetEditor() { @@ -972,6 +977,15 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { } } } + + // Mouse Wheel Event + const int _mouse_button_index = mb->get_button_index(); + if (_mouse_button_index == BUTTON_WHEEL_UP && mb->get_control()) { + _zoom_in(); + + } else if (_mouse_button_index == BUTTON_WHEEL_DOWN && mb->get_control()) { + _zoom_out(); + } } // Drag Middle Mouse if (mm.is_valid()) { @@ -1448,23 +1462,11 @@ void TileSetEditor::_on_tool_clicked(int p_tool) { } } } else if (p_tool == ZOOM_OUT) { - float scale = workspace->get_scale().x; - if (scale > 0.1) { - scale /= 2; - workspace->set_scale(Vector2(scale, scale)); - workspace_container->set_custom_minimum_size(workspace->get_rect().size * scale); - workspace_overlay->set_custom_minimum_size(workspace->get_rect().size * scale); - } + _zoom_out(); } else if (p_tool == ZOOM_1) { - workspace->set_scale(Vector2(1, 1)); - workspace_container->set_custom_minimum_size(workspace->get_rect().size); - workspace_overlay->set_custom_minimum_size(workspace->get_rect().size); + _reset_zoom(); } else if (p_tool == ZOOM_IN) { - float scale = workspace->get_scale().x; - scale *= 2; - workspace->set_scale(Vector2(scale, scale)); - workspace_container->set_custom_minimum_size(workspace->get_rect().size * scale); - workspace_overlay->set_custom_minimum_size(workspace->get_rect().size * scale); + _zoom_in(); } else if (p_tool == TOOL_SELECT) { if (creating_shape) { // Cancel Creation @@ -1503,6 +1505,31 @@ void TileSetEditor::_set_snap_sep(Vector2 p_val) { workspace->update(); } +void TileSetEditor::_zoom_in() { + float scale = workspace->get_scale().x; + if (scale < max_scale) { + scale *= scale_ratio; + workspace->set_scale(Vector2(scale, scale)); + workspace_container->set_custom_minimum_size(workspace->get_rect().size * scale); + workspace_overlay->set_custom_minimum_size(workspace->get_rect().size * scale); + } +} +void TileSetEditor::_zoom_out() { + + float scale = workspace->get_scale().x; + if (scale > min_scale) { + scale /= scale_ratio; + workspace->set_scale(Vector2(scale, scale)); + workspace_container->set_custom_minimum_size(workspace->get_rect().size * scale); + workspace_overlay->set_custom_minimum_size(workspace->get_rect().size * scale); + } +} +void TileSetEditor::_reset_zoom() { + workspace->set_scale(Vector2(1, 1)); + workspace_container->set_custom_minimum_size(workspace->get_rect().size); + workspace_overlay->set_custom_minimum_size(workspace->get_rect().size); +} + void TileSetEditor::draw_highlight_current_tile() { if (get_current_tile() >= 0) { diff --git a/editor/plugins/tile_set_editor_plugin.h b/editor/plugins/tile_set_editor_plugin.h index 23bf68b90f..bd8a2ddb98 100644 --- a/editor/plugins/tile_set_editor_plugin.h +++ b/editor/plugins/tile_set_editor_plugin.h @@ -141,6 +141,10 @@ class TileSetEditor : public Control { EditMode edit_mode; int current_tile; + float max_scale; + float min_scale; + float scale_ratio; + void update_texture_list(); void update_texture_list_icon(); @@ -178,6 +182,10 @@ private: void _set_snap_off(Vector2 p_val); void _set_snap_sep(Vector2 p_val); + void _zoom_in(); + void _zoom_out(); + void _reset_zoom(); + void draw_highlight_current_tile(); void draw_highlight_subtile(Vector2 coord, const Vector<Vector2> &other_highlighted = Vector<Vector2>()); void draw_tile_subdivision(int p_id, Color p_color) const; diff --git a/editor/project_export.cpp b/editor/project_export.cpp index 3ec49e187f..d2dccdb425 100644 --- a/editor/project_export.cpp +++ b/editor/project_export.cpp @@ -50,6 +50,7 @@ void ProjectExportDialog::_notification(int p_what) { switch (p_what) { case NOTIFICATION_READY: { + duplicate_preset->set_icon(get_icon("Duplicate", "EditorIcons")); delete_preset->set_icon(get_icon("Remove", "EditorIcons")); connect("confirmed", this, "_export_pck_zip"); custom_feature_display->get_parent_control()->add_style_override("panel", get_stylebox("bg", "Tree")); @@ -58,6 +59,7 @@ void ProjectExportDialog::_notification(int p_what) { EditorSettings::get_singleton()->set("interface/dialogs/export_bounds", get_rect()); } break; case NOTIFICATION_THEME_CHANGED: { + duplicate_preset->set_icon(get_icon("Duplicate", "EditorIcons")); delete_preset->set_icon(get_icon("Remove", "EditorIcons")); Control *panel = custom_feature_display->get_parent_control(); if (panel) @@ -171,6 +173,7 @@ void ProjectExportDialog::_edit_preset(int p_index) { runnable->set_disabled(true); parameters->edit(NULL); presets->unselect_all(); + duplicate_preset->set_disabled(true); delete_preset->set_disabled(true); sections->hide(); patches->clear(); @@ -188,6 +191,7 @@ void ProjectExportDialog::_edit_preset(int p_index) { sections->show(); name->set_editable(true); + duplicate_preset->set_disabled(false); delete_preset->set_disabled(false); name->set_text(current->get_name()); runnable->set_disabled(false); @@ -428,6 +432,61 @@ void ProjectExportDialog::_name_changed(const String &p_string) { _update_presets(); } +void ProjectExportDialog::_duplicate_preset() { + + Ref<EditorExportPreset> current = EditorExport::get_singleton()->get_export_preset(presets->get_current()); + if (current.is_null()) + return; + + Ref<EditorExportPreset> preset = current->get_platform()->create_preset(); + ERR_FAIL_COND(!preset.is_valid()); + + String name = current->get_name() + "" + itos(1); + bool make_runnable = true; + int attempt = 2; + while (true) { + + bool valid = true; + + for (int i = 0; i < EditorExport::get_singleton()->get_export_preset_count(); i++) { + Ref<EditorExportPreset> p = EditorExport::get_singleton()->get_export_preset(i); + if (p->get_platform() == preset->get_platform() && p->is_runnable()) { + make_runnable = false; + } + if (p->get_name() == name) { + valid = false; + break; + } + } + + if (valid) + break; + + attempt++; + name = current->get_name() + " " + itos(attempt); + } + + preset->set_name(name); + if (make_runnable) + preset->set_runnable(make_runnable); + preset->set_export_filter(current->get_export_filter()); + preset->set_include_filter(current->get_include_filter()); + preset->set_exclude_filter(current->get_exclude_filter()); + Vector<String> list = current->get_patches(); + for (int i = 0; i < list.size(); i++) { + preset->add_patch(list[i]); + } + preset->set_custom_features(current->get_custom_features()); + + for (const List<PropertyInfo>::Element *E = current->get_properties().front(); E; E = E->next()) { + preset->set(E->get().name, current->get(E->get().name)); + } + + EditorExport::get_singleton()->add_export_preset(preset); + _update_presets(); + _edit_preset(EditorExport::get_singleton()->get_export_preset_count() - 1); +} + void ProjectExportDialog::_delete_preset() { Ref<EditorExportPreset> current = EditorExport::get_singleton()->get_export_preset(presets->get_current()); @@ -745,12 +804,16 @@ void ProjectExportDialog::_export_project() { export_project->set_access(FileDialog::ACCESS_FILESYSTEM); export_project->clear_filters(); - String extension = platform->get_binary_extension(current); - if (extension != String()) { - export_project->add_filter("*." + extension + " ; " + platform->get_name() + " Export"); - export_project->set_current_file(default_filename + "." + extension); + if (current->get_export_path() != "") { + export_project->set_current_path(current->get_export_path()); } else { - export_project->set_current_file(default_filename); + String extension = platform->get_binary_extension(current); + if (extension != String()) { + export_project->add_filter("*." + extension + " ; " + platform->get_name() + " Export"); + export_project->set_current_file(default_filename + "." + extension); + } else { + export_project->set_current_file(default_filename); + } } // Ensure that signal is connected if previous attempt left it disconnected with _validate_export_path @@ -772,6 +835,7 @@ void ProjectExportDialog::_export_project_to_path(const String &p_path) { ERR_FAIL_COND(current.is_null()); Ref<EditorExportPlatform> platform = current->get_platform(); ERR_FAIL_COND(platform.is_null()); + current->set_export_path(p_path); Error err = platform->export_project(current, export_debug->is_pressed(), p_path, 0); if (err != OK) { @@ -789,6 +853,7 @@ void ProjectExportDialog::_bind_methods() { ClassDB::bind_method("_update_parameters", &ProjectExportDialog::_update_parameters); ClassDB::bind_method("_runnable_pressed", &ProjectExportDialog::_runnable_pressed); ClassDB::bind_method("_name_changed", &ProjectExportDialog::_name_changed); + ClassDB::bind_method("_duplicate_preset", &ProjectExportDialog::_duplicate_preset); ClassDB::bind_method("_delete_preset", &ProjectExportDialog::_delete_preset); ClassDB::bind_method("_delete_preset_confirm", &ProjectExportDialog::_delete_preset_confirm); ClassDB::bind_method("get_drag_data_fw", &ProjectExportDialog::get_drag_data_fw); @@ -842,6 +907,9 @@ ProjectExportDialog::ProjectExportDialog() { presets->set_drag_forwarding(this); mc->add_child(presets); presets->connect("item_selected", this, "_edit_preset"); + duplicate_preset = memnew(ToolButton); + preset_hb->add_child(duplicate_preset); + duplicate_preset->connect("pressed", this, "_duplicate_preset"); delete_preset = memnew(ToolButton); preset_hb->add_child(delete_preset); delete_preset->connect("pressed", this, "_delete_preset"); @@ -949,6 +1017,7 @@ ProjectExportDialog::ProjectExportDialog() { //disable by default name->set_editable(false); runnable->set_disabled(true); + duplicate_preset->set_disabled(true); delete_preset->set_disabled(true); sections->hide(); parameters->edit(NULL); diff --git a/editor/project_export.h b/editor/project_export.h index 552c6d7faf..a4bca843a8 100644 --- a/editor/project_export.h +++ b/editor/project_export.h @@ -61,6 +61,7 @@ private: TabContainer *sections; MenuButton *add_preset; + Button *duplicate_preset; Button *delete_preset; ItemList *presets; @@ -108,6 +109,7 @@ private: void _name_changed(const String &p_string); void _add_preset(int p_platform); void _edit_preset(int p_index); + void _duplicate_preset(); void _delete_preset(); void _delete_preset_confirm(); diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 4f0f79ee1b..fe438236c9 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -358,15 +358,12 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { ScriptLanguage *l = ScriptServer::get_language(i); if (l->get_type() == existing->get_class()) { String name = l->get_global_class_name(existing->get_path()); - if (ScriptServer::is_global_class(name)) { - if (EDITOR_GET("interface/editors/derive_script_globals_by_name").operator bool()) { - inherits = editor->get_editor_data().script_class_get_base(name); - } else if (l->can_inherit_from_file()) { - inherits = "\"" + existing->get_path() + "\""; - } - } else { + if (ScriptServer::is_global_class(name) && EDITOR_GET("interface/editors/derive_script_globals_by_name").operator bool()) { + inherits = name; + } else if (l->can_inherit_from_file()) { inherits = "\"" + existing->get_path() + "\""; } + break; } } } @@ -1503,6 +1500,7 @@ void SceneTreeDock::_script_created(Ref<Script> p_script) { editor_data->get_undo_redo().commit_action(); editor->push_item(p_script.operator->()); + _update_script_button(); } void SceneTreeDock::_toggle_editable_children() { @@ -1618,17 +1616,17 @@ void SceneTreeDock::_delete_confirm() { void SceneTreeDock::_update_script_button() { if (EditorNode::get_singleton()->get_editor_selection()->get_selection().size() == 1) { - button_create_script->show(); Node *n = EditorNode::get_singleton()->get_editor_selection()->get_selected_node_list()[0]; if (n->get_script().is_null()) { - button_create_script->set_icon(get_icon("ScriptCreate", "EditorIcons")); - button_create_script->set_tooltip(TTR("Attach a new or existing script for the selected node.")); + button_create_script->show(); + button_clear_script->hide(); } else { - button_create_script->set_icon(get_icon("ScriptExtend", "EditorIcons")); - button_create_script->set_tooltip(TTR("Extend the selected node's script with a new or existing script.")); + button_create_script->hide(); + button_clear_script->show(); } } else { - button_create_script->hide(); + button_create_script->show(); + button_clear_script->hide(); } } @@ -2073,9 +2071,12 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) { existing_script = selected->get_script(); } - menu->add_icon_shortcut(get_icon("ScriptCreate", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/attach_script"), TOOL_ATTACH_SCRIPT); + if (!existing_script.is_valid()) { + menu->add_icon_shortcut(get_icon("ScriptCreate", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/attach_script"), TOOL_ATTACH_SCRIPT); + } if (selection.size() > 1 || existing_script.is_valid()) { menu->add_icon_shortcut(get_icon("ScriptRemove", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/clear_script"), TOOL_CLEAR_SCRIPT); + menu->add_icon_shortcut(get_icon("ScriptExtend", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/extend_script"), TOOL_ATTACH_SCRIPT); } menu->add_separator(); @@ -2339,6 +2340,7 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel ED_SHORTCUT("scene_tree/instance_scene", TTR("Instance Child Scene")); ED_SHORTCUT("scene_tree/change_node_type", TTR("Change Type")); ED_SHORTCUT("scene_tree/attach_script", TTR("Attach Script")); + ED_SHORTCUT("scene_tree/extend_script", TTR("Extend Script")); ED_SHORTCUT("scene_tree/clear_script", TTR("Clear Script")); ED_SHORTCUT("scene_tree/move_up", TTR("Move Up"), KEY_MASK_CMD | KEY_UP); ED_SHORTCUT("scene_tree/move_down", TTR("Move Down"), KEY_MASK_CMD | KEY_DOWN); @@ -2375,6 +2377,7 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel tb = memnew(ToolButton); tb->connect("pressed", this, "_tool_selected", make_binds(TOOL_ATTACH_SCRIPT, false)); + tb->set_tooltip(TTR("Attach a new or existing script for the selected node.")); tb->set_shortcut(ED_GET_SHORTCUT("scene_tree/attach_script")); filter_hbc->add_child(tb); tb->hide(); diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp index 848e4def6d..6614e24df7 100644 --- a/editor/scene_tree_editor.cpp +++ b/editor/scene_tree_editor.cpp @@ -665,6 +665,13 @@ void SceneTreeEditor::_renamed() { Node *n = get_node(np); ERR_FAIL_COND(!n); + // Empty node names are not allowed, so resets it to previous text and show warning + if (which->get_text(0).strip_edges().empty()) { + which->set_text(0, n->get_name()); + EditorNode::get_singleton()->show_warning(TTR("No name provided")); + return; + } + String new_name = which->get_text(0); if (!Node::_validate_node_name(new_name)) { diff --git a/gles_builders.py b/gles_builders.py index 1e63a53f1a..f9fd6d3fa2 100644 --- a/gles_builders.py +++ b/gles_builders.py @@ -59,11 +59,11 @@ def include_file_in_legacygl_header(filename, header_data, depth): included_file = os.path.relpath(os.path.dirname(filename) + "/" + includeline) if not included_file in header_data.vertex_included_files and header_data.reading == "vertex": header_data.vertex_included_files += [included_file] - if include_file_in_legacygl_header(included_file, header_data, depth + 1) == None: + if include_file_in_legacygl_header(included_file, header_data, depth + 1) is None: print("Error in file '" + filename + "': #include " + includeline + "could not be found!") elif not included_file in header_data.fragment_included_files and header_data.reading == "fragment": header_data.fragment_included_files += [included_file] - if include_file_in_legacygl_header(included_file, header_data, depth + 1) == None: + if include_file_in_legacygl_header(included_file, header_data, depth + 1) is None: print("Error in file '" + filename + "': #include " + includeline + "could not be found!") line = fs.readline() diff --git a/methods.py b/methods.py index 0cf05751a8..111a2347be 100644 --- a/methods.py +++ b/methods.py @@ -330,7 +330,7 @@ def split_lib(self, libname, src_list = None, env_lib = None): list = [] lib_list = [] - if src_list == None: + if src_list is None: src_list = getattr(env, libname + "_sources") if type(env_lib) == type(None): diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp index 44044d2750..4eb798de11 100644 --- a/modules/csg/csg_shape.cpp +++ b/modules/csg/csg_shape.cpp @@ -598,8 +598,8 @@ CSGBrush *CSGMesh::_build_brush() { mw[j / 3] = mat; } } else { - int is = vertices.size(); - int as = avertices.size(); + int as = vertices.size(); + int is = avertices.size(); vertices.resize(as + is); smooth.resize((as + is) / 3); diff --git a/modules/gdnative/gdnative.cpp b/modules/gdnative/gdnative.cpp index ecde73ae1c..283e9b3bc8 100644 --- a/modules/gdnative/gdnative.cpp +++ b/modules/gdnative/gdnative.cpp @@ -306,6 +306,13 @@ bool GDNative::initialize() { #elif defined(UWP_ENABLED) // On UWP we use a relative path from the app String path = lib_path.replace("res://", ""); +#elif defined(OSX_ENABLED) + // On OSX the exported libraries are located under the Frameworks directory. + // So we need to replace the library path. + String path = ProjectSettings::get_singleton()->globalize_path(lib_path); + if (!FileAccess::exists(path)) { + path = OS::get_singleton()->get_executable_path().get_base_dir().plus_file("../Frameworks").plus_file(lib_path.get_file()); + } #else String path = ProjectSettings::get_singleton()->globalize_path(lib_path); #endif diff --git a/modules/gdnative/gdnative/array.cpp b/modules/gdnative/gdnative/array.cpp index 1fb0ff0500..a30cc09bf6 100644 --- a/modules/gdnative/gdnative/array.cpp +++ b/modules/gdnative/gdnative/array.cpp @@ -318,6 +318,38 @@ void GDAPI godot_array_destroy(godot_array *p_self) { ((Array *)p_self)->~Array(); } +godot_array GDAPI godot_array_duplicate(const godot_array *p_self, const godot_bool p_deep) { + const Array *self = (const Array *)p_self; + godot_array res; + Array *val = (Array *)&res; + memnew_placement(val, Array); + *val = self->duplicate(p_deep); + return res; +} + +godot_variant GDAPI godot_array_max(const godot_array *p_self) { + const Array *self = (const Array *)p_self; + godot_variant v; + Variant *val = (Variant *)&v; + memnew_placement(val, Variant); + *val = self->max(); + return v; +} + +godot_variant GDAPI godot_array_min(const godot_array *p_self) { + const Array *self = (const Array *)p_self; + godot_variant v; + Variant *val = (Variant *)&v; + memnew_placement(val, Variant); + *val = self->min(); + return v; +} + +void GDAPI godot_array_shuffle(godot_array *p_self) { + Array *self = (Array *)p_self; + self->shuffle(); +} + #ifdef __cplusplus } #endif diff --git a/modules/gdnative/gdnative/basis.cpp b/modules/gdnative/gdnative/basis.cpp index 70d2814577..d88499ade1 100644 --- a/modules/gdnative/gdnative/basis.cpp +++ b/modules/gdnative/gdnative/basis.cpp @@ -282,6 +282,15 @@ godot_basis GDAPI godot_basis_operator_multiply_scalar(const godot_basis *p_self return raw_dest; } +godot_basis GDAPI godot_basis_slerp(const godot_basis *p_self, const godot_basis *p_b, const godot_real p_t) { + godot_basis raw_dest; + Basis *dest = (Basis *)&raw_dest; + const Basis *self = (const Basis *)p_self; + const Basis *b = (const Basis *)p_b; + *dest = self->slerp(*b, p_t); + return raw_dest; +} + #ifdef __cplusplus } #endif diff --git a/modules/gdnative/gdnative/color.cpp b/modules/gdnative/gdnative/color.cpp index 4089f4458a..79f0c71b5e 100644 --- a/modules/gdnative/gdnative/color.cpp +++ b/modules/gdnative/gdnative/color.cpp @@ -116,6 +116,26 @@ godot_int GDAPI godot_color_to_rgba32(const godot_color *p_self) { return self->to_rgba32(); } +godot_int GDAPI godot_color_to_abgr32(const godot_color *p_self) { + const Color *self = (const Color *)p_self; + return self->to_abgr32(); +} + +godot_int GDAPI godot_color_to_abgr64(const godot_color *p_self) { + const Color *self = (const Color *)p_self; + return self->to_abgr64(); +} + +godot_int GDAPI godot_color_to_argb64(const godot_color *p_self) { + const Color *self = (const Color *)p_self; + return self->to_argb64(); +} + +godot_int GDAPI godot_color_to_rgba64(const godot_color *p_self) { + const Color *self = (const Color *)p_self; + return self->to_rgba64(); +} + godot_int GDAPI godot_color_to_argb32(const godot_color *p_self) { const Color *self = (const Color *)p_self; return self->to_argb32(); @@ -156,6 +176,27 @@ godot_color GDAPI godot_color_blend(const godot_color *p_self, const godot_color return dest; } +godot_color GDAPI godot_color_darkened(const godot_color *p_self, const godot_real p_amount) { + godot_color dest; + const Color *self = (const Color *)p_self; + *((Color *)&dest) = self->darkened(p_amount); + return dest; +} + +godot_color GDAPI godot_color_from_hsv(const godot_color *p_self, const godot_real p_h, const godot_real p_s, const godot_real p_v, const godot_real p_a) { + godot_color dest; + const Color *self = (const Color *)p_self; + *((Color *)&dest) = self->from_hsv(p_h, p_s, p_v, p_a); + return dest; +} + +godot_color GDAPI godot_color_lightened(const godot_color *p_self, const godot_real p_amount) { + godot_color dest; + const Color *self = (const Color *)p_self; + *((Color *)&dest) = self->lightened(p_amount); + return dest; +} + godot_string GDAPI godot_color_to_html(const godot_color *p_self, const godot_bool p_with_alpha) { godot_string dest; const Color *self = (const Color *)p_self; diff --git a/modules/gdnative/gdnative/node_path.cpp b/modules/gdnative/gdnative/node_path.cpp index f24facaae8..cf82940e09 100644 --- a/modules/gdnative/gdnative/node_path.cpp +++ b/modules/gdnative/gdnative/node_path.cpp @@ -110,6 +110,15 @@ godot_bool GDAPI godot_node_path_operator_equal(const godot_node_path *p_self, c return *self == *b; } +godot_node_path godot_node_path_get_as_property_path(const godot_node_path *p_self) { + const NodePath *self = (const NodePath *)p_self; + godot_node_path res; + NodePath *val = (NodePath *)&res; + memnew_placement(val, NodePath); + *val = self->get_as_property_path(); + return res; +} + #ifdef __cplusplus } #endif diff --git a/modules/gdnative/gdnative/quat.cpp b/modules/gdnative/gdnative/quat.cpp index ddec77edcd..2594759508 100644 --- a/modules/gdnative/gdnative/quat.cpp +++ b/modules/gdnative/gdnative/quat.cpp @@ -225,6 +225,12 @@ godot_quat GDAPI godot_quat_operator_neg(const godot_quat *p_self) { return raw_dest; } +void GDAPI godot_quat_set_axis_angle(godot_quat *p_self, const godot_vector3 *p_axis, const godot_real p_angle) { + Quat *self = (Quat *)p_self; + const Vector3 *axis = (const Vector3 *)p_axis; + self->set_axis_angle(*axis, p_angle); +} + #ifdef __cplusplus } #endif diff --git a/modules/gdnative/gdnative/rect2.cpp b/modules/gdnative/gdnative/rect2.cpp index 54b98fc4e5..5cbc2712c3 100644 --- a/modules/gdnative/gdnative/rect2.cpp +++ b/modules/gdnative/gdnative/rect2.cpp @@ -109,6 +109,27 @@ godot_rect2 GDAPI godot_rect2_grow(const godot_rect2 *p_self, const godot_real p return dest; } +godot_rect2 GDAPI godot_rect2_grow_individual(const godot_rect2 *p_self, const godot_real p_left, const godot_real p_top, const godot_real p_right, const godot_real p_bottom) { + godot_rect2 dest; + const Rect2 *self = (const Rect2 *)p_self; + *((Rect2 *)&dest) = self->grow_individual(p_left, p_top, p_right, p_bottom); + return dest; +} + +godot_rect2 GDAPI godot_rect2_grow_margin(const godot_rect2 *p_self, const godot_int p_margin, const godot_real p_by) { + godot_rect2 dest; + const Rect2 *self = (const Rect2 *)p_self; + *((Rect2 *)&dest) = self->grow_margin((Margin)p_margin, p_by); + return dest; +} + +godot_rect2 GDAPI godot_rect2_abs(const godot_rect2 *p_self) { + godot_rect2 dest; + const Rect2 *self = (const Rect2 *)p_self; + *((Rect2 *)&dest) = self->abs(); + return dest; +} + godot_rect2 GDAPI godot_rect2_expand(const godot_rect2 *p_self, const godot_vector2 *p_to) { godot_rect2 dest; const Rect2 *self = (const Rect2 *)p_self; diff --git a/modules/gdnative/gdnative/string.cpp b/modules/gdnative/gdnative/string.cpp index 8ca57392a3..0996633b70 100644 --- a/modules/gdnative/gdnative/string.cpp +++ b/modules/gdnative/gdnative/string.cpp @@ -1285,6 +1285,64 @@ godot_bool GDAPI godot_string_is_valid_ip_address(const godot_string *p_self) { return self->is_valid_ip_address(); } +godot_string GDAPI godot_string_dedent(const godot_string *p_self) { + const String *self = (const String *)p_self; + godot_string result; + String return_value = self->dedent(); + memnew_placement(&result, String(return_value)); + + return result; +} + +godot_string GDAPI godot_string_trim_prefix(const godot_string *p_self, const godot_string *p_prefix) { + const String *self = (const String *)p_self; + String *prefix = (String *)p_prefix; + godot_string result; + String return_value = self->trim_prefix(*prefix); + memnew_placement(&result, String(return_value)); + + return result; +} + +godot_string GDAPI godot_string_trim_suffix(const godot_string *p_self, const godot_string *p_suffix) { + const String *self = (const String *)p_self; + String *suffix = (String *)p_suffix; + godot_string result; + String return_value = self->trim_suffix(*suffix); + memnew_placement(&result, String(return_value)); + + return result; +} + +godot_string GDAPI godot_string_rstrip(const godot_string *p_self, const godot_string *p_chars) { + const String *self = (const String *)p_self; + String *chars = (String *)p_chars; + godot_string result; + String return_value = self->rstrip(*chars); + memnew_placement(&result, String(return_value)); + + return result; +} + +godot_pool_string_array GDAPI godot_string_rsplit(const godot_string *p_self, const godot_string *p_divisor, + const godot_bool p_allow_empty, const godot_int p_maxsplit) { + const String *self = (const String *)p_self; + String *divisor = (String *)p_divisor; + + godot_pool_string_array result; + memnew_placement(&result, PoolStringArray); + PoolStringArray *proxy = (PoolStringArray *)&result; + PoolStringArray::Write proxy_writer = proxy->write(); + Vector<String> tmp_result = self->rsplit(*divisor, p_allow_empty, p_maxsplit); + proxy->resize(tmp_result.size()); + + for (int i = 0; i < tmp_result.size(); i++) { + proxy_writer[i] = tmp_result[i]; + } + + return result; +} + #ifdef __cplusplus } #endif diff --git a/modules/gdnative/gdnative_api.json b/modules/gdnative/gdnative_api.json index 16a34a9a33..c5a1fa139e 100644 --- a/modules/gdnative/gdnative_api.json +++ b/modules/gdnative/gdnative_api.json @@ -14,6 +14,183 @@ "next": null, "api": [ { + "name": "godot_color_to_abgr32", + "return_type": "godot_int", + "arguments": [ + ["const godot_color *", "p_self"] + ] + }, + { + "name": "godot_color_to_abgr64", + "return_type": "godot_int", + "arguments": [ + ["const godot_color *", "p_self"] + ] + }, + { + "name": "godot_color_to_argb64", + "return_type": "godot_int", + "arguments": [ + ["const godot_color *", "p_self"] + ] + }, + { + "name": "godot_color_to_rgba64", + "return_type": "godot_int", + "arguments": [ + ["const godot_color *", "p_self"] + ] + }, + { + "name": "godot_color_darkened", + "return_type": "godot_color", + "arguments": [ + ["const godot_color *", "p_self"], + ["const godot_real", "p_amount"] + ] + }, + { + "name": "godot_color_from_hsv", + "return_type": "godot_color", + "arguments": [ + ["const godot_color *", "p_self"], + ["const godot_real", "p_h"], + ["const godot_real", "p_s"], + ["const godot_real", "p_v"], + ["const godot_real", "p_a"] + ] + }, + { + "name": "godot_color_lightened", + "return_type": "godot_color", + "arguments": [ + ["const godot_color *", "p_self"], + ["const godot_real", "p_amount"] + ] + }, + { + "name": "godot_array_duplicate", + "return_type": "godot_array", + "arguments": [ + ["const godot_array *", "p_self"], + ["const godot_bool", "p_deep"] + ] + }, + { + "name": "godot_array_max", + "return_type": "godot_variant", + "arguments": [ + ["const godot_array *", "p_self"] + ] + }, + { + "name": "godot_array_min", + "return_type": "godot_variant", + "arguments": [ + ["const godot_array *", "p_self"] + ] + }, + { + "name": "godot_array_shuffle", + "return_type": "void", + "arguments": [ + ["godot_array *", "p_self"] + ] + }, + { + "name": "godot_basis_slerp", + "return_type": "godot_basis", + "arguments": [ + ["const godot_basis *", "p_self"], + ["const godot_basis *", "p_b"], + ["const godot_real", "p_t"] + ] + }, + { + "name": "godot_node_path_get_as_property_path", + "return_type": "godot_node_path", + "arguments": [ + ["const godot_node_path *", "p_self"] + ] + }, + { + "name": "godot_quat_set_axis_angle", + "return_type": "void", + "arguments": [ + ["godot_quat *", "p_self"], + ["const godot_vector3 *", "p_axis"], + ["const godot_real", "p_angle"] + ] + }, + { + "name": "godot_rect2_grow_individual", + "return_type": "godot_rect2", + "arguments": [ + ["const godot_rect2 *", "p_self"], + ["const godot_real", "p_left"], + ["const godot_real", "p_top"], + ["const godot_real", "p_right"], + ["const godot_real", "p_bottom"] + ] + }, + { + "name": "godot_rect2_grow_margin", + "return_type": "godot_rect2", + "arguments": [ + ["const godot_rect2 *", "p_self"], + ["const godot_int", "p_margin"], + ["const godot_real", "p_by"] + ] + }, + { + "name": "godot_rect2_abs", + "return_type": "godot_rect2", + "arguments": [ + ["const godot_rect2 *", "p_self"] + ] + }, + { + "name": "godot_string_dedent", + "return_type": "godot_string", + "arguments": [ + ["const godot_string *", "p_self"] + ] + }, + { + "name": "godot_string_trim_prefix", + "return_type": "godot_string", + "arguments": [ + ["const godot_string *", "p_self"], + ["const godot_string *", "p_prefix"] + ] + }, + { + "name": "godot_string_trim_suffix", + "return_type": "godot_string", + "arguments": [ + ["const godot_string *", "p_self"], + ["const godot_string *", "p_suffix"] + ] + }, + { + "name": "godot_string_rstrip", + "return_type": "godot_string", + "arguments": [ + ["const godot_string *", "p_self"], + ["const godot_string *", "p_chars"] + ] + }, + { + "name": "godot_string_rsplit", + "return_type": "godot_pool_string_array", + "arguments": [ + ["const godot_string *", "p_self"], + ["const godot_string *", "p_divisor"], + ["const godot_bool", "p_allow_empty"], + ["const godot_int", "p_maxsplit"] + ] + }, + { "name": "godot_basis_get_quat", "return_type": "godot_quat", "arguments": [ diff --git a/modules/gdnative/include/gdnative/array.h b/modules/gdnative/include/gdnative/array.h index 1e66d133b9..876b8f8e8f 100644 --- a/modules/gdnative/include/gdnative/array.h +++ b/modules/gdnative/include/gdnative/array.h @@ -130,6 +130,14 @@ godot_int GDAPI godot_array_bsearch_custom(godot_array *p_self, const godot_vari void GDAPI godot_array_destroy(godot_array *p_self); +godot_array GDAPI godot_array_duplicate(const godot_array *p_self, const godot_bool p_deep); + +godot_variant GDAPI godot_array_max(const godot_array *p_self); + +godot_variant GDAPI godot_array_min(const godot_array *p_self); + +void GDAPI godot_array_shuffle(godot_array *p_self); + #ifdef __cplusplus } #endif diff --git a/modules/gdnative/include/gdnative/basis.h b/modules/gdnative/include/gdnative/basis.h index ebe2b1125b..6128bf3ac3 100644 --- a/modules/gdnative/include/gdnative/basis.h +++ b/modules/gdnative/include/gdnative/basis.h @@ -127,6 +127,8 @@ godot_basis GDAPI godot_basis_operator_multiply_vector(const godot_basis *p_self godot_basis GDAPI godot_basis_operator_multiply_scalar(const godot_basis *p_self, const godot_real p_b); +godot_basis GDAPI godot_basis_slerp(const godot_basis *p_self, const godot_basis *p_b, const godot_real p_t); + #ifdef __cplusplus } #endif diff --git a/modules/gdnative/include/gdnative/color.h b/modules/gdnative/include/gdnative/color.h index 1f0ac8354d..3007dbc6e3 100644 --- a/modules/gdnative/include/gdnative/color.h +++ b/modules/gdnative/include/gdnative/color.h @@ -81,6 +81,14 @@ godot_string GDAPI godot_color_as_string(const godot_color *p_self); godot_int GDAPI godot_color_to_rgba32(const godot_color *p_self); +godot_int GDAPI godot_color_to_abgr32(const godot_color *p_self); + +godot_int GDAPI godot_color_to_abgr64(const godot_color *p_self); + +godot_int GDAPI godot_color_to_argb64(const godot_color *p_self); + +godot_int GDAPI godot_color_to_rgba64(const godot_color *p_self); + godot_int GDAPI godot_color_to_argb32(const godot_color *p_self); godot_real GDAPI godot_color_gray(const godot_color *p_self); @@ -93,6 +101,12 @@ godot_color GDAPI godot_color_linear_interpolate(const godot_color *p_self, cons godot_color GDAPI godot_color_blend(const godot_color *p_self, const godot_color *p_over); +godot_color GDAPI godot_color_darkened(const godot_color *p_self, const godot_real p_amount); + +godot_color GDAPI godot_color_from_hsv(const godot_color *p_self, const godot_real p_h, const godot_real p_s, const godot_real p_v, const godot_real p_a); + +godot_color GDAPI godot_color_lightened(const godot_color *p_self, const godot_real p_amount); + godot_string GDAPI godot_color_to_html(const godot_color *p_self, const godot_bool p_with_alpha); godot_bool GDAPI godot_color_operator_equal(const godot_color *p_self, const godot_color *p_b); diff --git a/modules/gdnative/include/gdnative/node_path.h b/modules/gdnative/include/gdnative/node_path.h index 2b55e01d13..48fe5b4d3d 100644 --- a/modules/gdnative/include/gdnative/node_path.h +++ b/modules/gdnative/include/gdnative/node_path.h @@ -80,6 +80,8 @@ godot_bool GDAPI godot_node_path_is_empty(const godot_node_path *p_self); godot_bool GDAPI godot_node_path_operator_equal(const godot_node_path *p_self, const godot_node_path *p_b); +godot_node_path godot_node_path_get_as_property_path(const godot_node_path *p_self); + #ifdef __cplusplus } #endif diff --git a/modules/gdnative/include/gdnative/quat.h b/modules/gdnative/include/gdnative/quat.h index b1290f745c..634f486e66 100644 --- a/modules/gdnative/include/gdnative/quat.h +++ b/modules/gdnative/include/gdnative/quat.h @@ -109,6 +109,8 @@ godot_bool GDAPI godot_quat_operator_equal(const godot_quat *p_self, const godot godot_quat GDAPI godot_quat_operator_neg(const godot_quat *p_self); +void GDAPI godot_quat_set_axis_angle(godot_quat *p_self, const godot_vector3 *p_axis, const godot_real p_angle); + #ifdef __cplusplus } #endif diff --git a/modules/gdnative/include/gdnative/rect2.h b/modules/gdnative/include/gdnative/rect2.h index 4adcb73e3d..47c15c80bd 100644 --- a/modules/gdnative/include/gdnative/rect2.h +++ b/modules/gdnative/include/gdnative/rect2.h @@ -77,6 +77,12 @@ godot_bool GDAPI godot_rect2_has_point(const godot_rect2 *p_self, const godot_ve godot_rect2 GDAPI godot_rect2_grow(const godot_rect2 *p_self, const godot_real p_by); +godot_rect2 GDAPI godot_rect2_grow_individual(const godot_rect2 *p_self, const godot_real p_left, const godot_real p_top, const godot_real p_right, const godot_real p_bottom); + +godot_rect2 GDAPI godot_rect2_grow_margin(const godot_rect2 *p_self, const godot_int p_margin, const godot_real p_by); + +godot_rect2 GDAPI godot_rect2_abs(const godot_rect2 *p_self); + godot_rect2 GDAPI godot_rect2_expand(const godot_rect2 *p_self, const godot_vector2 *p_to); godot_bool GDAPI godot_rect2_operator_equal(const godot_rect2 *p_self, const godot_rect2 *p_b); diff --git a/modules/gdnative/include/gdnative/string.h b/modules/gdnative/include/gdnative/string.h index 73245160c1..95ae42a9ec 100644 --- a/modules/gdnative/include/gdnative/string.h +++ b/modules/gdnative/include/gdnative/string.h @@ -246,6 +246,12 @@ godot_bool GDAPI godot_string_is_valid_identifier(const godot_string *p_self); godot_bool GDAPI godot_string_is_valid_integer(const godot_string *p_self); godot_bool GDAPI godot_string_is_valid_ip_address(const godot_string *p_self); +godot_string GDAPI godot_string_dedent(const godot_string *p_self); +godot_string GDAPI godot_string_trim_prefix(const godot_string *p_self, const godot_string *p_prefix); +godot_string GDAPI godot_string_trim_suffix(const godot_string *p_self, const godot_string *p_suffix); +godot_string GDAPI godot_string_rstrip(const godot_string *p_self, const godot_string *p_chars); +godot_pool_string_array GDAPI godot_string_rsplit(const godot_string *p_self, const godot_string *p_divisor, const godot_bool p_allow_empty, const godot_int p_maxsplit); + void GDAPI godot_string_destroy(godot_string *p_self); #ifdef __cplusplus diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp index 2ce92f340d..068e8d2d92 100644 --- a/modules/gdscript/gdscript_editor.cpp +++ b/modules/gdscript/gdscript_editor.cpp @@ -1308,37 +1308,38 @@ static bool _guess_identifier_type(const GDScriptCompletionContext &p_context, c return false; } - // Check ClassDB - if (ClassDB::class_exists(p_identifier)) { - r_type.type.has_type = true; - r_type.type.kind = GDScriptParser::DataType::NATIVE; - r_type.type.native_type = p_identifier; - if (Engine::get_singleton()->has_singleton(p_identifier)) { - r_type.type.is_meta_type = false; - r_type.value = Engine::get_singleton()->get_singleton_object(p_identifier); - } else { - r_type.type.is_meta_type = true; - int idx = GDScriptLanguage::get_singleton()->get_global_map()[p_identifier]; - r_type.value = GDScriptLanguage::get_singleton()->get_global_array()[idx]; + for (int i = 0; i < 2; i++) { + StringName target_id; + switch (i) { + case 0: + // Check ClassDB + target_id = p_identifier; + break; + case 1: + // ClassDB again for underscore-prefixed classes + target_id = String("_") + p_identifier; + break; } - return true; - } - // ClassDB again for underscore-prefixed classes - StringName under_id = String("_") + p_identifier; - if (ClassDB::class_exists(under_id)) { - r_type.type.has_type = true; - r_type.type.kind = GDScriptParser::DataType::NATIVE; - r_type.type.native_type = p_identifier; - if (Engine::get_singleton()->has_singleton(p_identifier)) { - r_type.type.is_meta_type = false; - r_type.value = Engine::get_singleton()->get_singleton_object(p_identifier); - } else { - r_type.type.is_meta_type = true; - int idx = GDScriptLanguage::get_singleton()->get_global_map()[p_identifier]; - r_type.value = GDScriptLanguage::get_singleton()->get_global_array()[idx]; + if (ClassDB::class_exists(target_id)) { + r_type.type.has_type = true; + r_type.type.kind = GDScriptParser::DataType::NATIVE; + r_type.type.native_type = target_id; + if (Engine::get_singleton()->has_singleton(target_id)) { + r_type.type.is_meta_type = false; + r_type.value = Engine::get_singleton()->get_singleton_object(target_id); + } else { + r_type.type.is_meta_type = true; + const Map<StringName, int>::Element *target_elem = GDScriptLanguage::get_singleton()->get_global_map().find(target_id); + // Check because classes like EditorNode are in ClassDB by now, but unknown to GDScript + if (!target_elem) { + return false; + } + int idx = target_elem->get(); + r_type.value = GDScriptLanguage::get_singleton()->get_global_array()[idx]; + } + return true; } - return true; } // Check autoload singletons diff --git a/modules/mono/glue/Managed/Files/GD.cs b/modules/mono/glue/Managed/Files/GD.cs index e4818e186c..8c1a5a6ee8 100644 --- a/modules/mono/glue/Managed/Files/GD.cs +++ b/modules/mono/glue/Managed/Files/GD.cs @@ -70,6 +70,16 @@ namespace Godot return ResourceLoader.Load<T>(path); } + public static void LogError(string message) + { + godot_icall_GD_logerror(message); + } + + public static void LogWarning(string message) + { + godot_icall_GD_logwarning(message); + } + public static void Print(params object[] what) { godot_icall_GD_print(what); @@ -238,5 +248,11 @@ namespace Godot [MethodImpl(MethodImplOptions.InternalCall)] internal extern static string godot_icall_GD_var2str(object var); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static void godot_icall_GD_logerror(string type); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static void godot_icall_GD_logwarning(string type); } } diff --git a/modules/mono/glue/gd_glue.cpp b/modules/mono/glue/gd_glue.cpp index 051f42b966..6a5430489e 100644 --- a/modules/mono/glue/gd_glue.cpp +++ b/modules/mono/glue/gd_glue.cpp @@ -157,6 +157,14 @@ bool godot_icall_GD_type_exists(MonoString *p_type) { return ClassDB::class_exists(GDMonoMarshal::mono_string_to_godot(p_type)); } +void godot_icall_GD_logerror(MonoString *p_str) { + ERR_PRINTS(GDMonoMarshal::mono_string_to_godot(p_str)); +} + +void godot_icall_GD_logwarning(MonoString *p_str) { + WARN_PRINTS(GDMonoMarshal::mono_string_to_godot(p_str)); +} + MonoArray *godot_icall_GD_var2bytes(MonoObject *p_var) { Variant var = GDMonoMarshal::mono_object_to_variant(p_var); @@ -186,6 +194,8 @@ void godot_register_gd_icalls() { mono_add_internal_call("Godot.GD::godot_icall_GD_convert", (void *)godot_icall_GD_convert); mono_add_internal_call("Godot.GD::godot_icall_GD_hash", (void *)godot_icall_GD_hash); mono_add_internal_call("Godot.GD::godot_icall_GD_instance_from_id", (void *)godot_icall_GD_instance_from_id); + mono_add_internal_call("Godot.GD::godot_icall_GD_logerror", (void *)godot_icall_GD_logerror); + mono_add_internal_call("Godot.GD::godot_icall_GD_logwarning", (void *)godot_icall_GD_logwarning); mono_add_internal_call("Godot.GD::godot_icall_GD_print", (void *)godot_icall_GD_print); mono_add_internal_call("Godot.GD::godot_icall_GD_printerr", (void *)godot_icall_GD_printerr); mono_add_internal_call("Godot.GD::godot_icall_GD_printraw", (void *)godot_icall_GD_printraw); diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp index 7fdd7fe446..a80a015ed3 100644 --- a/modules/visual_script/visual_script_editor.cpp +++ b/modules/visual_script/visual_script_editor.cpp @@ -3018,11 +3018,15 @@ void VisualScriptEditor::_node_filter_changed(const String &p_text) { void VisualScriptEditor::_notification(int p_what) { - if (p_what == NOTIFICATION_READY) { + if (p_what == NOTIFICATION_READY || (p_what == NOTIFICATION_THEME_CHANGED && is_visible_in_tree())) { + node_filter->set_right_icon(Control::get_icon("Search", "EditorIcons")); node_filter->set_clear_button_enabled(true); - variable_editor->connect("changed", this, "_update_members"); - signal_editor->connect("changed", this, "_update_members"); + + if (p_what == NOTIFICATION_READY) { + variable_editor->connect("changed", this, "_update_members"); + signal_editor->connect("changed", this, "_update_members"); + } Ref<Theme> tm = EditorNode::get_singleton()->get_theme_base()->get_theme(); @@ -3056,8 +3060,12 @@ void VisualScriptEditor::_notification(int p_what) { node_styles[E->get().first] = frame_style; } } - } - if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { + + if (is_visible_in_tree()) { + _update_members(); + _update_graph(); + } + } else if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { left_vsplit->set_visible(is_visible_in_tree()); } } diff --git a/platform/android/build.gradle.template b/platform/android/build.gradle.template index 1603ea70d9..18ffc74fc3 100644 --- a/platform/android/build.gradle.template +++ b/platform/android/build.gradle.template @@ -14,9 +14,9 @@ apply plugin: 'com.android.application' allprojects { repositories { - jcenter() mavenCentral() google() + jcenter() $$GRADLE_REPOSITORY_URLS$$ } } diff --git a/platform/android/detect.py b/platform/android/detect.py index 953a2fa6d2..e4cab2fb23 100644 --- a/platform/android/detect.py +++ b/platform/android/detect.py @@ -186,7 +186,7 @@ def configure(env): env.PrependENVPath('PATH', tools_path) ccache_path = os.environ.get("CCACHE") - if ccache_path == None: + if ccache_path is None: env['CC'] = compiler_path + '/clang' env['CXX'] = compiler_path + '/clang++' else: @@ -293,7 +293,7 @@ def configure(env): # Return NDK version string in source.properties (adapted from the Chromium project). def get_ndk_version(path): - if path == None: + if path is None: return None prop_file_path = os.path.join(path, "source.properties") try: diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp index 3b503e2657..edb84cce07 100644 --- a/platform/android/export/export.cpp +++ b/platform/android/export/export.cpp @@ -395,7 +395,7 @@ class EditorExportAndroid : public EditorExportPlatform { return aname; } - String get_package_name(const String &p_package) { + String get_package_name(const String &p_package) const { String pname = p_package; String basename = ProjectSettings::get_singleton()->get("application/config/name"); @@ -420,6 +420,70 @@ class EditorExportAndroid : public EditorExportPlatform { return pname; } + bool is_package_name_valid(const String &p_package, String *r_error = NULL) const { + + String pname = p_package; + + if (pname.length() == 0) { + if (r_error) { + *r_error = "Package name is missing."; + } + return false; + } + + int segments = 0; + bool first = true; + for (int i = 0; i < pname.length(); i++) { + CharType c = pname[i]; + if (first && c == '.') { + if (r_error) { + *r_error = "Package segments must be of non-zero length."; + } + return false; + } + if (c == '.') { + segments++; + first = true; + continue; + } + if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_')) { + if (r_error) { + *r_error = "The character '" + String::chr(c) + "' is not allowed in Android application package names."; + } + return false; + } + if (first && (c >= '0' && c <= '9')) { + if (r_error) { + *r_error = "A digit cannot be the first character in a package segment."; + } + return false; + } + if (first && c == '_') { + if (r_error) { + *r_error = "The character '" + String::chr(c) + "' cannot be the first character in a package segment."; + } + return false; + } + first = false; + } + + if (segments == 0) { + if (r_error) { + *r_error = "The package must have at least one '.' separator."; + } + return false; + } + + if (first) { + if (r_error) { + *r_error = "Package segments must be of non-zero length."; + } + return false; + } + + return true; + } + static bool _should_compress_asset(const String &p_path, const Vector<uint8_t> &p_data) { /* @@ -1382,6 +1446,15 @@ public: } } + String pn = p_preset->get("package/unique_name"); + String pn_err; + + if (!is_package_name_valid(get_package_name(pn), &pn_err)) { + + valid = false; + err += "Invalid package name - " + pn_err + "\n"; + } + r_error = err; return valid; } diff --git a/platform/android/java/src/org/godotengine/godot/Godot.java b/platform/android/java/src/org/godotengine/godot/Godot.java index ab37f7a02c..88194f00d1 100644 --- a/platform/android/java/src/org/godotengine/godot/Godot.java +++ b/platform/android/java/src/org/godotengine/godot/Godot.java @@ -279,7 +279,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC // ...add to FrameLayout layout.addView(edittext); - mView = new GodotView(getApplication(), io, use_gl3, use_32_bits, use_debug_opengl,this); + mView = new GodotView(getApplication(), io, use_gl3, use_32_bits, use_debug_opengl, this); layout.addView(mView, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); edittext.setView(mView); io.setEdit(edittext); diff --git a/platform/android/java/src/org/godotengine/godot/GodotView.java b/platform/android/java/src/org/godotengine/godot/GodotView.java index 181ffc3b4b..4cb4db33de 100644 --- a/platform/android/java/src/org/godotengine/godot/GodotView.java +++ b/platform/android/java/src/org/godotengine/godot/GodotView.java @@ -86,7 +86,7 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener { private Godot activity; private InputManagerCompat mInputManager; - public GodotView(Context context, GodotIO p_io, boolean p_use_gl3, boolean p_use_32_bits, boolean p_use_debug_opengl,Godot p_activity) { + public GodotView(Context context, GodotIO p_io, boolean p_use_gl3, boolean p_use_32_bits, boolean p_use_debug_opengl, Godot p_activity) { super(context); ctx = context; io = p_io; @@ -204,48 +204,65 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener { return i; } } - onInputDeviceAdded(device_id); - return joy_devices.size() - 1; + + return -1; } @Override public void onInputDeviceAdded(int deviceId) { - joystick joy = new joystick(); - joy.device_id = deviceId; - final int id = joy_devices.size(); - InputDevice device = mInputManager.getInputDevice(deviceId); - final String name = device.getName(); - joy.name = device.getName(); - joy.axes = new ArrayList<InputDevice.MotionRange>(); - joy.hats = new ArrayList<InputDevice.MotionRange>(); - List<InputDevice.MotionRange> ranges = device.getMotionRanges(); - Collections.sort(ranges, new RangeComparator()); - for (InputDevice.MotionRange range : ranges) { - if (range.getAxis() == MotionEvent.AXIS_HAT_X || range.getAxis() == MotionEvent.AXIS_HAT_Y) { - joy.hats.add(range); - } else { - joy.axes.add(range); + int id = find_joy_device(deviceId); + + // Check if the device has not been already added + if (id < 0) { + InputDevice device = mInputManager.getInputDevice(deviceId); + + id = joy_devices.size(); + + joystick joy = new joystick(); + joy.device_id = deviceId; + joy.name = device.getName(); + joy.axes = new ArrayList<InputDevice.MotionRange>(); + joy.hats = new ArrayList<InputDevice.MotionRange>(); + + List<InputDevice.MotionRange> ranges = device.getMotionRanges(); + Collections.sort(ranges, new RangeComparator()); + + for (InputDevice.MotionRange range : ranges) { + if (range.getAxis() == MotionEvent.AXIS_HAT_X || range.getAxis() == MotionEvent.AXIS_HAT_Y) { + joy.hats.add(range); + } else { + joy.axes.add(range); + } } + + joy_devices.add(joy); + + final int device_id = id; + final String name = joy.name; + queueEvent(new Runnable() { + @Override + public void run() { + GodotLib.joyconnectionchanged(device_id, true, name); + } + }); } - joy_devices.add(joy); - queueEvent(new Runnable() { - @Override - public void run() { - GodotLib.joyconnectionchanged(id, true, name); - } - }); } @Override public void onInputDeviceRemoved(int deviceId) { - final int id = find_joy_device(deviceId); - joy_devices.remove(id); - queueEvent(new Runnable() { - @Override - public void run() { - GodotLib.joyconnectionchanged(id, false, ""); - } - }); + final int device_id = find_joy_device(deviceId); + + // Check if the evice has not been already removed + if (device_id > -1) { + joy_devices.remove(device_id); + + queueEvent(new Runnable() { + @Override + public void run() { + GodotLib.joyconnectionchanged(device_id, false, ""); + } + }); + } } @Override @@ -266,15 +283,18 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener { if ((source & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK || (source & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD || (source & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD) { final int button = get_godot_button(keyCode); - final int device = find_joy_device(event.getDeviceId()); + final int device_id = find_joy_device(event.getDeviceId()); - queueEvent(new Runnable() { - @Override - public void run() { - GodotLib.joybutton(device, button, false); - } - }); - return true; + // Check if the device exists + if (device_id > -1) { + queueEvent(new Runnable() { + @Override + public void run() { + GodotLib.joybutton(device_id, button, false); + } + }); + return true; + } } else { final int chr = event.getUnicodeChar(0); queueEvent(new Runnable() { @@ -284,6 +304,7 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener { } }); }; + return super.onKeyUp(keyCode, event); }; @@ -308,18 +329,20 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener { if (event.getRepeatCount() > 0) // ignore key echo return true; - final int button = get_godot_button(keyCode); - final int device = find_joy_device(event.getDeviceId()); - //Log.e(TAG, String.format("joy button down! button %x, %d, device %d", keyCode, button, device)); - queueEvent(new Runnable() { - @Override - public void run() { - GodotLib.joybutton(device, button, true); - } - }); - return true; + final int button = get_godot_button(keyCode); + final int device_id = find_joy_device(event.getDeviceId()); + // Check if the device exists + if (device_id > -1) { + queueEvent(new Runnable() { + @Override + public void run() { + GodotLib.joybutton(device_id, button, true); + } + }); + return true; + } } else { final int chr = event.getUnicodeChar(0); queueEvent(new Runnable() { @@ -329,6 +352,7 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener { } }); }; + return super.onKeyDown(keyCode, event); } @@ -338,33 +362,35 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener { if ((event.getSource() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK && event.getAction() == MotionEvent.ACTION_MOVE) { final int device_id = find_joy_device(event.getDeviceId()); - joystick joy = joy_devices.get(device_id); - for (int i = 0; i < joy.axes.size(); i++) { - InputDevice.MotionRange range = joy.axes.get(i); - final float value = (event.getAxisValue(range.getAxis()) - range.getMin()) / range.getRange() * 2.0f - 1.0f; - //Log.e(TAG, String.format("axis event: %d, value %f", i, value)); - final int idx = i; - queueEvent(new Runnable() { - @Override - public void run() { - GodotLib.joyaxis(device_id, idx, value); - } - }); - } + // Check if the device exists + if (device_id > -1) { + joystick joy = joy_devices.get(device_id); + + for (int i = 0; i < joy.axes.size(); i++) { + InputDevice.MotionRange range = joy.axes.get(i); + final float value = (event.getAxisValue(range.getAxis()) - range.getMin()) / range.getRange() * 2.0f - 1.0f; + final int idx = i; + queueEvent(new Runnable() { + @Override + public void run() { + GodotLib.joyaxis(device_id, idx, value); + } + }); + } - for (int i = 0; i < joy.hats.size(); i += 2) { - final int hatX = Math.round(event.getAxisValue(joy.hats.get(i).getAxis())); - final int hatY = Math.round(event.getAxisValue(joy.hats.get(i + 1).getAxis())); - //Log.e(TAG, String.format("HAT EVENT %d, %d", hatX, hatY)); - queueEvent(new Runnable() { - @Override - public void run() { - GodotLib.joyhat(device_id, hatX, hatY); - } - }); + for (int i = 0; i < joy.hats.size(); i += 2) { + final int hatX = Math.round(event.getAxisValue(joy.hats.get(i).getAxis())); + final int hatY = Math.round(event.getAxisValue(joy.hats.get(i + 1).getAxis())); + queueEvent(new Runnable() { + @Override + public void run() { + GodotLib.joyhat(device_id, hatX, hatY); + } + }); + } + return true; } - return true; }; return super.onGenericMotionEvent(event); @@ -408,9 +434,9 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener { setRenderer(new Renderer()); } - private static final int _EGL_CONTEXT_FLAGS_KHR = 0x30FC; - private static final int _EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR= 0x00000001; - + private static final int _EGL_CONTEXT_FLAGS_KHR = 0x30FC; + private static final int _EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR = 0x00000001; + private static class ContextFactory implements GLSurfaceView.EGLContextFactory { private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098; public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig) { @@ -422,9 +448,9 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener { checkEglError("Before eglCreateContext", egl); EGLContext context; if (use_debug_opengl) { - int[] attrib_list2 = { EGL_CONTEXT_CLIENT_VERSION, 2,_EGL_CONTEXT_FLAGS_KHR,_EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR, EGL10.EGL_NONE }; - int[] attrib_list3 = { EGL_CONTEXT_CLIENT_VERSION, 3,_EGL_CONTEXT_FLAGS_KHR,_EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR, EGL10.EGL_NONE }; - context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, use_gl3 ? attrib_list3 : attrib_list2); + int[] attrib_list2 = { EGL_CONTEXT_CLIENT_VERSION, 2, _EGL_CONTEXT_FLAGS_KHR, _EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR, EGL10.EGL_NONE }; + int[] attrib_list3 = { EGL_CONTEXT_CLIENT_VERSION, 3, _EGL_CONTEXT_FLAGS_KHR, _EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR, EGL10.EGL_NONE }; + context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, use_gl3 ? attrib_list3 : attrib_list2); } else { int[] attrib_list2 = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE }; int[] attrib_list3 = { EGL_CONTEXT_CLIENT_VERSION, 3, EGL10.EGL_NONE }; diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index 8e050c1d27..96ff226402 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -39,7 +39,7 @@ #include "file_access_android.h" #include "main/main.h" #include "servers/visual/visual_server_raster.h" -//#include "servers/visual/visual_server_wrap_mt.h" +#include "servers/visual/visual_server_wrap_mt.h" #ifdef ANDROID_NATIVE_ACTIVITY #include "dir_access_android.h" @@ -183,13 +183,11 @@ Error OS_Android::initialize(const VideoMode &p_desired, int p_video_driver, int video_driver_index = p_video_driver; visual_server = memnew(VisualServerRaster); - /* if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) { - + if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) { visual_server = memnew(VisualServerWrapMT(visual_server, false)); - };*/ + } visual_server->init(); - // visual_server->cursor_set_visible(false, 0); AudioDriverManager::initialize(p_audio_driver); diff --git a/platform/haiku/os_haiku.cpp b/platform/haiku/os_haiku.cpp index c80365f1f3..f9f12af817 100644 --- a/platform/haiku/os_haiku.cpp +++ b/platform/haiku/os_haiku.cpp @@ -117,16 +117,13 @@ Error OS_Haiku::initialize(const VideoMode &p_desired, int p_video_driver, int p #endif - visual_server = memnew(VisualServerRaster()); - - ERR_FAIL_COND_V(!visual_server, ERR_UNAVAILABLE); - - // TODO: enable multithreaded VS - /* + visual_server = memnew(VisualServerRaster); + // FIXME: Reimplement threaded rendering if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) { - visual_server = memnew(VisualServerWrapMT(visual_server, get_render_thread_mode() == RENDER_SEPARATE_THREAD)); + visual_server = memnew(VisualServerWrapMT(visual_server, false)); } - */ + + ERR_FAIL_COND_V(!visual_server, ERR_UNAVAILABLE); video_driver_index = p_video_driver; diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py index b13a1e9643..417571f6f3 100644 --- a/platform/iphone/detect.py +++ b/platform/iphone/detect.py @@ -87,7 +87,7 @@ def configure(env): s_compiler_path = '$IPHONEPATH/Developer/usr/bin/' ccache_path = os.environ.get("CCACHE") - if ccache_path == None: + if ccache_path is None: env['CC'] = compiler_path + 'clang' env['CXX'] = compiler_path + 'clang++' env['S_compiler'] = s_compiler_path + 'gcc' diff --git a/platform/iphone/os_iphone.cpp b/platform/iphone/os_iphone.cpp index addef61ec7..e996a5905b 100644 --- a/platform/iphone/os_iphone.cpp +++ b/platform/iphone/os_iphone.cpp @@ -34,7 +34,7 @@ #include "drivers/gles3/rasterizer_gles3.h" #include "servers/visual/visual_server_raster.h" -//#include "servers/visual/visual_server_wrap_mt.h" +#include "servers/visual/visual_server_wrap_mt.h" #include "main/main.h" @@ -107,13 +107,11 @@ Error OSIPhone::initialize(const VideoMode &p_desired, int p_video_driver, int p RasterizerGLES3::register_config(); RasterizerGLES3::make_current(); - visual_server = memnew(VisualServerRaster()); - /* - FIXME: Reimplement threaded rendering? Or remove? + visual_server = memnew(VisualServerRaster); + // FIXME: Reimplement threaded rendering if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) { visual_server = memnew(VisualServerWrapMT(visual_server, false)); - }; - */ + } visual_server->init(); //visual_server->cursor_set_visible(false, 0); diff --git a/platform/javascript/detect.py b/platform/javascript/detect.py index 17b31f8d73..cf85c3df7f 100644 --- a/platform/javascript/detect.py +++ b/platform/javascript/detect.py @@ -128,6 +128,10 @@ def configure(env): # us since we don't know requirements at compile-time. env.Append(LINKFLAGS=['-s', 'ALLOW_MEMORY_GROWTH=1']) + # Since we use both memory growth and MEMFS preloading, + # this avoids unecessary copying on start-up. + env.Append(LINKFLAGS=['--no-heap-copy']) + # This setting just makes WebGL 2 APIs available, it does NOT disable WebGL 1. env.Append(LINKFLAGS=['-s', 'USE_WEBGL2=1']) diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp index 7c7aeac980..9250ca4903 100644 --- a/platform/javascript/os_javascript.cpp +++ b/platform/javascript/os_javascript.cpp @@ -862,6 +862,24 @@ void OS_JavaScript::finalize() { // Miscellaneous +Error OS_JavaScript::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr) { + + ERR_EXPLAIN("OS::execute() is not available on the HTML5 platform"); + ERR_FAIL_V(ERR_UNAVAILABLE); +} + +Error OS_JavaScript::kill(const ProcessID &p_pid) { + + ERR_EXPLAIN("OS::kill() is not available on the HTML5 platform"); + ERR_FAIL_V(ERR_UNAVAILABLE); +} + +int OS_JavaScript::get_process_id() const { + + ERR_EXPLAIN("OS::get_process_id() is not available on the HTML5 platform"); + ERR_FAIL_V(0); +} + extern "C" EMSCRIPTEN_KEEPALIVE void send_notification(int p_notification) { if (p_notification == MainLoop::NOTIFICATION_WM_MOUSE_ENTER || p_notification == MainLoop::NOTIFICATION_WM_MOUSE_EXIT) { diff --git a/platform/javascript/os_javascript.h b/platform/javascript/os_javascript.h index 84075898ac..79dac5940f 100644 --- a/platform/javascript/os_javascript.h +++ b/platform/javascript/os_javascript.h @@ -133,6 +133,10 @@ public: void run_async(); bool main_loop_iterate(); + virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id = NULL, String *r_pipe = NULL, int *r_exitcode = NULL, bool read_stderr = false); + virtual Error kill(const ProcessID &p_pid); + virtual int get_process_id() const; + virtual void alert(const String &p_alert, const String &p_title = "ALERT!"); virtual void set_window_title(const String &p_title); virtual void set_icon(const Ref<Image> &p_icon); diff --git a/platform/osx/detect.py b/platform/osx/detect.py index 8a0883eca3..c5bd64b15c 100644 --- a/platform/osx/detect.py +++ b/platform/osx/detect.py @@ -89,7 +89,7 @@ def configure(env): basecmd = root + "/target/bin/x86_64-apple-" + env["osxcross_sdk"] + "-" ccache_path = os.environ.get("CCACHE") - if ccache_path == None: + if ccache_path is None: env['CC'] = basecmd + "cc" env['CXX'] = basecmd + "c++" else: diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h index 6fd52f09d1..546c88e74a 100644 --- a/platform/osx/os_osx.h +++ b/platform/osx/os_osx.h @@ -74,8 +74,12 @@ public: IP_Unix *ip_unix; +#ifdef COREAUDIO_ENABLED AudioDriverCoreAudio audio_driver; +#endif +#ifdef COREMIDI_ENABLED MIDIDriverCoreMidi midi_driver; +#endif InputDefault *input; JoypadOSX *joypad_osx; diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index 70b49805d2..5b60e1b633 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -331,7 +331,8 @@ static Vector2 get_mouse_pos(NSPoint locationInWindow, CGFloat backingScaleFacto get_mouse_pos( [OS_OSX::singleton->window_object mouseLocationOutsideOfEventStream], [OS_OSX::singleton->window_view backingScaleFactor]); - OS_OSX::singleton->input->set_mouse_position(Point2(mouse_x, mouse_y)); + if (OS_OSX::singleton->input) + OS_OSX::singleton->input->set_mouse_position(Point2(mouse_x, mouse_y)); if (OS_OSX::singleton->get_main_loop()) OS_OSX::singleton->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN); @@ -1384,7 +1385,6 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a visual_server = memnew(VisualServerRaster); if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) { - visual_server = memnew(VisualServerWrapMT(visual_server, get_render_thread_mode() == RENDER_SEPARATE_THREAD)); } @@ -1408,7 +1408,9 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a void OS_OSX::finalize() { +#ifdef COREMIDI_ENABLED midi_driver.close(); +#endif CFNotificationCenterRemoveObserver(CFNotificationCenterGetDistributedCenter(), NULL, kTISNotifySelectedKeyboardInputSourceChanged, NULL); CGDisplayRemoveReconfigurationCallback(displays_arrangement_changed, NULL); @@ -2725,7 +2727,9 @@ OS_OSX::OS_OSX() { [NSApp sendEvent:event]; } +#ifdef COREAUDIO_ENABLED AudioDriverManager::add_driver(&audio_driver); +#endif } bool OS_OSX::_check_internal_feature_support(const String &p_feature) { diff --git a/platform/server/SCsub b/platform/server/SCsub index c9082f9b3a..51fd05a87e 100644 --- a/platform/server/SCsub +++ b/platform/server/SCsub @@ -1,10 +1,21 @@ #!/usr/bin/env python +import os +import platform +import sys + Import('env') common_server = [\ "os_server.cpp",\ - "#platform/x11/crash_handler_x11.cpp", - "#platform/x11/power_x11.cpp", ] + +if sys.platform == "darwin": + common_server.append("#platform/osx/crash_handler_osx.mm") + common_server.append("#platform/osx/power_osx.cpp") + common_server.append("#platform/osx/sem_osx.cpp") +else: + common_server.append("#platform/x11/crash_handler_x11.cpp") + common_server.append("#platform/x11/power_x11.cpp") + prog = env.add_program('#bin/godot_server', ['godot_server.cpp'] + common_server) diff --git a/platform/server/detect.py b/platform/server/detect.py index 597a2ff6a0..0b23e9c649 100644 --- a/platform/server/detect.py +++ b/platform/server/detect.py @@ -11,9 +11,15 @@ def get_name(): return "Server" +def get_program_suffix(): + if (sys.platform == "darwin"): + return "osx" + return "x11" + + def can_build(): - if (os.name != "posix" or sys.platform == "darwin"): + if (os.name != "posix"): return False return True @@ -147,6 +153,10 @@ def configure(env): env.Append(CPPPATH=['#platform/server']) env.Append(CPPFLAGS=['-DSERVER_ENABLED', '-DUNIX_ENABLED']) + + if (platform.system() == "Darwin"): + env.Append(LINKFLAGS=['-framework', 'Cocoa', '-framework', 'Carbon', '-lz', '-framework', 'IOKit']) + env.Append(LIBS=['pthread']) if (platform.system() == "Linux"): diff --git a/platform/server/os_server.cpp b/platform/server/os_server.cpp index 6a7038e946..60f20d6009 100644 --- a/platform/server/os_server.cpp +++ b/platform/server/os_server.cpp @@ -68,6 +68,10 @@ void OS_Server::initialize_core() { crash_handler.initialize(); OS_Unix::initialize_core(); + +#ifdef __APPLE__ + SemaphoreOSX::make_default(); +#endif } Error OS_Server::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) { @@ -87,7 +91,11 @@ Error OS_Server::initialize(const VideoMode &p_desired, int p_video_driver, int input = memnew(InputDefault); +#ifdef __APPLE__ + power_manager = memnew(power_osx); +#else power_manager = memnew(PowerX11); +#endif _ensure_user_data_dir(); diff --git a/platform/server/os_server.h b/platform/server/os_server.h index 07d70e5236..0367ec3db9 100644 --- a/platform/server/os_server.h +++ b/platform/server/os_server.h @@ -34,8 +34,14 @@ #include "drivers/rtaudio/audio_driver_rtaudio.h" #include "drivers/unix/os_unix.h" #include "main/input_default.h" +#ifdef __APPLE__ +#include "platform/osx/crash_handler_osx.h" +#include "platform/osx/power_osx.h" +#include "platform/osx/sem_osx.h" +#else #include "platform/x11/crash_handler_x11.h" #include "platform/x11/power_x11.h" +#endif #include "servers/audio_server.h" #include "servers/visual/rasterizer.h" #include "servers/visual_server.h" @@ -61,7 +67,11 @@ class OS_Server : public OS_Unix { InputDefault *input; +#ifdef __APPLE__ + power_osx *power_manager; +#else PowerX11 *power_manager; +#endif CrashHandler crash_handler; diff --git a/platform/server/platform_config.h b/platform/server/platform_config.h index 2fa8eda337..26ba8f26c6 100644 --- a/platform/server/platform_config.h +++ b/platform/server/platform_config.h @@ -28,10 +28,13 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifdef __linux__ +#if defined(__linux__) || defined(__APPLE__) #include <alloca.h> #endif #if defined(__FreeBSD__) || defined(__OpenBSD__) #include <stdlib.h> #define PTHREAD_BSD_SET_NAME #endif +#ifdef __APPLE__ +#define PTHREAD_RENAME_SELF +#endif diff --git a/platform/uwp/detect.py b/platform/uwp/detect.py index 559f23ca5b..f25b9ba9cd 100644 --- a/platform/uwp/detect.py +++ b/platform/uwp/detect.py @@ -17,7 +17,7 @@ def can_build(): # building natively on windows! if (os.getenv("VSINSTALLDIR")): - if (os.getenv("ANGLE_SRC_PATH") == None): + if (os.getenv("ANGLE_SRC_PATH") is None): return False return True diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp index 6410378593..2209ecb20e 100644 --- a/platform/uwp/os_uwp.cpp +++ b/platform/uwp/os_uwp.cpp @@ -295,13 +295,10 @@ Error OSUWP::initialize(const VideoMode &p_desired, int p_video_driver, int p_au set_video_mode(vm); visual_server = memnew(VisualServerRaster); - // FIXME: Reimplement threaded rendering? Or remove? - /* + // FIXME: Reimplement threaded rendering if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) { - - visual_server = memnew(VisualServerWrapMT(visual_server, get_render_thread_mode() == RENDER_SEPARATE_THREAD)); + visual_server = memnew(VisualServerWrapMT(visual_server, false)); } - */ visual_server->init(); input = memnew(InputDefault); diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 3bbffd8fb7..f8705c4bff 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -1334,24 +1334,9 @@ Error OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int visual_server = memnew(VisualServerRaster); if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) { - visual_server = memnew(VisualServerWrapMT(visual_server, get_render_thread_mode() == RENDER_SEPARATE_THREAD)); } - /* - DEVMODE dmScreenSettings; // Device Mode - memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); // Makes Sure Memory's Cleared - dmScreenSettings.dmSize=sizeof(dmScreenSettings); // Size Of The Devmode Structure - dmScreenSettings.dmPelsWidth = width; // Selected Screen Width - dmScreenSettings.dmPelsHeight = height; // Selected Screen Height - dmScreenSettings.dmBitsPerPel = bits; // Selected Bits Per Pixel - dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT; - if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL) - - - - - */ visual_server->init(); input = memnew(InputDefault); diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index 88c2c8aec6..8ba5833796 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -342,12 +342,12 @@ Error OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_a context_gl->set_use_vsync(current_videomode.use_vsync); #endif - visual_server = memnew(VisualServerRaster); + visual_server = memnew(VisualServerRaster); if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) { - visual_server = memnew(VisualServerWrapMT(visual_server, get_render_thread_mode() == RENDER_SEPARATE_THREAD)); } + if (current_videomode.maximized) { current_videomode.maximized = false; set_window_maximized(true); diff --git a/scene/2d/path_2d.cpp b/scene/2d/path_2d.cpp index cdb208e6cd..4276918f53 100644 --- a/scene/2d/path_2d.cpp +++ b/scene/2d/path_2d.cpp @@ -63,6 +63,10 @@ bool Path2D::_edit_use_rect() const { bool Path2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { + if (curve.is_null()) { + return false; + } + for (int i = 0; i < curve->get_point_count(); i++) { Vector2 s[2]; s[0] = curve->get_point_position(i); diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index d0bebd3354..60074abb29 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -32,8 +32,11 @@ #include "core/core_string_names.h" #include "core/engine.h" +#include "core/list.h" #include "core/math/math_funcs.h" #include "core/method_bind_ext.gen.inc" +#include "core/object.h" +#include "core/rid.h" #include "scene/scene_string_names.h" void PhysicsBody2D::_notification(int p_what) { @@ -65,6 +68,8 @@ void PhysicsBody2D::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_layers", "mask"), &PhysicsBody2D::_set_layers); ClassDB::bind_method(D_METHOD("_get_layers"), &PhysicsBody2D::_get_layers); + + ClassDB::bind_method(D_METHOD("get_collision_exceptions"), &PhysicsBody2D::get_collision_exceptions); ClassDB::bind_method(D_METHOD("add_collision_exception_with", "body"), &PhysicsBody2D::add_collision_exception_with); ClassDB::bind_method(D_METHOD("remove_collision_exception_with", "body"), &PhysicsBody2D::remove_collision_exception_with); ADD_PROPERTY(PropertyInfo(Variant::INT, "layers", PROPERTY_HINT_LAYERS_2D_PHYSICS, "", 0), "_set_layers", "_get_layers"); //for backwards compat @@ -134,6 +139,20 @@ PhysicsBody2D::PhysicsBody2D(Physics2DServer::BodyMode p_mode) : set_pickable(false); } +Array PhysicsBody2D::get_collision_exceptions() { + List<RID> exceptions; + Physics2DServer::get_singleton()->body_get_collision_exceptions(get_rid(), &exceptions); + Array ret; + for (List<RID>::Element *E = exceptions.front(); E; E = E->next()) { + RID body = E->get(); + ObjectID instance_id = Physics2DServer::get_singleton()->body_get_object_instance_id(body); + Object *obj = ObjectDB::get_instance(instance_id); + PhysicsBody2D *physics_body = Object::cast_to<PhysicsBody2D>(obj); + ret.append(physics_body); + } + return ret; +} + void PhysicsBody2D::add_collision_exception_with(Node *p_node) { ERR_FAIL_NULL(p_node); diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h index 29befb0375..ddd55f7b7f 100644 --- a/scene/2d/physics_body_2d.h +++ b/scene/2d/physics_body_2d.h @@ -67,6 +67,7 @@ public: void set_collision_layer_bit(int p_bit, bool p_value); bool get_collision_layer_bit(int p_bit) const; + Array get_collision_exceptions(); void add_collision_exception_with(Node *p_node); //must be physicsbody void remove_collision_exception_with(Node *p_node); diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index 0fb0869979..970e8cf1ee 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -32,7 +32,10 @@ #include "core/core_string_names.h" #include "core/engine.h" +#include "core/list.h" #include "core/method_bind_ext.gen.inc" +#include "core/object.h" +#include "core/rid.h" #include "scene/scene_string_names.h" #ifdef TOOLS_ENABLED @@ -108,6 +111,20 @@ bool PhysicsBody::get_collision_layer_bit(int p_bit) const { return get_collision_layer() & (1 << p_bit); } +Array PhysicsBody::get_collision_exceptions() { + List<RID> exceptions; + PhysicsServer::get_singleton()->body_get_collision_exceptions(get_rid(), &exceptions); + Array ret; + for (List<RID>::Element *E = exceptions.front(); E; E = E->next()) { + RID body = E->get(); + ObjectID instance_id = PhysicsServer::get_singleton()->body_get_object_instance_id(body); + Object *obj = ObjectDB::get_instance(instance_id); + PhysicsBody *physics_body = Object::cast_to<PhysicsBody>(obj); + ret.append(physics_body); + } + return ret; +} + void PhysicsBody::add_collision_exception_with(Node *p_node) { ERR_FAIL_NULL(p_node); @@ -289,6 +306,7 @@ void StaticBody::_bind_methods() { ClassDB::bind_method(D_METHOD("_reload_physics_characteristics"), &StaticBody::_reload_physics_characteristics); + ClassDB::bind_method(D_METHOD("get_collision_exceptions"), &PhysicsBody::get_collision_exceptions); ClassDB::bind_method(D_METHOD("add_collision_exception_with", "body"), &PhysicsBody::add_collision_exception_with); ClassDB::bind_method(D_METHOD("remove_collision_exception_with", "body"), &PhysicsBody::remove_collision_exception_with); @@ -2326,7 +2344,8 @@ void PhysicalBone::set_joint_type(JointType p_joint_type) { if (p_joint_type == get_joint_type()) return; - memdelete(joint_data); + if (joint_data) + memdelete(joint_data); joint_data = NULL; switch (p_joint_type) { case JOINT_TYPE_PIN: @@ -2526,7 +2545,8 @@ PhysicalBone::PhysicalBone() : } PhysicalBone::~PhysicalBone() { - memdelete(joint_data); + if (joint_data) + memdelete(joint_data); } void PhysicalBone::update_bone_id() { diff --git a/scene/3d/physics_body.h b/scene/3d/physics_body.h index ed9f41197b..fa319e6fbb 100644 --- a/scene/3d/physics_body.h +++ b/scene/3d/physics_body.h @@ -69,6 +69,7 @@ public: void set_collision_mask_bit(int p_bit, bool p_value); bool get_collision_mask_bit(int p_bit) const; + Array get_collision_exceptions(); void add_collision_exception_with(Node *p_node); //must be physicsbody void remove_collision_exception_with(Node *p_node); diff --git a/scene/3d/soft_body.cpp b/scene/3d/soft_body.cpp index 4ebc941ebc..1e730d0b3d 100644 --- a/scene/3d/soft_body.cpp +++ b/scene/3d/soft_body.cpp @@ -29,8 +29,12 @@ /*************************************************************************/ #include "soft_body.h" +#include "core/list.h" +#include "core/object.h" #include "core/os/os.h" +#include "core/rid.h" #include "scene/3d/collision_object.h" +#include "scene/3d/physics_body.h" #include "scene/3d/skeleton.h" #include "servers/physics_server.h" @@ -335,6 +339,7 @@ void SoftBody::_bind_methods() { ClassDB::bind_method(D_METHOD("set_parent_collision_ignore", "parent_collision_ignore"), &SoftBody::set_parent_collision_ignore); ClassDB::bind_method(D_METHOD("get_parent_collision_ignore"), &SoftBody::get_parent_collision_ignore); + ClassDB::bind_method(D_METHOD("get_collision_exceptions"), &SoftBody::get_collision_exceptions); ClassDB::bind_method(D_METHOD("add_collision_exception_with", "body"), &SoftBody::add_collision_exception_with); ClassDB::bind_method(D_METHOD("remove_collision_exception_with", "body"), &SoftBody::remove_collision_exception_with); @@ -547,6 +552,20 @@ PoolVector<SoftBody::PinnedPoint> SoftBody::get_pinned_points_indices() { return pinned_points; } +Array SoftBody::get_collision_exceptions() { + List<RID> exceptions; + PhysicsServer::get_singleton()->soft_body_get_collision_exceptions(physics_rid, &exceptions); + Array ret; + for (List<RID>::Element *E = exceptions.front(); E; E = E->next()) { + RID body = E->get(); + ObjectID instance_id = PhysicsServer::get_singleton()->body_get_object_instance_id(body); + Object *obj = ObjectDB::get_instance(instance_id); + PhysicsBody *physics_body = Object::cast_to<PhysicsBody>(obj); + ret.append(physics_body); + } + return ret; +} + void SoftBody::add_collision_exception_with(Node *p_node) { ERR_FAIL_NULL(p_node); CollisionObject *collision_object = Object::cast_to<CollisionObject>(p_node); diff --git a/scene/3d/soft_body.h b/scene/3d/soft_body.h index ee3d8d87cf..b1e699e839 100644 --- a/scene/3d/soft_body.h +++ b/scene/3d/soft_body.h @@ -166,6 +166,7 @@ public: void set_drag_coefficient(real_t p_drag_coefficient); real_t get_drag_coefficient(); + Array get_collision_exceptions(); void add_collision_exception_with(Node *p_node); void remove_collision_exception_with(Node *p_node); diff --git a/scene/gui/link_button.cpp b/scene/gui/link_button.cpp index d38a067fef..c1561e97ba 100644 --- a/scene/gui/link_button.cpp +++ b/scene/gui/link_button.cpp @@ -75,6 +75,7 @@ void LinkButton::_notification(int p_what) { color = get_color("font_color"); do_underline = underline_mode == UNDERLINE_MODE_ALWAYS; } break; + case DRAW_HOVER_PRESSED: case DRAW_PRESSED: { if (has_color("font_color_pressed")) @@ -91,7 +92,6 @@ void LinkButton::_notification(int p_what) { do_underline = underline_mode != UNDERLINE_MODE_NEVER; } break; - case DRAW_HOVER_PRESSED: break; // Not used in this class case DRAW_DISABLED: { color = get_color("font_color_disabled"); diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index bb56eea98e..d996132960 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -1429,9 +1429,6 @@ void TextEdit::_notification(int p_what) { if (OS::get_singleton()->has_virtual_keyboard()) OS::get_singleton()->show_virtual_keyboard(get_text(), get_global_rect()); - if (raised_from_completion) { - VisualServer::get_singleton()->canvas_item_set_z_index(get_canvas_item(), 1); - } } break; case NOTIFICATION_FOCUS_EXIT: { @@ -1443,9 +1440,6 @@ void TextEdit::_notification(int p_what) { if (OS::get_singleton()->has_virtual_keyboard()) OS::get_singleton()->hide_virtual_keyboard(); - if (raised_from_completion) { - VisualServer::get_singleton()->canvas_item_set_z_index(get_canvas_item(), 0); - } } break; } } @@ -5666,16 +5660,12 @@ void TextEdit::_confirm_completion() { void TextEdit::_cancel_code_hint() { - VisualServer::get_singleton()->canvas_item_set_z_index(get_canvas_item(), 0); - raised_from_completion = false; completion_hint = ""; update(); } void TextEdit::_cancel_completion() { - VisualServer::get_singleton()->canvas_item_set_z_index(get_canvas_item(), 0); - raised_from_completion = false; if (!completion_active) return; @@ -5833,8 +5823,6 @@ void TextEdit::query_code_comple() { void TextEdit::set_code_hint(const String &p_hint) { - VisualServer::get_singleton()->canvas_item_set_z_index(get_canvas_item(), 1); - raised_from_completion = true; completion_hint = p_hint; completion_hint_offset = -0xFFFF; update(); @@ -5842,8 +5830,6 @@ void TextEdit::set_code_hint(const String &p_hint) { void TextEdit::code_complete(const Vector<String> &p_strings, bool p_forced) { - VisualServer::get_singleton()->canvas_item_set_z_index(get_canvas_item(), 1); - raised_from_completion = true; completion_strings = p_strings; completion_active = true; completion_forced = p_forced; @@ -6346,8 +6332,6 @@ TextEdit::TextEdit() { target_v_scroll = 0; v_scroll_speed = 80; - raised_from_completion = false; - context_menu_enabled = true; menu = memnew(PopupMenu); add_child(menu); diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index f0c18ad047..8a508a8738 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -306,8 +306,6 @@ private: float target_v_scroll; float v_scroll_speed; - bool raised_from_completion; - String highlighted_word; uint64_t last_dblclk; diff --git a/scene/gui/texture_button.cpp b/scene/gui/texture_button.cpp index 413f9dbbe6..1940bbfa98 100644 --- a/scene/gui/texture_button.cpp +++ b/scene/gui/texture_button.cpp @@ -128,6 +128,7 @@ void TextureButton::_notification(int p_what) { if (normal.is_valid()) texdraw = normal; } break; + case DRAW_HOVER_PRESSED: case DRAW_PRESSED: { if (pressed.is_null()) { @@ -150,7 +151,6 @@ void TextureButton::_notification(int p_what) { } else texdraw = hover; } break; - case DRAW_HOVER_PRESSED: break; // Not used in this class case DRAW_DISABLED: { if (disabled.is_null()) { diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 50e94e6db5..9f234f832d 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -1835,7 +1835,7 @@ void Node::set_editable_instance(Node *p_node, bool p_editable) { } } -bool Node::is_editable_instance(Node *p_node) const { +bool Node::is_editable_instance(const Node *p_node) const { if (!p_node) return false; //easier, null is never editable :) diff --git a/scene/main/node.h b/scene/main/node.h index a7baebc9c2..78db12dda9 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -303,7 +303,7 @@ public: String get_filename() const; void set_editable_instance(Node *p_node, bool p_editable); - bool is_editable_instance(Node *p_node) const; + bool is_editable_instance(const Node *p_node) const; void set_editable_instances(const HashMap<NodePath, int> &p_editable_instances); HashMap<NodePath, int> get_editable_instances() const; diff --git a/scene/resources/dynamic_font.cpp b/scene/resources/dynamic_font.cpp index 458cbf6718..7422c56eee 100644 --- a/scene/resources/dynamic_font.cpp +++ b/scene/resources/dynamic_font.cpp @@ -1029,7 +1029,7 @@ void DynamicFont::_bind_methods() { Mutex *DynamicFont::dynamic_font_mutex = NULL; -SelfList<DynamicFont>::List DynamicFont::dynamic_fonts; +SelfList<DynamicFont>::List *DynamicFont::dynamic_fonts = NULL; DynamicFont::DynamicFont() : font_list(this) { @@ -1041,29 +1041,31 @@ DynamicFont::DynamicFont() : spacing_char = 0; spacing_space = 0; outline_color = Color(1, 1, 1); - if (dynamic_font_mutex) + if (dynamic_font_mutex) { dynamic_font_mutex->lock(); - dynamic_fonts.add(&font_list); - if (dynamic_font_mutex) + dynamic_fonts->add(&font_list); dynamic_font_mutex->unlock(); + } } DynamicFont::~DynamicFont() { - - if (dynamic_font_mutex) + if (dynamic_font_mutex) { dynamic_font_mutex->lock(); - dynamic_fonts.remove(&font_list); - if (dynamic_font_mutex) + dynamic_fonts->remove(&font_list); dynamic_font_mutex->unlock(); + } } void DynamicFont::initialize_dynamic_fonts() { + dynamic_fonts = memnew(SelfList<DynamicFont>::List()); dynamic_font_mutex = Mutex::create(); } void DynamicFont::finish_dynamic_fonts() { memdelete(dynamic_font_mutex); dynamic_font_mutex = NULL; + memdelete(dynamic_fonts); + dynamic_fonts = NULL; } void DynamicFont::update_oversampling() { @@ -1073,7 +1075,7 @@ void DynamicFont::update_oversampling() { if (dynamic_font_mutex) dynamic_font_mutex->lock(); - SelfList<DynamicFont> *E = dynamic_fonts.first(); + SelfList<DynamicFont> *E = dynamic_fonts->first(); while (E) { if (E->self()->data_at_size.is_valid()) { diff --git a/scene/resources/dynamic_font.h b/scene/resources/dynamic_font.h index afda48a566..bd3f84d62c 100644 --- a/scene/resources/dynamic_font.h +++ b/scene/resources/dynamic_font.h @@ -285,7 +285,7 @@ public: SelfList<DynamicFont> font_list; static Mutex *dynamic_font_mutex; - static SelfList<DynamicFont>::List dynamic_fonts; + static SelfList<DynamicFont>::List *dynamic_fonts; static void initialize_dynamic_fonts(); static void finish_dynamic_fonts(); diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index 274c74a9a2..c3030ee741 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -614,7 +614,7 @@ void SpatialMaterial::_update_shader() { code += "\tfloat particle_frame = floor(INSTANCE_CUSTOM.z * float(particle_total_frames));\n"; code += "\tif (particles_anim_loop) particle_frame=clamp(particle_frame,0.0,particle_total_frames-1.0); else particle_frame=mod(particle_frame,float(particle_total_frames));\n"; code += "\tUV /= vec2(float(particles_anim_h_frames),float(particles_anim_v_frames));\n"; - code += "\tUV += vec2(mod(particle_frame,float(particles_anim_h_frames)) / float(particles_anim_h_frames),particle_frame / float(particles_anim_h_frames) / float(particles_anim_v_frames));\n"; + code += "\tUV += vec2(mod(particle_frame,float(particles_anim_h_frames)) / float(particles_anim_h_frames), floor(particle_frame / float(particles_anim_h_frames)) / float(particles_anim_v_frames));\n"; } break; } diff --git a/scene/resources/mesh_data_tool.cpp b/scene/resources/mesh_data_tool.cpp index a5449e1fe8..7af9086ab7 100644 --- a/scene/resources/mesh_data_tool.cpp +++ b/scene/resources/mesh_data_tool.cpp @@ -42,8 +42,6 @@ void MeshDataTool::clear() { Error MeshDataTool::create_from_surface(const Ref<ArrayMesh> &p_mesh, int p_surface) { ERR_FAIL_COND_V(p_mesh.is_null(), ERR_INVALID_PARAMETER); - - ERR_FAIL_COND_V(p_mesh.is_null(), ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(p_mesh->surface_get_primitive_type(p_surface) != Mesh::PRIMITIVE_TRIANGLES, ERR_INVALID_PARAMETER); Array arrays = p_mesh->surface_get_arrays(p_surface); diff --git a/servers/physics/area_pair_sw.cpp b/servers/physics/area_pair_sw.cpp index d2fef0ab77..5e295edcd1 100644 --- a/servers/physics/area_pair_sw.cpp +++ b/servers/physics/area_pair_sw.cpp @@ -147,10 +147,10 @@ Area2PairSW::~Area2PairSW() { if (colliding) { - if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) + if (area_b->has_area_monitor_callback()) area_b->remove_area_from_query(area_a, shape_a, shape_b); - if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) + if (area_a->has_area_monitor_callback()) area_a->remove_area_from_query(area_b, shape_b, shape_a); } diff --git a/servers/physics_2d/area_pair_2d_sw.cpp b/servers/physics_2d/area_pair_2d_sw.cpp index 9d515d2183..cdd35cf657 100644 --- a/servers/physics_2d/area_pair_2d_sw.cpp +++ b/servers/physics_2d/area_pair_2d_sw.cpp @@ -147,10 +147,10 @@ Area2Pair2DSW::~Area2Pair2DSW() { if (colliding) { - if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) + if (area_b->has_area_monitor_callback()) area_b->remove_area_from_query(area_a, shape_a, shape_b); - if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) + if (area_a->has_area_monitor_callback()) area_a->remove_area_from_query(area_b, shape_b, shape_a); } diff --git a/thirdparty/libwebsockets/lws_config.h b/thirdparty/libwebsockets/lws_config.h index e5e15cc2fd..86ce9ac38a 100644 --- a/thirdparty/libwebsockets/lws_config.h +++ b/thirdparty/libwebsockets/lws_config.h @@ -174,7 +174,7 @@ #define LWS_HAVE_MALLOC_H #endif -#if !defined(IPHONE_ENABLED) && !defined(OSX_ENABLED) && !defined(__HAIKU__) +#if !defined(__APPLE__) && !defined(__HAIKU__) #define LWS_HAVE_PIPE2 #endif diff --git a/thirdparty/libwebsockets/lws_config_private.h b/thirdparty/libwebsockets/lws_config_private.h index b26d225afa..e531777624 100644 --- a/thirdparty/libwebsockets/lws_config_private.h +++ b/thirdparty/libwebsockets/lws_config_private.h @@ -81,7 +81,7 @@ /* Define to 1 if you have the <sys/prctl.h> header file. */ #define LWS_HAVE_SYS_PRCTL_H -#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__HAIKU__) +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__HAIKU__) #undef LWS_HAVE_SYS_PRCTL_H #endif |