diff options
Diffstat (limited to 'scene')
53 files changed, 625 insertions, 346 deletions
diff --git a/scene/2d/animated_sprite.cpp b/scene/2d/animated_sprite.cpp index 54194ff543..e3d1592be0 100644 --- a/scene/2d/animated_sprite.cpp +++ b/scene/2d/animated_sprite.cpp @@ -59,15 +59,36 @@ bool AnimatedSprite::_edit_use_pivot() const { } Rect2 AnimatedSprite::_edit_get_rect() const { + return _get_rect(); +} + +bool AnimatedSprite::_edit_use_rect() const { if (!frames.is_valid() || !frames->has_animation(animation) || frame < 0 || frame >= frames->get_frame_count(animation)) { - return Node2D::_edit_get_rect(); + return false; + } + Ref<Texture> t; + if (animation) + t = frames->get_frame(animation, frame); + if (t.is_null()) + return false; + + return true; +} + +Rect2 AnimatedSprite::get_anchorable_rect() const { + return _get_rect(); +} + +Rect2 AnimatedSprite::_get_rect() const { + if (!frames.is_valid() || !frames->has_animation(animation) || frame < 0 || frame >= frames->get_frame_count(animation)) { + return Rect2(); } Ref<Texture> t; if (animation) t = frames->get_frame(animation, frame); if (t.is_null()) - return Node2D::_edit_get_rect(); + return Rect2(); Size2 s = t->get_size(); Point2 ofs = offset; @@ -80,10 +101,6 @@ Rect2 AnimatedSprite::_edit_get_rect() const { return Rect2(ofs, s); } -bool AnimatedSprite::_edit_use_rect() const { - return true; -} - void SpriteFrames::add_frame(const StringName &p_anim, const Ref<Texture> &p_frame, int p_at_pos) { Map<StringName, Anim>::Element *E = animations.find(p_anim); diff --git a/scene/2d/animated_sprite.h b/scene/2d/animated_sprite.h index be5b1ef6d6..806052a696 100644 --- a/scene/2d/animated_sprite.h +++ b/scene/2d/animated_sprite.h @@ -145,6 +145,7 @@ class AnimatedSprite : public Node2D { void _reset_timeout(); void _set_playing(bool p_playing); bool _is_playing() const; + Rect2 _get_rect() const; protected: static void _bind_methods(); @@ -161,6 +162,8 @@ public: virtual Rect2 _edit_get_rect() const; virtual bool _edit_use_rect() const; + virtual Rect2 get_anchorable_rect() const; + void set_sprite_frames(const Ref<SpriteFrames> &p_frames); Ref<SpriteFrames> get_sprite_frames() const; diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp index 54541293fd..b6dfc666b0 100644 --- a/scene/2d/audio_stream_player_2d.cpp +++ b/scene/2d/audio_stream_player_2d.cpp @@ -36,11 +36,8 @@ void AudioStreamPlayer2D::_mix_audio() { - if (!stream_playback.is_valid()) { - return; - } - - if (!active) { + if (!stream_playback.is_valid() || !active || + (stream_paused && stream_paused_fade <= 0.f)) { return; } @@ -53,8 +50,10 @@ void AudioStreamPlayer2D::_mix_audio() { AudioFrame *buffer = mix_buffer.ptrw(); int buffer_size = mix_buffer.size(); - //mix - stream_playback->mix(buffer, pitch_scale, buffer_size); + // Mix if we're not paused or we're fading out + if (!stream_paused || stream_paused_fade > 0.f) { + stream_playback->mix(buffer, pitch_scale, buffer_size); + } //write all outputs for (int i = 0; i < output_count; i++) { @@ -86,6 +85,13 @@ void AudioStreamPlayer2D::_mix_audio() { AudioFrame vol_inc = (current.vol - prev_outputs[i].vol) / float(buffer_size); AudioFrame vol = current.vol; + if (stream_paused) { + vol = vol * stream_paused_fade; + if (stream_paused_fade > 0.f) { + stream_paused_fade -= 0.1f; + } + } + int cc = AudioServer::get_singleton()->get_channel_count(); if (cc == 1) { @@ -142,6 +148,17 @@ void AudioStreamPlayer2D::_notification(int p_what) { AudioServer::get_singleton()->remove_callback(_mix_audios, this); } + if (p_what == NOTIFICATION_PAUSED) { + if (!can_process()) { + // Node can't process so we start fading out to silence + set_stream_paused(true); + } + } + + if (p_what == NOTIFICATION_UNPAUSED) { + set_stream_paused(false); + } + if (p_what == NOTIFICATION_INTERNAL_PHYSICS_PROCESS) { //update anything related to position first, if possible of course @@ -242,7 +259,6 @@ void AudioStreamPlayer2D::_notification(int p_what) { void AudioStreamPlayer2D::set_stream(Ref<AudioStream> p_stream) { - ERR_FAIL_COND(!p_stream.is_valid()); AudioServer::get_singleton()->lock(); mix_buffer.resize(AudioServer::get_singleton()->thread_get_mix_buffer_size()); @@ -254,14 +270,15 @@ void AudioStreamPlayer2D::set_stream(Ref<AudioStream> p_stream) { setseek = -1; } - stream = p_stream; - stream_playback = p_stream->instance_playback(); + if (p_stream.is_valid()) { + stream = p_stream; + stream_playback = p_stream->instance_playback(); + } AudioServer::get_singleton()->unlock(); - if (stream_playback.is_null()) { + if (p_stream.is_valid() && stream_playback.is_null()) { stream.unref(); - ERR_FAIL_COND(stream_playback.is_null()); } } @@ -418,6 +435,19 @@ uint32_t AudioStreamPlayer2D::get_area_mask() const { return area_mask; } +void AudioStreamPlayer2D::set_stream_paused(bool p_pause) { + + if (p_pause != stream_paused) { + stream_paused = p_pause; + stream_paused_fade = stream_paused ? 1.f : 0.f; + } +} + +bool AudioStreamPlayer2D::get_stream_paused() const { + + return stream_paused; +} + void AudioStreamPlayer2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_stream", "stream"), &AudioStreamPlayer2D::set_stream); @@ -454,6 +484,9 @@ void AudioStreamPlayer2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_area_mask", "mask"), &AudioStreamPlayer2D::set_area_mask); ClassDB::bind_method(D_METHOD("get_area_mask"), &AudioStreamPlayer2D::get_area_mask); + ClassDB::bind_method(D_METHOD("set_stream_paused", "pause"), &AudioStreamPlayer2D::set_stream_paused); + ClassDB::bind_method(D_METHOD("get_stream_paused"), &AudioStreamPlayer2D::get_stream_paused); + ClassDB::bind_method(D_METHOD("_bus_layout_changed"), &AudioStreamPlayer2D::_bus_layout_changed); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "stream", PROPERTY_HINT_RESOURCE_TYPE, "AudioStream"), "set_stream", "get_stream"); @@ -461,6 +494,7 @@ void AudioStreamPlayer2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::REAL, "pitch_scale", PROPERTY_HINT_RANGE, "0.01,32,0.01"), "set_pitch_scale", "get_pitch_scale"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playing", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "_set_playing", "is_playing"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "autoplay"), "set_autoplay", "is_autoplay_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "stream_paused", PROPERTY_HINT_NONE, ""), "set_stream_paused", "get_stream_paused"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "max_distance", PROPERTY_HINT_EXP_RANGE, "1,4096,1,or_greater"), "set_max_distance", "get_max_distance"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_attenuation", "get_attenuation"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "bus", PROPERTY_HINT_ENUM, ""), "set_bus", "get_bus"); @@ -483,6 +517,8 @@ AudioStreamPlayer2D::AudioStreamPlayer2D() { setplay = -1; output_ready = false; area_mask = 1; + stream_paused = false; + stream_paused_fade = 0.f; AudioServer::get_singleton()->connect("bus_layout_changed", this, "_bus_layout_changed"); } diff --git a/scene/2d/audio_stream_player_2d.h b/scene/2d/audio_stream_player_2d.h index 9ae8e3a518..b508de3171 100644 --- a/scene/2d/audio_stream_player_2d.h +++ b/scene/2d/audio_stream_player_2d.h @@ -71,7 +71,9 @@ private: float volume_db; float pitch_scale; + float stream_paused_fade; bool autoplay; + bool stream_paused; StringName bus; void _mix_audio(); @@ -123,6 +125,9 @@ public: void set_area_mask(uint32_t p_mask); uint32_t get_area_mask() const; + void set_stream_paused(bool p_pause); + bool get_stream_paused() const; + AudioStreamPlayer2D(); ~AudioStreamPlayer2D(); }; diff --git a/scene/2d/back_buffer_copy.cpp b/scene/2d/back_buffer_copy.cpp index caa1adebdb..e06c30ec6b 100644 --- a/scene/2d/back_buffer_copy.cpp +++ b/scene/2d/back_buffer_copy.cpp @@ -59,6 +59,11 @@ bool BackBufferCopy::_edit_use_rect() const { return true; } +Rect2 BackBufferCopy::get_anchorable_rect() const { + + return rect; +} + void BackBufferCopy::set_rect(const Rect2 &p_rect) { rect = p_rect; diff --git a/scene/2d/back_buffer_copy.h b/scene/2d/back_buffer_copy.h index 752d56de2b..b1ee12544b 100644 --- a/scene/2d/back_buffer_copy.h +++ b/scene/2d/back_buffer_copy.h @@ -58,6 +58,7 @@ public: void set_rect(const Rect2 &p_rect); Rect2 get_rect() const; + Rect2 get_anchorable_rect() const; void set_copy_mode(CopyMode p_mode); CopyMode get_copy_mode() const; diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp index f1c09594da..47326b9be2 100644 --- a/scene/2d/canvas_item.cpp +++ b/scene/2d/canvas_item.cpp @@ -321,11 +321,6 @@ void CanvasItem::hide() { _change_notify("visible"); } -Size2 CanvasItem::_edit_get_minimum_size() const { - - return Size2(-1, -1); //no limit -} - void CanvasItem::_update_callback() { if (!is_inside_tree()) { @@ -994,7 +989,6 @@ void CanvasItem::_bind_methods() { ClassDB::bind_method(D_METHOD("_edit_set_rect", "rect"), &CanvasItem::_edit_set_rect); ClassDB::bind_method(D_METHOD("_edit_get_rect"), &CanvasItem::_edit_get_rect); ClassDB::bind_method(D_METHOD("_edit_use_rect"), &CanvasItem::_edit_use_rect); - ClassDB::bind_method(D_METHOD("_edit_get_item_and_children_rect"), &CanvasItem::_edit_get_item_and_children_rect); ClassDB::bind_method(D_METHOD("_edit_set_rotation", "degrees"), &CanvasItem::_edit_set_rotation); ClassDB::bind_method(D_METHOD("_edit_get_rotation"), &CanvasItem::_edit_get_rotation); ClassDB::bind_method(D_METHOD("_edit_use_rotation"), &CanvasItem::_edit_use_rotation); @@ -1175,21 +1169,6 @@ int CanvasItem::get_canvas_layer() const { return 0; } -Rect2 CanvasItem::_edit_get_item_and_children_rect() const { - - Rect2 rect = _edit_get_rect(); - - for (int i = 0; i < get_child_count(); i++) { - CanvasItem *c = Object::cast_to<CanvasItem>(get_child(i)); - if (c) { - Rect2 sir = c->get_transform().xform(c->_edit_get_item_and_children_rect()); - rect = rect.merge(sir); - } - } - - return rect; -} - CanvasItem::CanvasItem() : xform_change(this) { diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h index 10d5082dfc..1e6a251c9c 100644 --- a/scene/2d/canvas_item.h +++ b/scene/2d/canvas_item.h @@ -222,6 +222,9 @@ public: /* EDITOR */ + // Select the node + virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; + // Save and restore a CanvasItem state virtual void _edit_set_state(const Dictionary &p_state){}; virtual Dictionary _edit_get_state() const { return Dictionary(); }; @@ -234,36 +237,21 @@ public: virtual void _edit_set_scale(const Size2 &p_scale) = 0; virtual Size2 _edit_get_scale() const = 0; + // Used to rotate the node + virtual bool _edit_use_rotation() const { return false; }; + virtual void _edit_set_rotation(float p_rotation){}; + virtual float _edit_get_rotation() const { return 0.0; }; + // Used to resize/move the node + virtual bool _edit_use_rect() const { return false; }; // MAYBE REPLACE BY A _edit_get_editmode() virtual void _edit_set_rect(const Rect2 &p_rect){}; virtual Rect2 _edit_get_rect() const { return Rect2(0, 0, 0, 0); }; - virtual bool _edit_use_rect() const { return false; }; - - Rect2 _edit_get_item_and_children_rect() const; - - // used to select the node - virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; - - // Used to rotate the node - virtual void - _edit_set_rotation(float p_rotation){}; - virtual float _edit_get_rotation() const { - return 0.0; - }; - virtual bool _edit_use_rotation() const { - return false; - }; + virtual Size2 _edit_get_minimum_size() const { return Size2(-1, -1); }; // LOOKS WEIRD // Used to set a pivot + virtual bool _edit_use_pivot() const { return false; }; virtual void _edit_set_pivot(const Point2 &p_pivot){}; - virtual Point2 _edit_get_pivot() const { - return Point2(); - }; - virtual bool _edit_use_pivot() const { - return false; - }; - - virtual Size2 _edit_get_minimum_size() const; + virtual Point2 _edit_get_pivot() const { return Point2(); }; /* VISIBILITY */ @@ -358,6 +346,9 @@ public: void set_notify_transform(bool p_enable); bool is_transform_notification_enabled() const; + // Used by control nodes to retreive the parent's anchorable area + virtual Rect2 get_anchorable_rect() const { return Rect2(0, 0, 0, 0); }; + int get_canvas_layer() const; CanvasItem(); diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp index 9a44eb31bb..f93c7d1f79 100644 --- a/scene/2d/light_2d.cpp +++ b/scene/2d/light_2d.cpp @@ -59,14 +59,22 @@ bool Light2D::_edit_use_pivot() const { Rect2 Light2D::_edit_get_rect() const { if (texture.is_null()) - return Node2D::_edit_get_rect(); + return Rect2(); Size2 s = texture->get_size() * _scale; return Rect2(texture_offset - s / 2.0, s); } bool Light2D::_edit_use_rect() const { - return true; + return !texture.is_null(); +} + +Rect2 Light2D::get_anchorable_rect() const { + if (texture.is_null()) + return Rect2(); + + Size2 s = texture->get_size() * _scale; + return Rect2(texture_offset - s / 2.0, s); } void Light2D::_update_light_visibility() { diff --git a/scene/2d/light_2d.h b/scene/2d/light_2d.h index 543805e329..40469cfbc8 100644 --- a/scene/2d/light_2d.h +++ b/scene/2d/light_2d.h @@ -94,6 +94,8 @@ public: virtual Rect2 _edit_get_rect() const; virtual bool _edit_use_rect() const; + virtual Rect2 get_anchorable_rect() const; + void set_enabled(bool p_enabled); bool is_enabled() const; diff --git a/scene/2d/screen_button.cpp b/scene/2d/screen_button.cpp index 9480f18176..45f63fd5bf 100644 --- a/scene/2d/screen_button.cpp +++ b/scene/2d/screen_button.cpp @@ -324,19 +324,21 @@ void TouchScreenButton::_release(bool p_exiting_tree) { } Rect2 TouchScreenButton::_edit_get_rect() const { - - if (texture.is_null()) - return Rect2(0, 0, 1, 1); - /* if (texture.is_null()) return CanvasItem::_edit_get_rect(); - */ return Rect2(Size2(), texture->get_size()); } bool TouchScreenButton::_edit_use_rect() const { - return true; + return !texture.is_null(); +} + +Rect2 TouchScreenButton::get_anchorable_rect() const { + if (texture.is_null()) + return CanvasItem::get_anchorable_rect(); + + return Rect2(Size2(), texture->get_size()); } void TouchScreenButton::set_visibility_mode(VisibilityMode p_mode) { diff --git a/scene/2d/screen_button.h b/scene/2d/screen_button.h index b2fafcc93d..3e8adc2e5e 100644 --- a/scene/2d/screen_button.h +++ b/scene/2d/screen_button.h @@ -103,8 +103,9 @@ public: bool is_pressed() const; - Rect2 _edit_get_rect() const; + virtual Rect2 _edit_get_rect() const; virtual bool _edit_use_rect() const; + virtual Rect2 get_anchorable_rect() const; TouchScreenButton(); }; diff --git a/scene/2d/sprite.cpp b/scene/2d/sprite.cpp index 64d0771fab..ebe0e81f6e 100644 --- a/scene/2d/sprite.cpp +++ b/scene/2d/sprite.cpp @@ -63,9 +63,16 @@ Rect2 Sprite::_edit_get_rect() const { } bool Sprite::_edit_use_rect() const { + if (texture.is_null()) + return false; + return true; } +Rect2 Sprite::get_anchorable_rect() const { + return get_rect(); +} + void Sprite::_get_rects(Rect2 &r_src_rect, Rect2 &r_dst_rect, bool &r_filter_clip) const { Rect2 base_rect; @@ -367,10 +374,6 @@ Rect2 Sprite::get_rect() const { if (texture.is_null()) return Rect2(0, 0, 1, 1); - /* - if (texture.is_null()) - return CanvasItem::_edit_get_rect(); - */ Size2i s; diff --git a/scene/2d/sprite.h b/scene/2d/sprite.h index 609ad8bb34..0a5ff002cd 100644 --- a/scene/2d/sprite.h +++ b/scene/2d/sprite.h @@ -115,6 +115,7 @@ public: int get_hframes() const; Rect2 get_rect() const; + virtual Rect2 get_anchorable_rect() const; Sprite(); ~Sprite(); diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index 1d60037287..9a343ca0f0 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -1152,16 +1152,6 @@ PoolVector<int> TileMap::_get_tile_data() const { return data; } -Rect2 TileMap::_edit_get_rect() const { - - const_cast<TileMap *>(this)->_update_dirty_quadrants(); - return rect_cache; -} - -bool TileMap::_edit_use_rect() const { - return true; -} - void TileMap::set_collision_layer(uint32_t p_layer) { collision_layer = p_layer; diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h index 3ddb143f4a..79d79ca59f 100644 --- a/scene/2d/tile_map.h +++ b/scene/2d/tile_map.h @@ -245,9 +245,6 @@ public: void set_cellv(const Vector2 &p_pos, int p_tile, bool p_flip_x = false, bool p_flip_y = false, bool p_transpose = false); int get_cellv(const Vector2 &p_pos) const; - Rect2 _edit_get_rect() const; - virtual bool _edit_use_rect() const; - void make_bitmask_area_dirty(const Vector2 &p_pos); void update_bitmask_area(const Vector2 &p_pos); void update_bitmask_region(const Vector2 &p_start = Vector2(), const Vector2 &p_end = Vector2()); diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp index e7b3645001..35c52a26c9 100644 --- a/scene/3d/audio_stream_player_3d.cpp +++ b/scene/3d/audio_stream_player_3d.cpp @@ -35,11 +35,8 @@ #include "scene/main/viewport.h" void AudioStreamPlayer3D::_mix_audio() { - if (!stream_playback.is_valid()) { - return; - } - - if (!active) { + if (!stream_playback.is_valid() || !active || + (stream_paused && stream_paused_fade <= 0.f)) { return; } @@ -54,8 +51,9 @@ void AudioStreamPlayer3D::_mix_audio() { AudioFrame *buffer = mix_buffer.ptrw(); int buffer_size = mix_buffer.size(); - //mix - if (output_count > 0 || out_of_range_mode == OUT_OF_RANGE_MIX) { + // Mix if we're not paused or we're fading out + if ((output_count > 0 || out_of_range_mode == OUT_OF_RANGE_MIX) && + (!stream_paused || stream_paused_fade > 0.f)) { float output_pitch_scale = 0.0; if (output_count) { @@ -108,6 +106,13 @@ void AudioStreamPlayer3D::_mix_audio() { AudioFrame vol_inc = (current.vol[k] - prev_outputs[i].vol[k]) / float(buffer_size); AudioFrame vol = current.vol[k]; + if (stream_paused) { + vol = vol * stream_paused_fade; + if (stream_paused_fade > 0.f) { + stream_paused_fade -= 0.1f; + } + } + AudioFrame *target = AudioServer::get_singleton()->thread_get_channel_mix_buffer(current.bus_index, k); current.filter.set_mode(AudioFilterSW::HIGHSHELF); @@ -237,6 +242,18 @@ void AudioStreamPlayer3D::_notification(int p_what) { AudioServer::get_singleton()->remove_callback(_mix_audios, this); } + + if (p_what == NOTIFICATION_PAUSED) { + if (!can_process()) { + // Node can't process so we start fading out to silence + set_stream_paused(true); + } + } + + if (p_what == NOTIFICATION_UNPAUSED) { + set_stream_paused(false); + } + if (p_what == NOTIFICATION_TRANSFORM_CHANGED) { if (doppler_tracking != DOPPLER_TRACKING_DISABLED) { @@ -552,7 +569,6 @@ void AudioStreamPlayer3D::_notification(int p_what) { void AudioStreamPlayer3D::set_stream(Ref<AudioStream> p_stream) { - ERR_FAIL_COND(!p_stream.is_valid()); AudioServer::get_singleton()->lock(); mix_buffer.resize(AudioServer::get_singleton()->thread_get_mix_buffer_size()); @@ -564,14 +580,15 @@ void AudioStreamPlayer3D::set_stream(Ref<AudioStream> p_stream) { setseek = -1; } - stream = p_stream; - stream_playback = p_stream->instance_playback(); + if (p_stream.is_valid()) { + stream = p_stream; + stream_playback = p_stream->instance_playback(); + } AudioServer::get_singleton()->unlock(); - if (stream_playback.is_null()) { + if (p_stream.is_valid() && stream_playback.is_null()) { stream.unref(); - ERR_FAIL_COND(stream_playback.is_null()); } } @@ -825,6 +842,19 @@ AudioStreamPlayer3D::DopplerTracking AudioStreamPlayer3D::get_doppler_tracking() return doppler_tracking; } +void AudioStreamPlayer3D::set_stream_paused(bool p_pause) { + + if (p_pause != stream_paused) { + stream_paused = p_pause; + stream_paused_fade = stream_paused ? 1.f : 0.f; + } +} + +bool AudioStreamPlayer3D::get_stream_paused() const { + + return stream_paused; +} + void AudioStreamPlayer3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_stream", "stream"), &AudioStreamPlayer3D::set_stream); @@ -888,6 +918,9 @@ void AudioStreamPlayer3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_doppler_tracking", "mode"), &AudioStreamPlayer3D::set_doppler_tracking); ClassDB::bind_method(D_METHOD("get_doppler_tracking"), &AudioStreamPlayer3D::get_doppler_tracking); + ClassDB::bind_method(D_METHOD("set_stream_paused", "pause"), &AudioStreamPlayer3D::set_stream_paused); + ClassDB::bind_method(D_METHOD("get_stream_paused"), &AudioStreamPlayer3D::get_stream_paused); + ClassDB::bind_method(D_METHOD("_bus_layout_changed"), &AudioStreamPlayer3D::_bus_layout_changed); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "stream", PROPERTY_HINT_RESOURCE_TYPE, "AudioStream"), "set_stream", "get_stream"); @@ -898,6 +931,7 @@ void AudioStreamPlayer3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::REAL, "pitch_scale", PROPERTY_HINT_RANGE, "0.01,32,0.01"), "set_pitch_scale", "get_pitch_scale"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playing", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "_set_playing", "is_playing"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "autoplay"), "set_autoplay", "is_autoplay_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "stream_paused", PROPERTY_HINT_NONE, ""), "set_stream_paused", "get_stream_paused"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "max_distance", PROPERTY_HINT_EXP_RANGE, "0,4096,1,or_greater"), "set_max_distance", "get_max_distance"); ADD_PROPERTY(PropertyInfo(Variant::INT, "out_of_range_mode", PROPERTY_HINT_ENUM, "Mix,Pause"), "set_out_of_range_mode", "get_out_of_range_mode"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "bus", PROPERTY_HINT_ENUM, ""), "set_bus", "get_bus"); @@ -949,6 +983,8 @@ AudioStreamPlayer3D::AudioStreamPlayer3D() { attenuation_filter_db = -24; out_of_range_mode = OUT_OF_RANGE_MIX; doppler_tracking = DOPPLER_TRACKING_DISABLED; + stream_paused = false; + stream_paused_fade = 0.f; velocity_tracker.instance(); AudioServer::get_singleton()->connect("bus_layout_changed", this, "_bus_layout_changed"); diff --git a/scene/3d/audio_stream_player_3d.h b/scene/3d/audio_stream_player_3d.h index 1fcb83cf21..cab1ff121a 100644 --- a/scene/3d/audio_stream_player_3d.h +++ b/scene/3d/audio_stream_player_3d.h @@ -107,7 +107,9 @@ private: float unit_size; float max_db; float pitch_scale; + float stream_paused_fade; bool autoplay; + bool stream_paused; StringName bus; void _mix_audio(); @@ -199,6 +201,9 @@ public: void set_doppler_tracking(DopplerTracking p_tracking); DopplerTracking get_doppler_tracking() const; + void set_stream_paused(bool p_pause); + bool get_stream_paused() const; + AudioStreamPlayer3D(); ~AudioStreamPlayer3D(); }; diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index 5056fb2fe4..e851c8d643 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -979,7 +979,7 @@ bool KinematicBody::move_and_collide(const Vector3 &p_motion, bool p_infinite_in return colliding; } -Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_floor_direction, bool p_infinite_inertia, float p_slope_stop_min_velocity, int p_max_slides, float p_floor_max_angle) { +Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_floor_direction, float p_slope_stop_min_velocity, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) { Vector3 lv = p_linear_velocity; @@ -1128,7 +1128,7 @@ Ref<KinematicCollision> KinematicBody::_get_slide_collision(int p_bounce) { void KinematicBody::_bind_methods() { ClassDB::bind_method(D_METHOD("move_and_collide", "rel_vec", "infinite_inertia"), &KinematicBody::_move, DEFVAL(true)); - ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "floor_normal", "infinite_inertia", "slope_stop_min_velocity", "max_slides", "floor_max_angle"), &KinematicBody::move_and_slide, DEFVAL(Vector3(0, 0, 0)), DEFVAL(true), DEFVAL(0.05), DEFVAL(4), DEFVAL(Math::deg2rad((float)45))); + ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "floor_normal", "slope_stop_min_velocity", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody::move_and_slide, DEFVAL(Vector3(0, 0, 0)), DEFVAL(0.05), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)), DEFVAL(true)); ClassDB::bind_method(D_METHOD("test_move", "from", "rel_vec", "infinite_inertia"), &KinematicBody::test_move); diff --git a/scene/3d/physics_body.h b/scene/3d/physics_body.h index 17d2769c79..0190dcbfc3 100644 --- a/scene/3d/physics_body.h +++ b/scene/3d/physics_body.h @@ -303,7 +303,7 @@ public: void set_safe_margin(float p_margin); float get_safe_margin() const; - Vector3 move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_floor_direction = Vector3(0, 0, 0), bool p_infinite_inertia = true, float p_slope_stop_min_velocity = 0.05, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45)); + Vector3 move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_floor_direction = Vector3(0, 0, 0), float p_slope_stop_min_velocity = 0.05, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45), bool p_infinite_inertia = true); bool is_on_floor() const; bool is_on_wall() const; bool is_on_ceiling() const; diff --git a/scene/3d/physics_joint.cpp b/scene/3d/physics_joint.cpp index c7a002e675..7988c43eab 100644 --- a/scene/3d/physics_joint.cpp +++ b/scene/3d/physics_joint.cpp @@ -260,7 +260,7 @@ void HingeJoint::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_lower_limit", "lower_limit"), &HingeJoint::_set_lower_limit); ClassDB::bind_method(D_METHOD("_get_lower_limit"), &HingeJoint::_get_lower_limit); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "params/bias", PROPERTY_HINT_RANGE, "0.01,0.99,0.01"), "set_param", "get_param", PARAM_BIAS); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "params/bias", PROPERTY_HINT_RANGE, "0.00,0.99,0.01"), "set_param", "get_param", PARAM_BIAS); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_limit/enable"), "set_flag", "get_flag", FLAG_USE_LIMIT); ADD_PROPERTY(PropertyInfo(Variant::REAL, "angular_limit/upper", PROPERTY_HINT_RANGE, "-180,180,0.1"), "_set_upper_limit", "_get_upper_limit"); @@ -270,7 +270,7 @@ void HingeJoint::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_limit/relaxation", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param", "get_param", PARAM_LIMIT_RELAXATION); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "motor/enable"), "set_flag", "get_flag", FLAG_ENABLE_MOTOR); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "motor/target_velocity", PROPERTY_HINT_RANGE, "0.01,4096,0.01"), "set_param", "get_param", PARAM_MOTOR_TARGET_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "motor/target_velocity", PROPERTY_HINT_RANGE, "-200,200,0.01,or_greater,or_lesser"), "set_param", "get_param", PARAM_MOTOR_TARGET_VELOCITY); ADD_PROPERTYI(PropertyInfo(Variant::REAL, "motor/max_impulse", PROPERTY_HINT_RANGE, "0.01,1024,0.01"), "set_param", "get_param", PARAM_MOTOR_MAX_IMPULSE); BIND_ENUM_CONSTANT(PARAM_BIAS); diff --git a/scene/3d/skeleton.cpp b/scene/3d/skeleton.cpp index 76d90dc6ff..8d91b6f09f 100644 --- a/scene/3d/skeleton.cpp +++ b/scene/3d/skeleton.cpp @@ -547,6 +547,8 @@ void Skeleton::localize_rests() { } } +#ifndef _3D_DISABLED + void Skeleton::bind_physical_bone_to_bone(int p_bone, PhysicalBone *p_physical_bone) { ERR_FAIL_INDEX(p_bone, bones.size()); ERR_FAIL_COND(bones[p_bone].physical_bone); @@ -691,6 +693,8 @@ void Skeleton::physical_bones_remove_collision_exception(RID p_exception) { _physical_bones_add_remove_collision_exception(false, this, p_exception); } +#endif // _3D_DISABLED + void Skeleton::_bind_methods() { ClassDB::bind_method(D_METHOD("add_bone", "name"), &Skeleton::add_bone); @@ -727,11 +731,15 @@ void Skeleton::_bind_methods() { ClassDB::bind_method(D_METHOD("get_bone_transform", "bone_idx"), &Skeleton::get_bone_transform); +#ifndef _3D_DISABLED + ClassDB::bind_method(D_METHOD("physical_bones_stop_simulation"), &Skeleton::physical_bones_stop_simulation); ClassDB::bind_method(D_METHOD("physical_bones_start_simulation", "bones"), &Skeleton::physical_bones_start_simulation_on, DEFVAL(Array())); ClassDB::bind_method(D_METHOD("physical_bones_add_collision_exception", "exception"), &Skeleton::physical_bones_add_collision_exception); ClassDB::bind_method(D_METHOD("physical_bones_remove_collision_exception", "exception"), &Skeleton::physical_bones_remove_collision_exception); +#endif // _3D_DISABLED + BIND_CONSTANT(NOTIFICATION_UPDATE_SKELETON); } diff --git a/scene/3d/skeleton.h b/scene/3d/skeleton.h index dad11960a5..9672acb57a 100644 --- a/scene/3d/skeleton.h +++ b/scene/3d/skeleton.h @@ -38,7 +38,10 @@ @author Juan Linietsky <reduzio@gmail.com> */ +#ifndef _3D_DISABLED class PhysicalBone; +#endif // _3D_DISABLED + class Skeleton : public Spatial { GDCLASS(Skeleton, Spatial); @@ -64,8 +67,10 @@ class Skeleton : public Spatial { Transform transform_final; +#ifndef _3D_DISABLED PhysicalBone *physical_bone; PhysicalBone *cache_parent_physical_bone; +#endif // _3D_DISABLED List<uint32_t> nodes_bound; @@ -75,8 +80,10 @@ class Skeleton : public Spatial { ignore_animation = false; custom_pose_enable = false; disable_rest = false; +#ifndef _3D_DISABLED physical_bone = NULL; cache_parent_physical_bone = NULL; +#endif // _3D_DISABLED } }; @@ -164,6 +171,7 @@ public: void localize_rests(); // used for loaders and tools +#ifndef _3D_DISABLED // Physical bone API void bind_physical_bone_to_bone(int p_bone, PhysicalBone *p_physical_bone); @@ -182,6 +190,7 @@ public: void physical_bones_start_simulation_on(const Array &p_bones); void physical_bones_add_collision_exception(RID p_exception); void physical_bones_remove_collision_exception(RID p_exception); +#endif // _3D_DISABLED public: Skeleton(); diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp index 946a1246ff..6dcd5ca8ea 100644 --- a/scene/animation/animation_blend_tree.cpp +++ b/scene/animation/animation_blend_tree.cpp @@ -1036,6 +1036,7 @@ bool AnimationNodeBlendTree::_set(const StringName &p_name, const Variant &p_val String name = p_name; if (name.begins_with("nodes/")) { + String node_name = name.get_slicec('/', 1); String what = name.get_slicec('/', 2); diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index a4322bf713..eac2c8d0c1 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -660,7 +660,22 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float nc->audio_start = p_time; } } else if (nc->audio_playing) { - if (nc->audio_start > p_time || (nc->audio_len > 0 && p_time - nc->audio_start < nc->audio_len)) { + + bool loop = a->has_loop(); + + bool stop = false; + + if (!loop && p_time < nc->audio_start) { + stop = true; + } else if (nc->audio_len > 0) { + float len = nc->audio_start > p_time ? (a->get_length() - nc->audio_start) + p_time : p_time - nc->audio_start; + + if (len > nc->audio_len) { + stop = true; + } + } + + if (stop) { //time to stop nc->node->call("stop"); nc->audio_playing = false; diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index 011c4eb470..83ec9f819b 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -1041,7 +1041,22 @@ void AnimationTree::_process_graph(float p_delta) { t->start = time; } } else if (t->playing) { - if (t->start > time || (t->len > 0 && time - t->start < t->len)) { + + bool loop = a->has_loop(); + + bool stop = false; + + if (!loop && time < t->start) { + stop = true; + } else if (t->len > 0) { + float len = t->start > time ? (a->get_length() - t->start) + time : time - t->start; + + if (len > t->len) { + stop=true; + } + } + + if (stop) { //time to stop t->object->call("stop"); t->playing = false; @@ -1050,6 +1065,12 @@ void AnimationTree::_process_graph(float p_delta) { } } + float db = Math::linear2db(MAX(blend,0.00001)); + if (t->object->has_method("set_unit_db")) { + t->object->call("set_unit_db", db); + } else { + t->object->call("set_volume_db", db); + } } break; case Animation::TYPE_ANIMATION: { diff --git a/scene/animation/root_motion_view.cpp b/scene/animation/root_motion_view.cpp index 8443995720..a28c63064a 100644 --- a/scene/animation/root_motion_view.cpp +++ b/scene/animation/root_motion_view.cpp @@ -37,6 +37,14 @@ float RootMotionView::get_radius() const { return radius; } +void RootMotionView::set_zero_y(bool p_zero_y) { + zero_y = p_zero_y; +} + +bool RootMotionView::get_zero_y() const { + return zero_y; +} + void RootMotionView::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { @@ -77,9 +85,11 @@ void RootMotionView::_notification(int p_what) { transform.orthonormalize(); //dont want scale, too imprecise transform.affine_invert(); - accumulated = accumulated * transform; + accumulated = transform * accumulated; accumulated.origin.x = Math::fposmod(accumulated.origin.x, cell_size); - accumulated.origin.y = Math::fposmod(accumulated.origin.y, cell_size); + if (zero_y) { + accumulated.origin.y = 0; + } accumulated.origin.z = Math::fposmod(accumulated.origin.z, cell_size); VS::get_singleton()->immediate_clear(immediate); @@ -142,13 +152,18 @@ void RootMotionView::_bind_methods() { ClassDB::bind_method(D_METHOD("set_radius", "size"), &RootMotionView::set_radius); ClassDB::bind_method(D_METHOD("get_radius"), &RootMotionView::get_radius); + ClassDB::bind_method(D_METHOD("set_zero_y", "enable"), &RootMotionView::set_zero_y); + ClassDB::bind_method(D_METHOD("get_zero_y"), &RootMotionView::get_zero_y); + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "animation_path", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "AnimationTree"), "set_animation_path", "get_animation_path"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_color", "get_color"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "cell_size", PROPERTY_HINT_RANGE, "0.1,16,0.01,or_greater"), "set_cell_size", "get_cell_size"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "radius", PROPERTY_HINT_RANGE, "0.1,16,0.01,or_greater"), "set_radius", "get_radius"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "zero_y"), "set_zero_y", "get_zero_y"); } RootMotionView::RootMotionView() { + zero_y = true; radius = 10; cell_size = 1; set_process_internal(true); diff --git a/scene/animation/root_motion_view.h b/scene/animation/root_motion_view.h index 65e9ff480b..611183d364 100644 --- a/scene/animation/root_motion_view.h +++ b/scene/animation/root_motion_view.h @@ -13,6 +13,7 @@ public: bool use_in_game; Color color; bool first; + bool zero_y; Transform accumulated; @@ -33,6 +34,9 @@ public: void set_radius(float p_radius); float get_radius() const; + void set_zero_y(bool p_zero_y); + bool get_zero_y() const; + virtual AABB get_aabb() const; virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const; diff --git a/scene/audio/audio_player.cpp b/scene/audio/audio_player.cpp index 408c00334a..40ec04e479 100644 --- a/scene/audio/audio_player.cpp +++ b/scene/audio/audio_player.cpp @@ -44,14 +44,23 @@ void AudioStreamPlayer::_mix_internal(bool p_fadeout) { buffer_size = MIN(buffer_size, 16); //short fadeout ramp } - //mix - stream_playback->mix(buffer, pitch_scale, buffer_size); + // Mix if we're not paused or we're fading out + if (!stream_paused || stream_paused_fade > 0.f) { + stream_playback->mix(buffer, pitch_scale, buffer_size); + } //multiply volume interpolating to avoid clicks if this changes float target_volume = p_fadeout ? -80.0 : volume_db; float vol = Math::db2linear(mix_volume_db); float vol_inc = (Math::db2linear(target_volume) - vol) / float(buffer_size); + if (stream_paused) { + vol = vol * stream_paused_fade; + if (stream_paused_fade > 0.f) { + stream_paused_fade -= 0.1f; + } + } + for (int i = 0; i < buffer_size; i++) { buffer[i] *= vol; vol += vol_inc; @@ -90,11 +99,8 @@ void AudioStreamPlayer::_mix_internal(bool p_fadeout) { void AudioStreamPlayer::_mix_audio() { - if (!stream_playback.is_valid()) { - return; - } - - if (!active) { + if (!stream_playback.is_valid() || !active || + (stream_paused && stream_paused_fade <= 0.f)) { return; } @@ -135,6 +141,17 @@ void AudioStreamPlayer::_notification(int p_what) { AudioServer::get_singleton()->remove_callback(_mix_audios, this); } + + if (p_what == NOTIFICATION_PAUSED) { + if (!can_process()) { + // Node can't process so we start fading out to silence + set_stream_paused(true); + } + } + + if (p_what == NOTIFICATION_UNPAUSED) { + set_stream_paused(false); + } } void AudioStreamPlayer::set_stream(Ref<AudioStream> p_stream) { @@ -159,7 +176,6 @@ void AudioStreamPlayer::set_stream(Ref<AudioStream> p_stream) { if (p_stream.is_valid() && stream_playback.is_null()) { stream.unref(); - ERR_FAIL_COND(stream_playback.is_null()); } } @@ -275,6 +291,19 @@ bool AudioStreamPlayer::_is_active() const { return active; } +void AudioStreamPlayer::set_stream_paused(bool p_pause) { + + if (p_pause != stream_paused) { + stream_paused = p_pause; + stream_paused_fade = stream_paused ? 1.f : 0.f; + } +} + +bool AudioStreamPlayer::get_stream_paused() const { + + return stream_paused; +} + void AudioStreamPlayer::_validate_property(PropertyInfo &property) const { if (property.name == "bus") { @@ -328,11 +357,15 @@ void AudioStreamPlayer::_bind_methods() { ClassDB::bind_method(D_METHOD("_bus_layout_changed"), &AudioStreamPlayer::_bus_layout_changed); + ClassDB::bind_method(D_METHOD("set_stream_paused", "pause"), &AudioStreamPlayer::set_stream_paused); + ClassDB::bind_method(D_METHOD("get_stream_paused"), &AudioStreamPlayer::get_stream_paused); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "stream", PROPERTY_HINT_RESOURCE_TYPE, "AudioStream"), "set_stream", "get_stream"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "volume_db", PROPERTY_HINT_RANGE, "-80,24"), "set_volume_db", "get_volume_db"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "pitch_scale", PROPERTY_HINT_RANGE, "0.01,32,0.01"), "set_pitch_scale", "get_pitch_scale"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playing", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "_set_playing", "is_playing"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "autoplay"), "set_autoplay", "is_autoplay_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "stream_paused", PROPERTY_HINT_NONE, ""), "set_stream_paused", "get_stream_paused"); ADD_PROPERTY(PropertyInfo(Variant::INT, "mix_target", PROPERTY_HINT_ENUM, "Stereo,Surround,Center"), "set_mix_target", "get_mix_target"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "bus", PROPERTY_HINT_ENUM, ""), "set_bus", "get_bus"); @@ -351,6 +384,8 @@ AudioStreamPlayer::AudioStreamPlayer() { autoplay = false; setseek = -1; active = false; + stream_paused = false; + stream_paused_fade = 0.f; mix_target = MIX_TARGET_STEREO; AudioServer::get_singleton()->connect("bus_layout_changed", this, "_bus_layout_changed"); diff --git a/scene/audio/audio_player.h b/scene/audio/audio_player.h index 21189aea6d..c42f191589 100644 --- a/scene/audio/audio_player.h +++ b/scene/audio/audio_player.h @@ -56,7 +56,9 @@ private: float mix_volume_db; float pitch_scale; float volume_db; + float stream_paused_fade; bool autoplay; + bool stream_paused; StringName bus; MixTarget mix_target; @@ -100,6 +102,9 @@ public: void set_mix_target(MixTarget p_target); MixTarget get_mix_target() const; + void set_stream_paused(bool p_pause); + bool get_stream_paused() const; + AudioStreamPlayer(); ~AudioStreamPlayer(); }; diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index 34891832e2..f8c188d33d 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -242,6 +242,14 @@ bool ColorPicker::is_raw_mode() const { return raw_mode_enabled; } +void ColorPicker::set_deferred_mode(bool p_enabled) { + deferred_mode_enabled = p_enabled; +} + +bool ColorPicker::is_deferred_mode() const { + return deferred_mode_enabled; +} + void ColorPicker::_update_text_value() { bool visible = true; if (text_is_constructor) { @@ -328,7 +336,11 @@ void ColorPicker::_uv_input(const Ref<InputEvent> &p_event) { last_hsv = color; set_pick_color(color); _update_color(); + if (!deferred_mode_enabled) + emit_signal("color_changed", color); + } else if (deferred_mode_enabled && !bev->is_pressed() && bev->get_button_index() == BUTTON_LEFT) { emit_signal("color_changed", color); + changing_color = false; } else { changing_color = false; } @@ -347,7 +359,8 @@ void ColorPicker::_uv_input(const Ref<InputEvent> &p_event) { last_hsv = color; set_pick_color(color); _update_color(); - emit_signal("color_changed", color); + if (!deferred_mode_enabled) + emit_signal("color_changed", color); } } @@ -368,7 +381,10 @@ void ColorPicker::_w_input(const Ref<InputEvent> &p_event) { last_hsv = color; set_pick_color(color); _update_color(); - emit_signal("color_changed", color); + if (!deferred_mode_enabled) + emit_signal("color_changed", color); + else if (!bev->is_pressed() && bev->get_button_index() == BUTTON_LEFT) + emit_signal("color_changed", color); } Ref<InputEventMouseMotion> mev = p_event; @@ -383,7 +399,8 @@ void ColorPicker::_w_input(const Ref<InputEvent> &p_event) { last_hsv = color; set_pick_color(color); _update_color(); - emit_signal("color_changed", color); + if (!deferred_mode_enabled) + emit_signal("color_changed", color); } } @@ -500,6 +517,8 @@ void ColorPicker::_bind_methods() { ClassDB::bind_method(D_METHOD("get_pick_color"), &ColorPicker::get_pick_color); ClassDB::bind_method(D_METHOD("set_raw_mode", "mode"), &ColorPicker::set_raw_mode); ClassDB::bind_method(D_METHOD("is_raw_mode"), &ColorPicker::is_raw_mode); + ClassDB::bind_method(D_METHOD("set_deferred_mode", "mode"), &ColorPicker::set_deferred_mode); + ClassDB::bind_method(D_METHOD("is_deferred_mode"), &ColorPicker::is_deferred_mode); ClassDB::bind_method(D_METHOD("set_edit_alpha", "show"), &ColorPicker::set_edit_alpha); ClassDB::bind_method(D_METHOD("is_editing_alpha"), &ColorPicker::is_editing_alpha); ClassDB::bind_method(D_METHOD("add_preset", "color"), &ColorPicker::add_preset); @@ -522,6 +541,7 @@ void ColorPicker::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_pick_color", "get_pick_color"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "edit_alpha"), "set_edit_alpha", "is_editing_alpha"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "raw_mode"), "set_raw_mode", "is_raw_mode"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "deferred_mode"), "set_deferred_mode", "is_deferred_mode"); ADD_SIGNAL(MethodInfo("color_changed", PropertyInfo(Variant::COLOR, "color"))); } @@ -533,6 +553,7 @@ ColorPicker::ColorPicker() : edit_alpha = true; text_is_constructor = false; raw_mode_enabled = false; + deferred_mode_enabled = false; changing_color = false; screen = NULL; diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h index 6b63e5fe60..c8d8e1aa8a 100644 --- a/scene/gui/color_picker.h +++ b/scene/gui/color_picker.h @@ -67,6 +67,7 @@ private: Color color; bool raw_mode_enabled; + bool deferred_mode_enabled; bool updating; bool changing_color; float h, s, v; @@ -107,6 +108,9 @@ public: void set_raw_mode(bool p_enabled); bool is_raw_mode() const; + void set_deferred_mode(bool p_enabled); + bool is_deferred_mode() const; + void set_focus_on_line_edit(); ColorPicker(); diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 18a0cd13d9..068af42260 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -160,9 +160,16 @@ void Control::_update_minimum_size_cache() { Size2 minsize = get_minimum_size(); minsize.x = MAX(minsize.x, data.custom_minimum_size.x); minsize.y = MAX(minsize.y, data.custom_minimum_size.y); + + bool size_changed = false; + if (data.minimum_size_cache != minsize) + size_changed = true; + data.minimum_size_cache = minsize; data.minimum_size_valid = true; - minimum_size_changed(); + + if (size_changed) + minimum_size_changed(); } Size2 Control::get_combined_minimum_size() const { @@ -1267,35 +1274,34 @@ bool Control::has_constant(const StringName &p_name, const StringName &p_type) c return Theme::get_default()->has_constant(p_name, type); } -Size2 Control::get_parent_area_size() const { - - ERR_FAIL_COND_V(!is_inside_tree(), Size2()); - - Size2 parent_size; +Rect2 Control::get_parent_anchorable_rect() const { + if (!is_inside_tree()) + return Rect2(); + Rect2 parent_rect; if (data.parent_canvas_item) { - - parent_size = data.parent_canvas_item->_edit_get_rect().size; + parent_rect = data.parent_canvas_item->get_anchorable_rect(); } else { - - parent_size = get_viewport()->get_visible_rect().size; + parent_rect = get_viewport()->get_visible_rect(); } - return parent_size; + return parent_rect; } -void Control::_size_changed() { +Size2 Control::get_parent_area_size() const { - if (!is_inside_tree()) - return; + return get_parent_anchorable_rect().size; +} - Size2 parent_size = get_parent_area_size(); +void Control::_size_changed() { + + Rect2 parent_rect = get_parent_anchorable_rect(); float margin_pos[4]; for (int i = 0; i < 4; i++) { - float area = parent_size[i & 1]; + float area = parent_rect.size[i & 1]; margin_pos[i] = data.margin[i] + (data.anchor[i] * area); } @@ -1325,9 +1331,9 @@ void Control::_size_changed() { } // We use a little workaround to avoid flickering when moving the pivot with _edit_set_pivot() - if (Math::abs(Math::sin(data.rotation * 4.0f)) < 0.00001f && get_viewport()->is_snap_controls_to_pixels_enabled()) { - new_size_cache = new_size_cache.floor(); - new_pos_cache = new_pos_cache.floor(); + if (is_inside_tree() && Math::abs(Math::sin(data.rotation * 4.0f)) < 0.00001f && get_viewport()->is_snap_controls_to_pixels_enabled()) { + new_size_cache = new_size_cache.round(); + new_pos_cache = new_pos_cache.round(); } bool pos_changed = new_pos_cache != data.pos_cache; bool size_changed = new_size_cache != data.size_cache; @@ -1335,57 +1341,25 @@ void Control::_size_changed() { data.pos_cache = new_pos_cache; data.size_cache = new_size_cache; - if (size_changed) { - notification(NOTIFICATION_RESIZED); - } - if (pos_changed || size_changed) { - item_rect_changed(size_changed); - _change_notify_margins(); - _notify_transform(); - } - - if (pos_changed && !size_changed) { - _update_canvas_item_transform(); //move because it won't be updated - } -} - -float Control::_get_parent_range(int p_idx) const { - - if (!is_inside_tree()) { - - return 0; - } - if (data.parent_canvas_item) { + if (is_inside_tree()) { + if (size_changed) { + notification(NOTIFICATION_RESIZED); + } + if (pos_changed || size_changed) { + item_rect_changed(size_changed); + _change_notify_margins(); + _notify_transform(); + } - return data.parent_canvas_item->_edit_get_rect().size[p_idx & 1]; - } else { - return get_viewport()->get_visible_rect().size[p_idx & 1]; + if (pos_changed && !size_changed) { + _update_canvas_item_transform(); //move because it won't be updated + } } - - return 0; -} - -float Control::_get_range(int p_idx) const { - - p_idx &= 1; - - float parent_range = _get_parent_range(p_idx); - float from = _a2s(data.margin[p_idx], data.anchor[p_idx], parent_range); - float to = _a2s(data.margin[p_idx + 2], data.anchor[p_idx + 2], parent_range); - - return to - from; -} - -float Control::_s2a(float p_val, float p_anchor, float p_range) const { - return p_val - (p_anchor * p_range); -} - -float Control::_a2s(float p_val, float p_anchor, float p_range) const { - return Math::floor(p_val + (p_anchor * p_range)); } void Control::set_anchor(Margin p_margin, float p_anchor, bool p_keep_margin, bool p_push_opposite_anchor) { - float parent_range = _get_parent_range((p_margin == MARGIN_LEFT || p_margin == MARGIN_RIGHT) ? 0 : 1); + Rect2 parent_rect = get_parent_anchorable_rect(); + float parent_range = (p_margin == MARGIN_LEFT || p_margin == MARGIN_RIGHT) ? parent_rect.size.x : parent_rect.size.y; float previous_margin_pos = data.margin[p_margin] + data.anchor[p_margin] * parent_range; float previous_opposite_margin_pos = data.margin[(p_margin + 2) % 4] + data.anchor[(p_margin + 2) % 4] * parent_range; @@ -1401,9 +1375,9 @@ void Control::set_anchor(Margin p_margin, float p_anchor, bool p_keep_margin, bo } if (!p_keep_margin) { - data.margin[p_margin] = _s2a(previous_margin_pos, data.anchor[p_margin], parent_range); + data.margin[p_margin] = previous_margin_pos - data.anchor[p_margin] * parent_range; if (p_push_opposite_anchor) { - data.margin[(p_margin + 2) % 4] = _s2a(previous_opposite_margin_pos, data.anchor[(p_margin + 2) % 4], parent_range); + data.margin[(p_margin + 2) % 4] = previous_opposite_margin_pos - data.anchor[(p_margin + 2) % 4] * parent_range; } } if (is_inside_tree()) { @@ -1411,7 +1385,7 @@ void Control::set_anchor(Margin p_margin, float p_anchor, bool p_keep_margin, bo } update(); - _change_notify(); + _change_notify("anchor"); } void Control::_set_anchor(Margin p_margin, float p_anchor) { @@ -1557,8 +1531,7 @@ void Control::set_margins_preset(LayoutPreset p_preset, LayoutPresetMode p_resiz new_size.y = min_size.y; } - float pw = _get_parent_range(0); - float ph = _get_parent_range(1); + Rect2 parent_rect = get_parent_anchorable_rect(); //Left switch (p_preset) { @@ -1570,21 +1543,21 @@ void Control::set_margins_preset(LayoutPreset p_preset, LayoutPresetMode p_resiz case PRESET_LEFT_WIDE: case PRESET_HCENTER_WIDE: case PRESET_WIDE: - data.margin[0] = pw * (0.0 - data.anchor[0]) + p_margin; + data.margin[0] = parent_rect.size.x * (0.0 - data.anchor[0]) + p_margin + parent_rect.position.x; break; case PRESET_CENTER_TOP: case PRESET_CENTER_BOTTOM: case PRESET_CENTER: case PRESET_VCENTER_WIDE: - data.margin[0] = pw * (0.5 - data.anchor[0]) - new_size.x / 2; + data.margin[0] = parent_rect.size.x * (0.5 - data.anchor[0]) - new_size.x / 2 + parent_rect.position.x; break; case PRESET_TOP_RIGHT: case PRESET_BOTTOM_RIGHT: case PRESET_CENTER_RIGHT: case PRESET_RIGHT_WIDE: - data.margin[0] = pw * (1.0 - data.anchor[0]) - new_size.x - p_margin; + data.margin[0] = parent_rect.size.x * (1.0 - data.anchor[0]) - new_size.x - p_margin + parent_rect.position.x; break; } @@ -1598,21 +1571,21 @@ void Control::set_margins_preset(LayoutPreset p_preset, LayoutPresetMode p_resiz case PRESET_TOP_WIDE: case PRESET_VCENTER_WIDE: case PRESET_WIDE: - data.margin[1] = ph * (0.0 - data.anchor[1]) + p_margin; + data.margin[1] = parent_rect.size.y * (0.0 - data.anchor[1]) + p_margin + parent_rect.position.y; break; case PRESET_CENTER_LEFT: case PRESET_CENTER_RIGHT: case PRESET_CENTER: case PRESET_HCENTER_WIDE: - data.margin[1] = ph * (0.5 - data.anchor[1]) - new_size.y / 2; + data.margin[1] = parent_rect.size.y * (0.5 - data.anchor[1]) - new_size.y / 2 + parent_rect.position.y; break; case PRESET_BOTTOM_LEFT: case PRESET_BOTTOM_RIGHT: case PRESET_CENTER_BOTTOM: case PRESET_BOTTOM_WIDE: - data.margin[1] = ph * (1.0 - data.anchor[1]) - new_size.y - p_margin; + data.margin[1] = parent_rect.size.y * (1.0 - data.anchor[1]) - new_size.y - p_margin + parent_rect.position.y; break; } @@ -1622,14 +1595,14 @@ void Control::set_margins_preset(LayoutPreset p_preset, LayoutPresetMode p_resiz case PRESET_BOTTOM_LEFT: case PRESET_CENTER_LEFT: case PRESET_LEFT_WIDE: - data.margin[2] = pw * (0.0 - data.anchor[2]) + new_size.x + p_margin; + data.margin[2] = parent_rect.size.x * (0.0 - data.anchor[2]) + new_size.x + p_margin + parent_rect.position.x; break; case PRESET_CENTER_TOP: case PRESET_CENTER_BOTTOM: case PRESET_CENTER: case PRESET_VCENTER_WIDE: - data.margin[2] = pw * (0.5 - data.anchor[2]) + new_size.x / 2; + data.margin[2] = parent_rect.size.x * (0.5 - data.anchor[2]) + new_size.x / 2 + parent_rect.position.x; break; case PRESET_TOP_RIGHT: @@ -1640,7 +1613,7 @@ void Control::set_margins_preset(LayoutPreset p_preset, LayoutPresetMode p_resiz case PRESET_BOTTOM_WIDE: case PRESET_HCENTER_WIDE: case PRESET_WIDE: - data.margin[2] = pw * (1.0 - data.anchor[2]) - p_margin; + data.margin[2] = parent_rect.size.x * (1.0 - data.anchor[2]) - p_margin + parent_rect.position.x; break; } @@ -1650,14 +1623,14 @@ void Control::set_margins_preset(LayoutPreset p_preset, LayoutPresetMode p_resiz case PRESET_TOP_RIGHT: case PRESET_CENTER_TOP: case PRESET_TOP_WIDE: - data.margin[3] = ph * (0.0 - data.anchor[3]) + new_size.y + p_margin; + data.margin[3] = parent_rect.size.y * (0.0 - data.anchor[3]) + new_size.y + p_margin + parent_rect.position.y; break; case PRESET_CENTER_LEFT: case PRESET_CENTER_RIGHT: case PRESET_CENTER: case PRESET_HCENTER_WIDE: - data.margin[3] = ph * (0.5 - data.anchor[3]) + new_size.y / 2; + data.margin[3] = parent_rect.size.y * (0.5 - data.anchor[3]) + new_size.y / 2 + parent_rect.position.y; break; case PRESET_BOTTOM_LEFT: @@ -1668,7 +1641,7 @@ void Control::set_margins_preset(LayoutPreset p_preset, LayoutPresetMode p_resiz case PRESET_BOTTOM_WIDE: case PRESET_VCENTER_WIDE: case PRESET_WIDE: - data.margin[3] = ph * (1.0 - data.anchor[3]) - p_margin; + data.margin[3] = parent_rect.size.y * (1.0 - data.anchor[3]) - p_margin + parent_rect.position.y; break; } @@ -1747,31 +1720,29 @@ void Control::set_global_position(const Point2 &p_point) { set_position(inv.xform(p_point)); } -void Control::set_position(const Size2 &p_point) { - - float pw = _get_parent_range(0); - float ph = _get_parent_range(1); +Rect2 Control::_compute_child_rect(const float p_anchors[4], const float p_margins[4]) const { - float x = _a2s(data.margin[0], data.anchor[0], pw); - float y = _a2s(data.margin[1], data.anchor[1], ph); - float x2 = _a2s(data.margin[2], data.anchor[2], pw); - float y2 = _a2s(data.margin[3], data.anchor[3], ph); + Rect2 anchorable = get_parent_anchorable_rect(); + Rect2 result = anchorable; + for (int i = 0; i < 4; i++) { + result.grow_margin((Margin)i, p_anchors[i] * anchorable.get_size()[i % 2] + p_margins[i]); + } - Size2 ret = Size2(x2 - x, y2 - y); - Size2 min = get_combined_minimum_size(); + return result; +} - Size2 size = Size2(MAX(min.width, ret.width), MAX(min.height, ret.height)); - float w = size.x; - float h = size.y; +void Control::_compute_margins(Rect2 p_rect, const float p_anchors[4], float (&r_margins)[4]) { - x = p_point.x; - y = p_point.y; + Size2 parent_rect_size = get_parent_anchorable_rect().size; + r_margins[0] = Math::floor(p_rect.position.x - (p_anchors[0] * parent_rect_size.x)); + r_margins[1] = Math::floor(p_rect.position.y - (p_anchors[1] * parent_rect_size.y)); + r_margins[2] = Math::floor(p_rect.position.x + p_rect.size.x - (p_anchors[2] * parent_rect_size.x)); + r_margins[3] = Math::floor(p_rect.position.y + p_rect.size.y - (p_anchors[3] * parent_rect_size.y)); +} - data.margin[0] = _s2a(x, data.anchor[0], pw); - data.margin[1] = _s2a(y, data.anchor[1], ph); - data.margin[2] = _s2a(x + w, data.anchor[2], pw); - data.margin[3] = _s2a(y + h, data.anchor[3], ph); +void Control::set_position(const Size2 &p_point) { + _compute_margins(Rect2(p_point, data.size_cache), data.anchor, data.margin); _size_changed(); } @@ -1784,18 +1755,7 @@ void Control::set_size(const Size2 &p_size) { if (new_size.y < min.y) new_size.y = min.y; - float pw = _get_parent_range(0); - float ph = _get_parent_range(1); - - float x = _a2s(data.margin[0], data.anchor[0], pw); - float y = _a2s(data.margin[1], data.anchor[1], ph); - - float w = new_size.width; - float h = new_size.height; - - data.margin[2] = _s2a(x + w, data.anchor[2], pw); - data.margin[3] = _s2a(y + h, data.anchor[3], ph); - + _compute_margins(Rect2(data.pos_cache, new_size), data.anchor, data.margin); _size_changed(); } @@ -1826,6 +1786,11 @@ Rect2 Control::get_rect() const { return Rect2(get_position(), get_size()); } +Rect2 Control::get_anchorable_rect() const { + + return Rect2(Point2(), get_size()); +} + void Control::add_icon_override(const StringName &p_name, const Ref<Texture> &p_icon) { ERR_FAIL_COND(p_icon.is_null()); @@ -2325,12 +2290,11 @@ Control *Control::_get_focus_neighbour(Margin p_margin, int p_count) { Point2 points[4]; Transform2D xform = get_global_transform(); - Rect2 rect = _edit_get_rect(); - points[0] = xform.xform(rect.position); - points[1] = xform.xform(rect.position + Point2(rect.size.x, 0)); - points[2] = xform.xform(rect.position + rect.size); - points[3] = xform.xform(rect.position + Point2(0, rect.size.y)); + points[0] = xform.xform(Point2()); + points[1] = xform.xform(Point2(get_size().x, 0)); + points[2] = xform.xform(get_size()); + points[3] = xform.xform(Point2(0, get_size().y)); const Vector2 dir[4] = { Vector2(-1, 0), @@ -2384,12 +2348,11 @@ void Control::_window_find_focus_neighbour(const Vector2 &p_dir, Node *p_at, con Point2 points[4]; Transform2D xform = c->get_global_transform(); - Rect2 rect = c->_edit_get_rect(); - points[0] = xform.xform(rect.position); - points[1] = xform.xform(rect.position + Point2(rect.size.x, 0)); - points[2] = xform.xform(rect.position + rect.size); - points[3] = xform.xform(rect.position + Point2(0, rect.size.y)); + points[0] = xform.xform(Point2()); + points[1] = xform.xform(Point2(get_size().x, 0)); + points[2] = xform.xform(get_size()); + points[3] = xform.xform(Point2(0, get_size().y)); float min = 1e7; diff --git a/scene/gui/control.h b/scene/gui/control.h index 9124256624..fa5274d854 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -202,12 +202,12 @@ private: NodePath focus_next; NodePath focus_prev; - HashMap<StringName, Ref<Texture>, StringNameHasher> icon_override; - HashMap<StringName, Ref<Shader>, StringNameHasher> shader_override; - HashMap<StringName, Ref<StyleBox>, StringNameHasher> style_override; - HashMap<StringName, Ref<Font>, StringNameHasher> font_override; - HashMap<StringName, Color, StringNameHasher> color_override; - HashMap<StringName, int, StringNameHasher> constant_override; + HashMap<StringName, Ref<Texture> > icon_override; + HashMap<StringName, Ref<Shader> > shader_override; + HashMap<StringName, Ref<StyleBox> > style_override; + HashMap<StringName, Ref<Font> > font_override; + HashMap<StringName, Color> color_override; + HashMap<StringName, int> constant_override; Map<Ref<Font>, int> font_refcount; } data; @@ -220,10 +220,6 @@ private: void _set_anchor(Margin p_margin, float p_anchor); - float _get_parent_range(int p_idx) const; - float _get_range(int p_idx) const; - float _s2a(float p_val, float p_anchor, float p_range) const; - float _a2s(float p_val, float p_anchor, float p_range) const; void _propagate_theme_changed(CanvasItem *p_at, Control *p_owner, bool p_assign = true); void _theme_changed(); @@ -233,6 +229,9 @@ private: void _update_scroll(); void _resize(const Size2 &p_size); + Rect2 _compute_child_rect(const float p_anchors[4], const float p_margins[4]) const; + void _compute_margins(Rect2 p_rect, const float p_anchors[4], float (&r_margins)[4]); + void _size_changed(); String _get_tooltip() const; @@ -283,6 +282,7 @@ public: }; + /* EDITOR */ virtual Dictionary _edit_get_state() const; virtual void _edit_set_state(const Dictionary &p_state); @@ -358,6 +358,7 @@ public: Rect2 get_rect() const; Rect2 get_global_rect() const; Rect2 get_window_rect() const; ///< use with care, as it blocks waiting for the visual server + Rect2 get_anchorable_rect() const; void set_rotation(float p_radians); void set_rotation_degrees(float p_degrees); @@ -465,6 +466,7 @@ public: bool is_toplevel_control() const; Size2 get_parent_area_size() const; + Rect2 get_parent_anchorable_rect() const; void grab_click_focus(); diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index 57b9a9a11b..72ed0e9b81 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -942,6 +942,7 @@ void ItemList::_notification(int p_what) { } } + minimum_size_changed(); shape_changed = false; } diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 0cd5219f8f..b71a4dd133 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -711,7 +711,8 @@ void LineEdit::_notification(int p_what) { if (selected) VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs), Size2(char_width, caret_height)), selection_color); - drawer.draw_char(ci, Point2(x_ofs, y_ofs + font_ascent), cchar, next, selected ? font_color_selected : font_color); + int yofs = y_ofs + (caret_height - font->get_height()) / 2; + drawer.draw_char(ci, Point2(x_ofs, yofs + font_ascent), cchar, next, selected ? font_color_selected : font_color); if (char_ofs == cursor_pos && draw_caret) { if (ime_text.length() == 0) { diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index f34559fc8d..ce2e3538da 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -324,7 +324,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & color = _find_color(text, p_base_color); font_color_shadow = _find_color(text, p_font_color_shadow); underline = _find_underline(text); - if (_find_meta(text, &meta)) { + if (_find_meta(text, &meta) && underline_meta) { underline = true; } diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index 4f72b5c6ed..c30fa96327 100644 --- a/scene/gui/tab_container.cpp +++ b/scene/gui/tab_container.cpp @@ -407,7 +407,7 @@ void TabContainer::_child_renamed_callback() { void TabContainer::add_child_notify(Node *p_child) { - Control::add_child_notify(p_child); + Container::add_child_notify(p_child); Control *c = Object::cast_to<Control>(p_child); if (!c) @@ -515,7 +515,7 @@ Control *TabContainer::get_current_tab_control() const { void TabContainer::remove_child_notify(Node *p_child) { - Control::remove_child_notify(p_child); + Container::remove_child_notify(p_child); call_deferred("_update_current_tab"); diff --git a/scene/gui/tab_container.h b/scene/gui/tab_container.h index 1afe5f7541..8a3c9d2bb2 100644 --- a/scene/gui/tab_container.h +++ b/scene/gui/tab_container.h @@ -31,11 +31,11 @@ #ifndef TAB_CONTAINER_H #define TAB_CONTAINER_H -#include "scene/gui/control.h" +#include "scene/gui/container.h" #include "scene/gui/popup.h" -class TabContainer : public Control { +class TabContainer : public Container { - GDCLASS(TabContainer, Control); + GDCLASS(TabContainer, Container); public: enum TabAlign { diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 215ba0271f..218b5060a1 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -426,6 +426,9 @@ void TextEdit::_update_scrollbars() { void TextEdit::_click_selection_held() { + // Warning: is_mouse_button_pressed(BUTTON_LEFT) returns false for double+ clicks, so this doesn't work for MODE_WORD + // and MODE_LINE. However, moving the mouse triggers _gui_input, which calls these functions too, so that's not a huge problem. + // I'm unsure if there's an actual fix that doesn't have a ton of side effects. if (Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT) && selection.selecting_mode != Selection::MODE_NONE) { switch (selection.selecting_mode) { case Selection::MODE_POINTER: { @@ -455,7 +458,7 @@ void TextEdit::_update_selection_mode_pointer() { select(selection.selecting_line, selection.selecting_column, row, col); cursor_set_line(row, false); - cursor_set_column(col, false); + cursor_set_column(col); update(); click_select_held->start(); @@ -496,21 +499,24 @@ void TextEdit::_update_selection_mode_word() { selection.selected_word_beg = beg; selection.selected_word_end = end; selection.selected_word_origin = beg; + cursor_set_line(selection.to_line, false); cursor_set_column(selection.to_column); } else { if ((col <= selection.selected_word_origin && row == selection.selecting_line) || row < selection.selecting_line) { selection.selecting_column = selection.selected_word_end; select(row, beg, selection.selecting_line, selection.selected_word_end); + cursor_set_line(selection.from_line, false); cursor_set_column(selection.from_column); } else { selection.selecting_column = selection.selected_word_beg; select(selection.selecting_line, selection.selected_word_beg, row, end); + cursor_set_line(selection.to_line, false); cursor_set_column(selection.to_column); } } - cursor_set_line(row, false); update(); + click_select_held->start(); } @@ -531,7 +537,7 @@ void TextEdit::_update_selection_mode_line() { selection.selecting_column = 0; col = text[row].length(); } - cursor_set_column(0, false); + cursor_set_column(0); select(selection.selecting_line, selection.selecting_column, row, col); update(); @@ -960,12 +966,13 @@ void TextEdit::_notification(int p_what) { // draw line numbers if (cache.line_number_w) { + int yofs = ofs_y + (get_row_height() - cache.font->get_height()) / 2; String fc = String::num(line + 1); while (fc.length() < line_number_char_count) { fc = line_num_padding + fc; } - cache.font->draw(ci, Point2(cache.style_normal->get_margin(MARGIN_LEFT) + cache.breakpoint_gutter_width + ofs_x, ofs_y + cache.font->get_ascent()), fc, cache.line_number_color); + cache.font->draw(ci, Point2(cache.style_normal->get_margin(MARGIN_LEFT) + cache.breakpoint_gutter_width + ofs_x, yofs + cache.font->get_ascent()), fc, cache.line_number_color); } } @@ -1088,12 +1095,13 @@ void TextEdit::_notification(int p_what) { } if (brace_matching_enabled) { + int yofs = ofs_y + (get_row_height() - cache.font->get_height()) / 2; if ((brace_open_match_line == line && brace_open_match_column == last_wrap_column + j) || (cursor.column == last_wrap_column + j && cursor.line == line && cursor_wrap_index == line_wrap_index && (brace_open_matching || brace_open_mismatch))) { if (brace_open_mismatch) color = cache.brace_mismatch_color; - drawer.draw_char(ci, Point2i(char_ofs + char_margin + ofs_x, ofs_y + ascent), '_', str[j + 1], in_selection && override_selected_font_color ? cache.font_selected_color : color); + drawer.draw_char(ci, Point2i(char_ofs + char_margin + ofs_x, yofs + ascent), '_', str[j + 1], in_selection && override_selected_font_color ? cache.font_selected_color : color); } if ((brace_close_match_line == line && brace_close_match_column == last_wrap_column + j) || @@ -1101,7 +1109,7 @@ void TextEdit::_notification(int p_what) { if (brace_close_mismatch) color = cache.brace_mismatch_color; - drawer.draw_char(ci, Point2i(char_ofs + char_margin + ofs_x, ofs_y + ascent), '_', str[j + 1], in_selection && override_selected_font_color ? cache.font_selected_color : color); + drawer.draw_char(ci, Point2i(char_ofs + char_margin + ofs_x, yofs + ascent), '_', str[j + 1], in_selection && override_selected_font_color ? cache.font_selected_color : color); } } @@ -1161,9 +1169,10 @@ void TextEdit::_notification(int p_what) { } if (str[j] >= 32) { - int w = drawer.draw_char(ci, Point2i(char_ofs + char_margin + ofs_x, ofs_y + ascent), str[j], str[j + 1], in_selection && override_selected_font_color ? cache.font_selected_color : color); + int yofs = ofs_y + (get_row_height() - cache.font->get_height()) / 2; + int w = drawer.draw_char(ci, Point2i(char_ofs + char_margin + ofs_x, yofs + ascent), str[j], str[j + 1], in_selection && override_selected_font_color ? cache.font_selected_color : color); if (underlined) { - draw_rect(Rect2(char_ofs + char_margin + ofs_x, ofs_y + ascent + 2, w, 1), in_selection && override_selected_font_color ? cache.font_selected_color : color); + draw_rect(Rect2(char_ofs + char_margin + ofs_x, yofs + ascent + 2, w, 1), in_selection && override_selected_font_color ? cache.font_selected_color : color); } } else if (draw_tabs && str[j] == '\t') { int yofs = (get_row_height() - cache.tab_icon->get_height()) / 2; @@ -1528,8 +1537,11 @@ void TextEdit::backspace_at_cursor() { if (is_line_hidden(cursor.line)) set_line_as_hidden(prev_line, true); - if (is_line_set_as_breakpoint(cursor.line)) + if (is_line_set_as_breakpoint(cursor.line)) { + if (!text.is_breakpoint(prev_line)) + emit_signal("breakpoint_toggled", prev_line); set_line_as_breakpoint(prev_line, true); + } if (auto_brace_completion_enabled && cursor.column > 0 && @@ -1660,14 +1672,17 @@ void TextEdit::_get_mouse_pos(const Point2i &p_mouse, int &r_row, int &r_col) co rows /= get_row_height(); rows += get_v_scroll_offset(); int first_vis_line = get_first_visible_line(); + int last_vis_line = get_last_visible_line(); int row = first_vis_line + Math::floor(rows); int wrap_index = 0; if (is_wrap_enabled() || is_hiding_enabled()) { - int f_ofs = num_lines_from_rows(first_vis_line, cursor.wrap_ofs, rows + 1, wrap_index) - 1; - row = first_vis_line + f_ofs; - row = CLAMP(row, 0, get_last_visible_line() + 1); + int f_ofs = num_lines_from_rows(first_vis_line, cursor.wrap_ofs, rows + (1 * SGN(rows)), wrap_index) - 1; + if (rows < 0) + row = first_vis_line - f_ofs; + else + row = first_vis_line + f_ofs; } if (row < 0) @@ -3301,22 +3316,37 @@ void TextEdit::_base_insert_text(int p_line, int p_char, const String &p_text, i ERR_FAIL_INDEX(p_line, text.size()); ERR_FAIL_COND(p_char < 0); - /* STEP 1 add spaces if the char is greater than the end of the line */ + /* STEP 1 remove \r from source text and separate in substrings */ + + Vector<String> substrings = p_text.replace("\r", "").split("\n"); + + /* STEP 2 fire breakpoint_toggled signals */ + + // Is this just a new empty line? + bool shift_first_line = p_char == 0 && p_text.replace("\r", "") == "\n"; + + int i = p_line + !shift_first_line; + int lines = substrings.size() - 1; + for (; i < text.size(); i++) { + if (text.is_breakpoint(i)) { + if ((i - lines < p_line || !text.is_breakpoint(i - lines)) || (i - lines == p_line && !shift_first_line)) + emit_signal("breakpoint_toggled", i); + if (i + lines >= text.size() || !text.is_breakpoint(i + lines)) + emit_signal("breakpoint_toggled", i + lines); + } + } + + /* STEP 3 add spaces if the char is greater than the end of the line */ while (p_char > text[p_line].length()) { text.set(p_line, text[p_line] + String::chr(' ')); } - /* STEP 2 separate dest string in pre and post text */ + /* STEP 4 separate dest string in pre and post text */ String preinsert_text = text[p_line].substr(0, p_char); String postinsert_text = text[p_line].substr(p_char, text[p_line].size()); - /* STEP 3 remove \r from source text and separate in substrings */ - - //buh bye \r and split - Vector<String> substrings = p_text.replace("\r", "").split("\n"); - for (int i = 0; i < substrings.size(); i++) { //insert the substrings @@ -3334,9 +3364,7 @@ void TextEdit::_base_insert_text(int p_line, int p_char, const String &p_text, i } } - // if we are just making a new empty line, reset breakpoints and hidden status - if (p_char == 0 && p_text.replace("\r", "") == "\n") { - + if (shift_first_line) { text.set_breakpoint(p_line + 1, text.is_breakpoint(p_line)); text.set_hidden(p_line + 1, text.is_hidden(p_line)); text.set_breakpoint(p_line, false); @@ -3392,11 +3420,20 @@ void TextEdit::_base_remove_text(int p_from_line, int p_from_column, int p_to_li String pre_text = text[p_from_line].substr(0, p_from_column); String post_text = text[p_to_line].substr(p_to_column, text[p_to_line].length()); - for (int i = p_from_line; i < p_to_line; i++) { + int lines = p_to_line - p_from_line; - text.remove(p_from_line + 1); + for (int i = p_from_line + 1; i < text.size(); i++) { + if (text.is_breakpoint(i)) { + if (i + lines >= text.size() || !text.is_breakpoint(i + lines)) + emit_signal("breakpoint_toggled", i); + if (i > p_to_line && (i - lines < 0 || !text.is_breakpoint(i - lines))) + emit_signal("breakpoint_toggled", i - lines); + } } + for (int i = p_from_line; i < p_to_line; i++) { + text.remove(p_from_line + 1); + } text.set(p_from_line, pre_text + post_text); text.set_line_wrap_amount(p_from_line, -1); @@ -4869,6 +4906,24 @@ void TextEdit::get_breakpoints(List<int> *p_breakpoints) const { } } +Array TextEdit::get_breakpoints_array() const { + + Array arr; + for (int i = 0; i < text.size(); i++) { + if (text.is_breakpoint(i)) + arr.append(i); + } + return arr; +} + +void TextEdit::remove_breakpoints() { + for (int i = 0; i < text.size(); i++) { + if (text.is_breakpoint(i)) + /* Should "breakpoint_toggled" be fired when breakpoints are removed this way? */ + text.set_breakpoint(i, false); + } +} + void TextEdit::set_line_as_hidden(int p_line, bool p_hidden) { ERR_FAIL_INDEX(p_line, text.size()); @@ -5538,7 +5593,17 @@ void TextEdit::_confirm_completion() { cursor_set_column(cursor.column - completion_base.length(), false); insert_text_at_cursor(completion_current); - if (completion_current.ends_with("(") && auto_brace_completion_enabled) { + // When inserted into the middle of an existing string, don't add an unnecessary quote + String line = text[cursor.line]; + CharType next_char = line[cursor.column]; + CharType last_completion_char = completion_current[completion_current.length() - 1]; + + if ((last_completion_char == '"' || last_completion_char == '\'') && + last_completion_char == next_char) { + _base_remove_text(cursor.line, cursor.column, cursor.line, cursor.column + 1); + } + + if (last_completion_char == '(' && auto_brace_completion_enabled) { insert_text_at_cursor(")"); cursor.column--; } @@ -5765,18 +5830,23 @@ String TextEdit::get_word_at_pos(const Vector2 &p_pos) const { if (select_word(s, col, beg, end)) { bool inside_quotes = false; + char selected_quote = '\0'; int qbegin = 0, qend = 0; for (int i = 0; i < s.length(); i++) { - if (s[i] == '"') { - if (inside_quotes) { - qend = i; - inside_quotes = false; - if (col >= qbegin && col <= qend) { - return s.substr(qbegin, qend - qbegin); + if (s[i] == '"' || s[i] == '\'') { + if (i == 0 || s[i - 1] != '\\') { + if (inside_quotes && selected_quote == s[i]) { + qend = i; + inside_quotes = false; + selected_quote = '\0'; + if (col >= qbegin && col <= qend) { + return s.substr(qbegin, qend - qbegin); + } + } else if (!inside_quotes) { + qbegin = i + 1; + inside_quotes = true; + selected_quote = s[i]; } - } else { - qbegin = i + 1; - inside_quotes = true; } } } @@ -5857,12 +5927,12 @@ void TextEdit::set_line_length_guideline_column(int p_column) { update(); } -void TextEdit::set_draw_breakpoint_gutter(bool p_draw) { +void TextEdit::set_breakpoint_gutter_enabled(bool p_draw) { draw_breakpoint_gutter = p_draw; update(); } -bool TextEdit::is_drawing_breakpoint_gutter() const { +bool TextEdit::is_breakpoint_gutter_enabled() const { return draw_breakpoint_gutter; } @@ -6045,6 +6115,8 @@ void TextEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("set_show_line_numbers", "enable"), &TextEdit::set_show_line_numbers); ClassDB::bind_method(D_METHOD("is_show_line_numbers_enabled"), &TextEdit::is_show_line_numbers_enabled); + ClassDB::bind_method(D_METHOD("set_breakpoint_gutter_enabled", "enable"), &TextEdit::set_breakpoint_gutter_enabled); + ClassDB::bind_method(D_METHOD("is_breakpoint_gutter_enabled"), &TextEdit::is_breakpoint_gutter_enabled); ClassDB::bind_method(D_METHOD("set_hiding_enabled", "enable"), &TextEdit::set_hiding_enabled); ClassDB::bind_method(D_METHOD("is_hiding_enabled"), &TextEdit::is_hiding_enabled); @@ -6083,11 +6155,15 @@ void TextEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("menu_option", "option"), &TextEdit::menu_option); ClassDB::bind_method(D_METHOD("get_menu"), &TextEdit::get_menu); + ClassDB::bind_method(D_METHOD("get_breakpoints"), &TextEdit::get_breakpoints_array); + ClassDB::bind_method(D_METHOD("remove_breakpoints"), &TextEdit::remove_breakpoints); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT), "set_text", "get_text"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "readonly"), "set_readonly", "is_readonly"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "highlight_current_line"), "set_highlight_current_line", "is_highlight_current_line_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "syntax_highlighting"), "set_syntax_coloring", "is_syntax_coloring_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_line_numbers"), "set_show_line_numbers", "is_show_line_numbers_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "breakpoint_gutter"), "set_breakpoint_gutter_enabled", "is_breakpoint_gutter_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "highlight_all_occurrences"), "set_highlight_all_occurrences", "is_highlight_all_occurrences_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "override_selected_font_color"), "set_override_selected_font_color", "is_overriding_selected_font_color"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "context_menu_enabled"), "set_context_menu_enabled", "is_context_menu_enabled"); diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index 5c82d1ac20..586f4c8e93 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -473,6 +473,8 @@ public: void set_line_as_breakpoint(int p_line, bool p_breakpoint); bool is_line_set_as_breakpoint(int p_line) const; void get_breakpoints(List<int> *p_breakpoints) const; + Array get_breakpoints_array() const; + void remove_breakpoints(); void set_line_as_hidden(int p_line, bool p_hidden); bool is_line_hidden(int p_line) const; @@ -632,8 +634,8 @@ public: void set_show_line_length_guideline(bool p_show); void set_line_length_guideline_column(int p_column); - void set_draw_breakpoint_gutter(bool p_draw); - bool is_drawing_breakpoint_gutter() const; + void set_breakpoint_gutter_enabled(bool p_draw); + bool is_breakpoint_gutter_enabled() const; void set_breakpoint_gutter_width(int p_gutter_width); int get_breakpoint_gutter_width() const; diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp index ae21775c55..4750e05633 100644 --- a/scene/main/http_request.cpp +++ b/scene/main/http_request.cpp @@ -30,8 +30,6 @@ #include "http_request.h" -#include "version.h" - void HTTPRequest::_redirect_request(const String &p_new_url) { } @@ -106,28 +104,10 @@ Error HTTPRequest::request(const String &p_url, const Vector<String> &p_custom_h validate_ssl = p_ssl_validate_domain; - bool has_user_agent = false; - bool has_accept = false; headers = p_custom_headers; request_data = p_request_data; - for (int i = 0; i < headers.size(); i++) { - - if (headers[i].findn("user-agent:") == 0) - has_user_agent = true; - if (headers[i].findn("Accept:") == 0) - has_accept = true; - } - - if (!has_user_agent) { - headers.push_back("User-Agent: GodotEngine/" + String(VERSION_FULL_BUILD) + " (" + OS::get_singleton()->get_name() + ")"); - } - - if (!has_accept) { - headers.push_back("Accept: */*"); - } - requesting = true; if (use_threads) { diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 4dc7b03685..6d18cce21d 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -1895,7 +1895,7 @@ Node *Node::_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap) const // Skip nodes not really belonging to the instanced hierarchy; they'll be processed normally later // but remember non-instanced nodes that are hidden below instanced ones if (descendant->data.owner != this) { - if (descendant->get_parent() && descendant->get_parent() != this && descendant->get_parent()->data.owner == this) + if (descendant->get_parent() && descendant->get_parent() != this && descendant->get_parent()->data.owner == this && descendant->data.owner != descendant->get_parent()) hidden_roots.push_back(descendant); continue; } @@ -1934,8 +1934,9 @@ Node *Node::_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap) const if (E->get().usage & PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE) { Resource *res = Object::cast_to<Resource>(value); - if (res) // Duplicate only if it's a resource + if (res) { // Duplicate only if it's a resource current_node->set(name, res->duplicate()); + } } else { diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index 8d6e57b335..6438616cf2 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -498,7 +498,8 @@ bool SceneTree::idle(float p_time) { _notify_group_pause("idle_process_internal", Node::NOTIFICATION_INTERNAL_PROCESS); _notify_group_pause("idle_process", Node::NOTIFICATION_PROCESS); - Size2 win_size = Size2(OS::get_singleton()->get_video_mode().width, OS::get_singleton()->get_video_mode().height); + Size2 win_size = Size2(OS::get_singleton()->get_window_size().width, OS::get_singleton()->get_window_size().height); + if (win_size != last_screen_size) { last_screen_size = win_size; @@ -656,6 +657,11 @@ void SceneTree::_notification(int p_notification) { #endif } break; + case NOTIFICATION_CRASH: { + + get_root()->propagate_notification(p_notification); + } break; + default: break; }; @@ -1112,7 +1118,7 @@ void SceneTree::_update_root_rect() { } //actual screen video mode - Size2 video_mode = Size2(OS::get_singleton()->get_video_mode().width, OS::get_singleton()->get_video_mode().height); + Size2 video_mode = Size2(OS::get_singleton()->get_window_size().width, OS::get_singleton()->get_window_size().height); Size2 desired_res = stretch_min; Size2 viewport_size; @@ -2004,7 +2010,7 @@ SceneTree::SceneTree() { stretch_aspect = STRETCH_ASPECT_IGNORE; stretch_shrink = 1; - last_screen_size = Size2(OS::get_singleton()->get_video_mode().width, OS::get_singleton()->get_video_mode().height); + last_screen_size = Size2(OS::get_singleton()->get_window_size().width, OS::get_singleton()->get_window_size().height); _update_root_rect(); if (ScriptDebugger::get_singleton()) { diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index a894b82a94..01302d4214 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -626,7 +626,7 @@ Rect2 Viewport::get_visible_rect() const { if (size == Size2()) { - r = Rect2(Point2(), Size2(OS::get_singleton()->get_video_mode().width, OS::get_singleton()->get_video_mode().height)); + r = Rect2(Point2(), Size2(OS::get_singleton()->get_window_size().width, OS::get_singleton()->get_window_size().height)); } else { r = Rect2(Point2(), size); @@ -1404,6 +1404,8 @@ void Viewport::_gui_call_input(Control *p_control, const Ref<InputEvent> &p_inpu mb->get_button_index() == BUTTON_WHEEL_UP || mb->get_button_index() == BUTTON_WHEEL_LEFT || mb->get_button_index() == BUTTON_WHEEL_RIGHT)); + Ref<InputEventPanGesture> pn = p_input; + cant_stop_me_now = pn.is_valid() || cant_stop_me_now; bool ismouse = ev.is_valid() || Object::cast_to<InputEventMouseMotion>(*p_input) != NULL; diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index d64e6970bf..702953fa40 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -844,7 +844,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_constant("separation", "HBoxContainer", 4 * scale); theme->set_constant("separation", "VBoxContainer", 4 * scale); - theme->set_constant("margin_left", "MarginContainer", 8 * scale); + theme->set_constant("margin_left", "MarginContainer", 0 * scale); theme->set_constant("margin_top", "MarginContainer", 0 * scale); theme->set_constant("margin_right", "MarginContainer", 0 * scale); theme->set_constant("margin_bottom", "MarginContainer", 0 * scale); diff --git a/scene/resources/dynamic_font.cpp b/scene/resources/dynamic_font.cpp index 05493d5777..e5d463d391 100644 --- a/scene/resources/dynamic_font.cpp +++ b/scene/resources/dynamic_font.cpp @@ -625,7 +625,7 @@ void DynamicFontAtSize::_update_char(CharType p_char) { break; } - int error = FT_Load_Char(face, p_char, FT_HAS_COLOR(face) ? FT_LOAD_COLOR : FT_LOAD_DEFAULT | (font->force_autohinter ? FT_LOAD_FORCE_AUTOHINT : 0)); + int error = FT_Load_Char(face, p_char, FT_HAS_COLOR(face) ? FT_LOAD_COLOR : FT_LOAD_DEFAULT | (font->force_autohinter ? FT_LOAD_FORCE_AUTOHINT : 0) | ft_hinting); if (error) { char_map[p_char] = character; return; diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp index 3fab4d3cfc..d3da842b79 100644 --- a/scene/resources/environment.cpp +++ b/scene/resources/environment.cpp @@ -378,7 +378,7 @@ bool Environment::is_ssr_rough() const { void Environment::set_ssao_enabled(bool p_enable) { ssao_enabled = p_enable; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); + VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); _change_notify(); } @@ -390,7 +390,7 @@ bool Environment::is_ssao_enabled() const { void Environment::set_ssao_radius(float p_radius) { ssao_radius = p_radius; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); + VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); } float Environment::get_ssao_radius() const { @@ -400,7 +400,7 @@ float Environment::get_ssao_radius() const { void Environment::set_ssao_intensity(float p_intensity) { ssao_intensity = p_intensity; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); + VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); } float Environment::get_ssao_intensity() const { @@ -411,7 +411,7 @@ float Environment::get_ssao_intensity() const { void Environment::set_ssao_radius2(float p_radius) { ssao_radius2 = p_radius; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); + VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); } float Environment::get_ssao_radius2() const { @@ -421,7 +421,7 @@ float Environment::get_ssao_radius2() const { void Environment::set_ssao_intensity2(float p_intensity) { ssao_intensity2 = p_intensity; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); + VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); } float Environment::get_ssao_intensity2() const { @@ -431,7 +431,7 @@ float Environment::get_ssao_intensity2() const { void Environment::set_ssao_bias(float p_bias) { ssao_bias = p_bias; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); + VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); } float Environment::get_ssao_bias() const { @@ -441,17 +441,27 @@ float Environment::get_ssao_bias() const { void Environment::set_ssao_direct_light_affect(float p_direct_light_affect) { ssao_direct_light_affect = p_direct_light_affect; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); + VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); } float Environment::get_ssao_direct_light_affect() const { return ssao_direct_light_affect; } +void Environment::set_ssao_ao_channel_affect(float p_ao_channel_affect) { + + ssao_ao_channel_affect = p_ao_channel_affect; + VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); +} +float Environment::get_ssao_ao_channel_affect() const { + + return ssao_ao_channel_affect; +} + void Environment::set_ssao_color(const Color &p_color) { ssao_color = p_color; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); + VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); } Color Environment::get_ssao_color() const { @@ -462,7 +472,7 @@ Color Environment::get_ssao_color() const { void Environment::set_ssao_blur(SSAOBlur p_blur) { ssao_blur = p_blur; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); + VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); } Environment::SSAOBlur Environment::get_ssao_blur() const { @@ -472,7 +482,7 @@ Environment::SSAOBlur Environment::get_ssao_blur() const { void Environment::set_ssao_quality(SSAOQuality p_quality) { ssao_quality = p_quality; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); + VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); } Environment::SSAOQuality Environment::get_ssao_quality() const { @@ -483,7 +493,7 @@ Environment::SSAOQuality Environment::get_ssao_quality() const { void Environment::set_ssao_edge_sharpness(float p_edge_sharpness) { ssao_edge_sharpness = p_edge_sharpness; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); + VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); } float Environment::get_ssao_edge_sharpness() const { @@ -1008,6 +1018,9 @@ void Environment::_bind_methods() { ClassDB::bind_method(D_METHOD("set_ssao_direct_light_affect", "amount"), &Environment::set_ssao_direct_light_affect); ClassDB::bind_method(D_METHOD("get_ssao_direct_light_affect"), &Environment::get_ssao_direct_light_affect); + ClassDB::bind_method(D_METHOD("set_ssao_ao_channel_affect", "amount"), &Environment::set_ssao_ao_channel_affect); + ClassDB::bind_method(D_METHOD("get_ssao_ao_channel_affect"), &Environment::get_ssao_ao_channel_affect); + ClassDB::bind_method(D_METHOD("set_ssao_color", "color"), &Environment::set_ssao_color); ClassDB::bind_method(D_METHOD("get_ssao_color"), &Environment::get_ssao_color); @@ -1028,6 +1041,7 @@ void Environment::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::REAL, "ssao_intensity2", PROPERTY_HINT_RANGE, "0.0,128,0.1"), "set_ssao_intensity2", "get_ssao_intensity2"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "ssao_bias", PROPERTY_HINT_RANGE, "0.001,8,0.001"), "set_ssao_bias", "get_ssao_bias"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "ssao_light_affect", PROPERTY_HINT_RANGE, "0.00,1,0.01"), "set_ssao_direct_light_affect", "get_ssao_direct_light_affect"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "ssao_ao_channel_affect", PROPERTY_HINT_RANGE, "0.00,1,0.01"), "set_ssao_ao_channel_affect", "get_ssao_ao_channel_affect"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ssao_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_ssao_color", "get_ssao_color"); ADD_PROPERTY(PropertyInfo(Variant::INT, "ssao_quality", PROPERTY_HINT_ENUM, "Low,Medium,High"), "set_ssao_quality", "get_ssao_quality"); ADD_PROPERTY(PropertyInfo(Variant::INT, "ssao_blur", PROPERTY_HINT_ENUM, "Disabled,1x1,2x2,3x3"), "set_ssao_blur", "get_ssao_blur"); @@ -1220,6 +1234,7 @@ Environment::Environment() { ssao_intensity2 = 1; ssao_bias = 0.01; ssao_direct_light_affect = 0.0; + ssao_ao_channel_affect = 0.0; ssao_blur = SSAO_BLUR_3x3; set_ssao_edge_sharpness(4); set_ssao_quality(SSAO_QUALITY_LOW); diff --git a/scene/resources/environment.h b/scene/resources/environment.h index 27fd57aa09..7d66c7e60b 100644 --- a/scene/resources/environment.h +++ b/scene/resources/environment.h @@ -127,6 +127,7 @@ private: float ssao_intensity2; float ssao_bias; float ssao_direct_light_affect; + float ssao_ao_channel_affect; Color ssao_color; SSAOBlur ssao_blur; float ssao_edge_sharpness; @@ -274,6 +275,9 @@ public: void set_ssao_direct_light_affect(float p_direct_light_affect); float get_ssao_direct_light_affect() const; + void set_ssao_ao_channel_affect(float p_ao_channel_affect); + float get_ssao_ao_channel_affect() const; + void set_ssao_color(const Color &p_color); Color get_ssao_color() const; diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index 5e7569586a..654d7b884e 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -393,6 +393,9 @@ void SpatialMaterial::_update_shader() { if (flags[FLAG_DONT_RECEIVE_SHADOWS]) { code += ",shadows_disabled"; } + if (flags[FLAG_ENSURE_CORRECT_NORMALS]) { + code += ",ensure_correct_normals"; + } code += ";\n"; code += "uniform vec4 albedo : hint_color;\n"; @@ -1852,6 +1855,7 @@ void SpatialMaterial::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_fixed_size"), "set_flag", "get_flag", FLAG_FIXED_SIZE); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_albedo_tex_force_srgb"), "set_flag", "get_flag", FLAG_ALBEDO_TEXTURE_FORCE_SRGB); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_do_not_receive_shadows"), "set_flag", "get_flag", FLAG_DONT_RECEIVE_SHADOWS); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_ensure_correct_normals"), "set_flag", "get_flag", FLAG_ENSURE_CORRECT_NORMALS); ADD_GROUP("Vertex Color", "vertex_color"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "vertex_color_use_as_albedo"), "set_flag", "get_flag", FLAG_ALBEDO_FROM_VERTEX_COLOR); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "vertex_color_is_srgb"), "set_flag", "get_flag", FLAG_SRGB_VERTEX_COLOR); @@ -2042,6 +2046,7 @@ void SpatialMaterial::_bind_methods() { BIND_ENUM_CONSTANT(FLAG_TRIPLANAR_USE_WORLD); BIND_ENUM_CONSTANT(FLAG_ALBEDO_TEXTURE_FORCE_SRGB); BIND_ENUM_CONSTANT(FLAG_DONT_RECEIVE_SHADOWS); + BIND_ENUM_CONSTANT(FLAG_ENSURE_CORRECT_NORMALS); BIND_ENUM_CONSTANT(FLAG_MAX); BIND_ENUM_CONSTANT(DIFFUSE_BURLEY); diff --git a/scene/resources/material.h b/scene/resources/material.h index ce733bfb8d..87594213bc 100644 --- a/scene/resources/material.h +++ b/scene/resources/material.h @@ -189,6 +189,7 @@ public: FLAG_USE_ALPHA_SCISSOR, FLAG_ALBEDO_TEXTURE_FORCE_SRGB, FLAG_DONT_RECEIVE_SHADOWS, + FLAG_ENSURE_CORRECT_NORMALS, FLAG_MAX }; @@ -237,7 +238,7 @@ private: uint64_t blend_mode : 2; uint64_t depth_draw_mode : 2; uint64_t cull_mode : 2; - uint64_t flags : 15; + uint64_t flags : 16; uint64_t detail_blend_mode : 2; uint64_t diffuse_mode : 3; uint64_t specular_mode : 2; diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h index e8b7ecaf9a..a3fb068569 100644 --- a/scene/resources/mesh.h +++ b/scene/resources/mesh.h @@ -100,7 +100,7 @@ public: ARRAY_FLAG_USE_16_BIT_BONES = ARRAY_COMPRESS_INDEX << 2, ARRAY_FLAG_USE_DYNAMIC_UPDATE = ARRAY_COMPRESS_INDEX << 3, - ARRAY_COMPRESS_DEFAULT = ARRAY_COMPRESS_VERTEX | ARRAY_COMPRESS_NORMAL | ARRAY_COMPRESS_TANGENT | ARRAY_COMPRESS_COLOR | ARRAY_COMPRESS_TEX_UV | ARRAY_COMPRESS_TEX_UV2 | ARRAY_COMPRESS_WEIGHTS + ARRAY_COMPRESS_DEFAULT = ARRAY_COMPRESS_NORMAL | ARRAY_COMPRESS_TANGENT | ARRAY_COMPRESS_COLOR | ARRAY_COMPRESS_TEX_UV | ARRAY_COMPRESS_TEX_UV2 | ARRAY_COMPRESS_WEIGHTS }; diff --git a/scene/resources/theme.h b/scene/resources/theme.h index c23f237c75..e0d4038e7e 100644 --- a/scene/resources/theme.h +++ b/scene/resources/theme.h @@ -55,12 +55,12 @@ class Theme : public Resource { void _unref_font(Ref<Font> p_sc); void _emit_theme_changed(); - HashMap<StringName, HashMap<StringName, Ref<Texture>, StringNameHasher>, StringNameHasher> icon_map; - HashMap<StringName, HashMap<StringName, Ref<StyleBox>, StringNameHasher>, StringNameHasher> style_map; - HashMap<StringName, HashMap<StringName, Ref<Font>, StringNameHasher>, StringNameHasher> font_map; - HashMap<StringName, HashMap<StringName, Ref<Shader>, StringNameHasher>, StringNameHasher> shader_map; - HashMap<StringName, HashMap<StringName, Color, StringNameHasher>, StringNameHasher> color_map; - HashMap<StringName, HashMap<StringName, int, StringNameHasher>, StringNameHasher> constant_map; + HashMap<StringName, HashMap<StringName, Ref<Texture> > > icon_map; + HashMap<StringName, HashMap<StringName, Ref<StyleBox> > > style_map; + HashMap<StringName, HashMap<StringName, Ref<Font> > > font_map; + HashMap<StringName, HashMap<StringName, Ref<Shader> > > shader_map; + HashMap<StringName, HashMap<StringName, Color> > color_map; + HashMap<StringName, HashMap<StringName, int> > constant_map; protected: bool _set(const StringName &p_name, const Variant &p_value); |