diff options
Diffstat (limited to 'scene')
56 files changed, 578 insertions, 380 deletions
diff --git a/scene/2d/animated_sprite.cpp b/scene/2d/animated_sprite.cpp index f290a181ec..824f50495b 100644 --- a/scene/2d/animated_sprite.cpp +++ b/scene/2d/animated_sprite.cpp @@ -34,7 +34,51 @@ #define NORMAL_SUFFIX "_normal" -//////////////////////////// +Dictionary AnimatedSprite::_edit_get_state() const { + Dictionary state = Node2D::_edit_get_state(); + state["offset"] = offset; + return state; +} + +void AnimatedSprite::_edit_set_state(const Dictionary &p_state) { + Node2D::_edit_set_state(p_state); + set_offset(p_state["offset"]); +} + +void AnimatedSprite::_edit_set_pivot(const Point2 &p_pivot) { + set_offset(get_offset() - p_pivot); + set_position(get_transform().xform(p_pivot)); +} + +Point2 AnimatedSprite::_edit_get_pivot() const { + return Vector2(); +} + +bool AnimatedSprite::_edit_use_pivot() const { + return true; +} + +Rect2 AnimatedSprite::_edit_get_rect() const { + if (!frames.is_valid() || !frames->has_animation(animation) || frame < 0 || frame >= frames->get_frame_count(animation)) { + return Node2D::_edit_get_rect(); + } + + Ref<Texture> t; + if (animation) + t = frames->get_frame(animation, frame); + if (t.is_null()) + return Node2D::_edit_get_rect(); + Size2 s = t->get_size(); + + Point2 ofs = offset; + if (centered) + ofs -= s / 2; + + if (s == Size2(0, 0)) + s = Size2(1, 1); + + return Rect2(ofs, s); +} void SpriteFrames::add_frame(const StringName &p_anim, const Ref<Texture> &p_frame, int p_at_pos) { @@ -248,20 +292,6 @@ SpriteFrames::SpriteFrames() { add_animation(SceneStringNames::get_singleton()->_default); } -void AnimatedSprite::_edit_set_pivot(const Point2 &p_pivot) { - - set_offset(p_pivot); -} - -Point2 AnimatedSprite::_edit_get_pivot() const { - - return get_offset(); -} -bool AnimatedSprite::_edit_use_pivot() const { - - return true; -} - void AnimatedSprite::_validate_property(PropertyInfo &property) const { if (!frames.is_valid()) @@ -491,29 +521,6 @@ bool AnimatedSprite::is_flipped_v() const { return vflip; } -Rect2 AnimatedSprite::_edit_get_rect() const { - - if (!frames.is_valid() || !frames->has_animation(animation) || frame < 0 || frame >= frames->get_frame_count(animation)) { - return Node2D::_edit_get_rect(); - } - - Ref<Texture> t; - if (animation) - t = frames->get_frame(animation, frame); - if (t.is_null()) - return Node2D::_edit_get_rect(); - Size2i s = t->get_size(); - - Point2 ofs = offset; - if (centered) - ofs -= s / 2; - - if (s == Size2(0, 0)) - s = Size2(1, 1); - - return Rect2(ofs, s); -} - void AnimatedSprite::_res_changed() { set_frame(frame); diff --git a/scene/2d/animated_sprite.h b/scene/2d/animated_sprite.h index 2c356d619f..a38adf792c 100644 --- a/scene/2d/animated_sprite.h +++ b/scene/2d/animated_sprite.h @@ -150,9 +150,13 @@ protected: virtual void _validate_property(PropertyInfo &property) const; public: + virtual Dictionary _edit_get_state() const; + virtual void _edit_set_state(const Dictionary &p_state); + virtual void _edit_set_pivot(const Point2 &p_pivot); virtual Point2 _edit_get_pivot() const; virtual bool _edit_use_pivot() const; + virtual Rect2 _edit_get_rect() const; void set_sprite_frames(const Ref<SpriteFrames> &p_frames); Ref<SpriteFrames> get_sprite_frames() const; @@ -182,8 +186,6 @@ public: void set_modulate(const Color &p_color); Color get_modulate() const; - virtual Rect2 _edit_get_rect() const; - virtual String get_configuration_warning() const; AnimatedSprite(); }; diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp index 6fff7ac0a4..bb914b90fc 100644 --- a/scene/2d/area_2d.cpp +++ b/scene/2d/area_2d.cpp @@ -399,7 +399,7 @@ void Area2D::set_monitoring(bool p_enable) { if (p_enable == monitoring) return; if (locked) { - ERR_EXPLAIN("Function blocked during in/out signal. Use call_deferred(\"set_enable_monitoring\",true/false)"); + ERR_EXPLAIN("Function blocked during in/out signal. Use call_deferred(\"set_monitoring\",true/false)"); } ERR_FAIL_COND(locked); diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp index b11deb08fd..fc67d28a29 100644 --- a/scene/2d/audio_stream_player_2d.cpp +++ b/scene/2d/audio_stream_player_2d.cpp @@ -54,7 +54,7 @@ void AudioStreamPlayer2D::_mix_audio() { int buffer_size = mix_buffer.size(); //mix - stream_playback->mix(buffer, 1.0, buffer_size); + stream_playback->mix(buffer, pitch_scale, buffer_size); //write all outputs for (int i = 0; i < output_count; i++) { @@ -279,6 +279,13 @@ float AudioStreamPlayer2D::get_volume_db() const { return volume_db; } +void AudioStreamPlayer2D::set_pitch_scale(float p_pitch_scale) { + pitch_scale = p_pitch_scale; +} +float AudioStreamPlayer2D::get_pitch_scale() const { + return pitch_scale; +} + void AudioStreamPlayer2D::play(float p_from_pos) { if (stream_playback.is_valid()) { @@ -419,6 +426,9 @@ void AudioStreamPlayer2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_volume_db", "volume_db"), &AudioStreamPlayer2D::set_volume_db); ClassDB::bind_method(D_METHOD("get_volume_db"), &AudioStreamPlayer2D::get_volume_db); + ClassDB::bind_method(D_METHOD("set_pitch_scale", "pitch_scale"), &AudioStreamPlayer2D::set_pitch_scale); + ClassDB::bind_method(D_METHOD("get_pitch_scale"), &AudioStreamPlayer2D::get_pitch_scale); + ClassDB::bind_method(D_METHOD("play", "from_position"), &AudioStreamPlayer2D::play, DEFVAL(0.0)); ClassDB::bind_method(D_METHOD("seek", "to_position"), &AudioStreamPlayer2D::seek); ClassDB::bind_method(D_METHOD("stop"), &AudioStreamPlayer2D::stop); @@ -448,6 +458,7 @@ void AudioStreamPlayer2D::_bind_methods() { 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::REAL, "max_distance", PROPERTY_HINT_RANGE, "1,65536,1"), "set_max_distance", "get_max_distance"); @@ -461,6 +472,7 @@ void AudioStreamPlayer2D::_bind_methods() { AudioStreamPlayer2D::AudioStreamPlayer2D() { volume_db = 0; + pitch_scale = 1.0; autoplay = false; setseek = -1; active = false; diff --git a/scene/2d/audio_stream_player_2d.h b/scene/2d/audio_stream_player_2d.h index 39bc985f58..9ae8e3a518 100644 --- a/scene/2d/audio_stream_player_2d.h +++ b/scene/2d/audio_stream_player_2d.h @@ -70,6 +70,7 @@ private: volatile float setplay; float volume_db; + float pitch_scale; bool autoplay; StringName bus; @@ -98,6 +99,9 @@ public: void set_volume_db(float p_volume); float get_volume_db() const; + void set_pitch_scale(float p_pitch_scale); + float get_pitch_scale() const; + void play(float p_from_pos = 0.0); void seek(float p_seconds); void stop(); diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h index 7e5bea0511..68384b9f1e 100644 --- a/scene/2d/canvas_item.h +++ b/scene/2d/canvas_item.h @@ -230,7 +230,7 @@ public: // Used to resize/move/select the node virtual void _edit_set_rect(const Rect2 &p_rect){}; virtual Rect2 _edit_get_rect() const { return Rect2(-32, -32, 64, 64); }; - virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { return true; } + virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { return _edit_get_rect().has_point(p_point); } Rect2 _edit_get_item_and_children_rect() const; virtual bool _edit_use_rect() const { return false; }; diff --git a/scene/2d/joints_2d.cpp b/scene/2d/joints_2d.cpp index 7a96a54854..329382c034 100644 --- a/scene/2d/joints_2d.cpp +++ b/scene/2d/joints_2d.cpp @@ -75,8 +75,7 @@ void Joint2D::_update_joint(bool p_only_free) { ba = body_a->get_rid(); bb = body_b->get_rid(); - if (exclude_from_collision) - Physics2DServer::get_singleton()->body_add_collision_exception(body_a->get_rid(), body_b->get_rid()); + Physics2DServer::get_singleton()->joint_disable_collisions_between_bodies(joint, exclude_from_collision); } void Joint2D::set_node_a(const NodePath &p_node_a) { diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp index 999d8a2630..1220ff299c 100644 --- a/scene/2d/light_2d.cpp +++ b/scene/2d/light_2d.cpp @@ -33,35 +33,36 @@ #include "engine.h" #include "servers/visual_server.h" -void Light2D::_edit_set_pivot(const Point2 &p_pivot) { +Dictionary Light2D::_edit_get_state() const { + Dictionary state = Node2D::_edit_get_state(); + state["offset"] = get_texture_offset(); + return state; +} - set_texture_offset(p_pivot); +void Light2D::_edit_set_state(const Dictionary &p_state) { + Node2D::_edit_set_state(p_state); + set_texture_offset(p_state["offset"]); } -Point2 Light2D::_edit_get_pivot() const { +void Light2D::_edit_set_pivot(const Point2 &p_pivot) { + set_position(get_transform().xform(p_pivot)); + set_texture_offset(get_texture_offset() - p_pivot); +} - return get_texture_offset(); +Point2 Light2D::_edit_get_pivot() const { + return Vector2(); } -bool Light2D::_edit_use_pivot() const { +bool Light2D::_edit_use_pivot() const { return true; } Rect2 Light2D::_edit_get_rect() const { - if (texture.is_null()) - return Rect2(0, 0, 1, 1); - - Size2i s; - - s = texture->get_size() * _scale; - Point2i ofs = texture_offset; - ofs -= s / 2; - - if (s == Size2(0, 0)) - s = Size2(1, 1); + return Node2D::_edit_get_rect(); - return Rect2(ofs, s); + Size2 s = texture->get_size() * _scale; + return Rect2(texture_offset - s / 2.0, s); } void Light2D::_update_light_visibility() { @@ -131,6 +132,7 @@ void Light2D::set_texture_offset(const Vector2 &p_offset) { texture_offset = p_offset; VS::get_singleton()->canvas_light_set_texture_offset(canvas_light, texture_offset); item_rect_changed(); + _change_notify("offset"); } Vector2 Light2D::get_texture_offset() const { diff --git a/scene/2d/light_2d.h b/scene/2d/light_2d.h index b216ad5e95..16d8c485d4 100644 --- a/scene/2d/light_2d.h +++ b/scene/2d/light_2d.h @@ -85,6 +85,9 @@ protected: static void _bind_methods(); public: + virtual Dictionary _edit_get_state() const; + virtual void _edit_set_state(const Dictionary &p_state); + virtual void _edit_set_pivot(const Point2 &p_pivot); virtual Point2 _edit_get_pivot() const; virtual bool _edit_use_pivot() const; diff --git a/scene/2d/line_builder.cpp b/scene/2d/line_builder.cpp index e78d2e9c34..b1a072729f 100644 --- a/scene/2d/line_builder.cpp +++ b/scene/2d/line_builder.cpp @@ -347,7 +347,7 @@ void LineBuilder::build() { } if (intersection_result != SEGMENT_INTERSECT) - // In this case the joint is too fucked up to be re-used, + // In this case the joint is too corrputed to be re-used, // start again the strip with fallback points strip_begin(pos_up0, pos_down0, color1, uvx1); } diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp index 95a1cbfce3..95e24505be 100644 --- a/scene/2d/node_2d.cpp +++ b/scene/2d/node_2d.cpp @@ -46,10 +46,9 @@ Dictionary Node2D::_edit_get_state() const { } void Node2D::_edit_set_state(const Dictionary &p_state) { - Dictionary state = p_state; - pos = state["position"]; - angle = state["rotation"]; - _scale = state["scale"]; + pos = p_state["position"]; + angle = p_state["rotation"]; + _scale = p_state["scale"]; _update_transform(); _change_notify("rotation"); @@ -60,6 +59,8 @@ void Node2D::_edit_set_state(const Dictionary &p_state) { void Node2D::_edit_set_position(const Point2 &p_position) { pos = p_position; + _update_transform(); + _change_notify("position"); } Point2 Node2D::_edit_get_position() const { diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index cc99ce5f49..9908907ee9 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -372,9 +372,7 @@ bool RigidBody2D::_test_motion(const Vector2 &p_motion, float p_margin, const Re void RigidBody2D::_direct_state_changed(Object *p_state) { -//eh.. fuck #ifdef DEBUG_ENABLED - state = Object::cast_to<Physics2DDirectBodyState>(p_state); #else state = (Physics2DDirectBodyState *)p_state; //trust it diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp index f6cb796b10..e63dc4e515 100644 --- a/scene/2d/polygon_2d.cpp +++ b/scene/2d/polygon_2d.cpp @@ -31,8 +31,31 @@ #include "polygon_2d.h" #include "core/math/geometry.h" -Rect2 Polygon2D::_edit_get_rect() const { +Dictionary Polygon2D::_edit_get_state() const { + Dictionary state = Node2D::_edit_get_state(); + state["offset"] = offset; + return state; +} + +void Polygon2D::_edit_set_state(const Dictionary &p_state) { + Node2D::_edit_set_state(p_state); + set_offset(p_state["offset"]); +} + +void Polygon2D::_edit_set_pivot(const Point2 &p_pivot) { + set_position(get_transform().xform(p_pivot)); + set_offset(get_offset() - p_pivot); +} + +Point2 Polygon2D::_edit_get_pivot() const { + return Vector2(); +} + +bool Polygon2D::_edit_use_pivot() const { + return true; +} +Rect2 Polygon2D::_edit_get_rect() const { if (rect_cache_dirty) { int l = polygon.size(); PoolVector<Vector2>::Read r = polygon.read(); @@ -52,21 +75,7 @@ Rect2 Polygon2D::_edit_get_rect() const { bool Polygon2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { - return Geometry::is_point_in_polygon(p_point, Variant(polygon)); -} - -void Polygon2D::_edit_set_pivot(const Point2 &p_pivot) { - - set_offset(p_pivot); -} - -Point2 Polygon2D::_edit_get_pivot() const { - - return get_offset(); -} -bool Polygon2D::_edit_use_pivot() const { - - return true; + return Geometry::is_point_in_polygon(p_point - get_offset(), Variant(polygon)); } void Polygon2D::_notification(int p_what) { @@ -324,6 +333,7 @@ void Polygon2D::set_offset(const Vector2 &p_offset) { offset = p_offset; rect_cache_dirty = true; update(); + _change_notify("offset"); } Vector2 Polygon2D::get_offset() const { diff --git a/scene/2d/polygon_2d.h b/scene/2d/polygon_2d.h index f62c78c55b..66f44cb3f1 100644 --- a/scene/2d/polygon_2d.h +++ b/scene/2d/polygon_2d.h @@ -59,6 +59,16 @@ protected: static void _bind_methods(); public: + virtual Dictionary _edit_get_state() const; + virtual void _edit_set_state(const Dictionary &p_state); + + virtual void _edit_set_pivot(const Point2 &p_pivot); + virtual Point2 _edit_get_pivot() const; + virtual bool _edit_use_pivot() const; + virtual Rect2 _edit_get_rect() const; + + virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; + void set_polygon(const PoolVector<Vector2> &p_polygon); PoolVector<Vector2> get_polygon() const; @@ -98,15 +108,6 @@ public: void set_offset(const Vector2 &p_offset); Vector2 get_offset() const; - //editor stuff - - virtual void _edit_set_pivot(const Point2 &p_pivot); - virtual Point2 _edit_get_pivot() const; - virtual bool _edit_use_pivot() const; - - virtual Rect2 _edit_get_rect() const; - virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; - Polygon2D(); }; diff --git a/scene/2d/sprite.cpp b/scene/2d/sprite.cpp index 9c344b9581..17ca066fc0 100644 --- a/scene/2d/sprite.cpp +++ b/scene/2d/sprite.cpp @@ -34,17 +34,27 @@ #include "scene/main/viewport.h" #include "scene/scene_string_names.h" -void Sprite::_edit_set_pivot(const Point2 &p_pivot) { +Dictionary Sprite::_edit_get_state() const { + Dictionary state = Node2D::_edit_get_state(); + state["offset"] = offset; + return state; +} - set_offset(p_pivot); +void Sprite::_edit_set_state(const Dictionary &p_state) { + Node2D::_edit_set_state(p_state); + set_offset(p_state["offset"]); } -Point2 Sprite::_edit_get_pivot() const { +void Sprite::_edit_set_pivot(const Point2 &p_pivot) { + set_offset(get_offset() - p_pivot); + set_position(get_transform().xform(p_pivot)); +} - return get_offset(); +Point2 Sprite::_edit_get_pivot() const { + return Vector2(); } -bool Sprite::_edit_use_pivot() const { +bool Sprite::_edit_use_pivot() const { return true; } diff --git a/scene/2d/sprite.h b/scene/2d/sprite.h index 261165bbf9..0422e0635f 100644 --- a/scene/2d/sprite.h +++ b/scene/2d/sprite.h @@ -65,6 +65,9 @@ protected: virtual void _validate_property(PropertyInfo &property) const; public: + virtual Dictionary _edit_get_state() const; + virtual void _edit_set_state(const Dictionary &p_state); + virtual void _edit_set_pivot(const Point2 &p_pivot); virtual Point2 _edit_get_pivot() const; virtual bool _edit_use_pivot() const; diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp index bf3bc42e4e..d448ef024d 100644 --- a/scene/3d/audio_stream_player_3d.cpp +++ b/scene/3d/audio_stream_player_3d.cpp @@ -57,18 +57,18 @@ void AudioStreamPlayer3D::_mix_audio() { //mix if (output_count > 0 || out_of_range_mode == OUT_OF_RANGE_MIX) { - float pitch_scale = 0.0; + float output_pitch_scale = 0.0; if (output_count) { //used for doppler, not realistic but good enough for (int i = 0; i < output_count; i++) { - pitch_scale += outputs[i].pitch_scale; + output_pitch_scale += outputs[i].pitch_scale; } - pitch_scale /= float(output_count); + output_pitch_scale /= float(output_count); } else { - pitch_scale = 1.0; + output_pitch_scale = 1.0; } - stream_playback->mix(buffer, pitch_scale, buffer_size); + stream_playback->mix(buffer, pitch_scale * output_pitch_scale, buffer_size); } //write all outputs @@ -607,6 +607,13 @@ float AudioStreamPlayer3D::get_max_db() const { return max_db; } +void AudioStreamPlayer3D::set_pitch_scale(float p_pitch_scale) { + pitch_scale = p_pitch_scale; +} +float AudioStreamPlayer3D::get_pitch_scale() const { + return pitch_scale; +} + void AudioStreamPlayer3D::play(float p_from_pos) { if (stream_playback.is_valid()) { @@ -832,6 +839,9 @@ void AudioStreamPlayer3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_max_db", "max_db"), &AudioStreamPlayer3D::set_max_db); ClassDB::bind_method(D_METHOD("get_max_db"), &AudioStreamPlayer3D::get_max_db); + ClassDB::bind_method(D_METHOD("set_pitch_scale", "pitch_scale"), &AudioStreamPlayer3D::set_pitch_scale); + ClassDB::bind_method(D_METHOD("get_pitch_scale"), &AudioStreamPlayer3D::get_pitch_scale); + ClassDB::bind_method(D_METHOD("play", "from_position"), &AudioStreamPlayer3D::play, DEFVAL(0.0)); ClassDB::bind_method(D_METHOD("seek", "to_position"), &AudioStreamPlayer3D::seek); ClassDB::bind_method(D_METHOD("stop"), &AudioStreamPlayer3D::stop); @@ -885,6 +895,7 @@ void AudioStreamPlayer3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::REAL, "unit_db", PROPERTY_HINT_RANGE, "-80,80"), "set_unit_db", "get_unit_db"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "unit_size", PROPERTY_HINT_RANGE, "0.1,100,0.1"), "set_unit_size", "get_unit_size"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "max_db", PROPERTY_HINT_RANGE, "-24,6"), "set_max_db", "get_max_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::REAL, "max_distance", PROPERTY_HINT_RANGE, "0,65536,1"), "set_max_distance", "get_max_distance"); @@ -921,6 +932,7 @@ AudioStreamPlayer3D::AudioStreamPlayer3D() { unit_size = 1; attenuation_model = ATTENUATION_INVERSE_DISTANCE; max_db = 3; + pitch_scale = 1.0; autoplay = false; setseek = -1; active = false; diff --git a/scene/3d/audio_stream_player_3d.h b/scene/3d/audio_stream_player_3d.h index 9a1f369da2..1fcb83cf21 100644 --- a/scene/3d/audio_stream_player_3d.h +++ b/scene/3d/audio_stream_player_3d.h @@ -106,6 +106,7 @@ private: float unit_db; float unit_size; float max_db; + float pitch_scale; bool autoplay; StringName bus; @@ -153,6 +154,9 @@ public: void set_max_db(float p_boost); float get_max_db() const; + void set_pitch_scale(float p_pitch_scale); + float get_pitch_scale() const; + void play(float p_from_pos = 0.0); void seek(float p_seconds); void stop(); diff --git a/scene/3d/baked_lightmap.cpp b/scene/3d/baked_lightmap.cpp index fa4e6492a1..204aaef7ec 100644 --- a/scene/3d/baked_lightmap.cpp +++ b/scene/3d/baked_lightmap.cpp @@ -316,7 +316,7 @@ bool BakedLightmap::_bake_time(void *ud, float p_secs, float p_progress) { int mins_left = p_secs / 60; int secs_left = Math::fmod(p_secs, 60.0f); int percent = p_progress * 100; - bool abort = bake_step_function(btd->pass + percent, btd->text + " " + itos(percent) + "% (Time Left: " + itos(mins_left) + ":" + itos(secs_left) + "s)"); + bool abort = bake_step_function(btd->pass + percent, btd->text + " " + vformat(RTR("%d%%"), percent) + " " + vformat(RTR("(Time Left: %d:%02d s)"), mins_left, secs_left)); btd->last_step = time; if (abort) return true; diff --git a/scene/3d/camera.h b/scene/3d/camera.h index 3fd3303a25..e2679870de 100644 --- a/scene/3d/camera.h +++ b/scene/3d/camera.h @@ -97,7 +97,7 @@ protected: void _update_camera_mode(); void _notification(int p_what); - virtual void _validate_property(PropertyInfo &property) const; + virtual void _validate_property(PropertyInfo &p_property) const; static void _bind_methods(); diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index 25acd6deb0..5c814312dd 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -370,9 +370,7 @@ struct _RigidBodyInOut { void RigidBody::_direct_state_changed(Object *p_state) { -//eh.. fuck #ifdef DEBUG_ENABLED - state = Object::cast_to<PhysicsDirectBodyState>(p_state); #else state = (PhysicsDirectBodyState *)p_state; //trust it diff --git a/scene/3d/physics_joint.cpp b/scene/3d/physics_joint.cpp index fed6d76f65..2e9f1a241a 100644 --- a/scene/3d/physics_joint.cpp +++ b/scene/3d/physics_joint.cpp @@ -71,8 +71,7 @@ void Joint::_update_joint(bool p_only_free) { ba = body_a->get_rid(); bb = body_b->get_rid(); - if (exclude_from_collision) - PhysicsServer::get_singleton()->body_add_collision_exception(body_a->get_rid(), body_b->get_rid()); + PhysicsServer::get_singleton()->joint_disable_collisions_between_bodies(joint, exclude_from_collision); } void Joint::set_node_a(const NodePath &p_node_a) { diff --git a/scene/audio/audio_player.cpp b/scene/audio/audio_player.cpp index cf070c2235..408c00334a 100644 --- a/scene/audio/audio_player.cpp +++ b/scene/audio/audio_player.cpp @@ -45,7 +45,7 @@ void AudioStreamPlayer::_mix_internal(bool p_fadeout) { } //mix - stream_playback->mix(buffer, 1.0, buffer_size); + 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; @@ -126,8 +126,8 @@ void AudioStreamPlayer::_notification(int p_what) { if (!active || (setseek < 0 && !stream_playback->is_playing())) { active = false; - emit_signal("finished"); set_process_internal(false); + emit_signal("finished"); } } @@ -177,6 +177,13 @@ float AudioStreamPlayer::get_volume_db() const { return volume_db; } +void AudioStreamPlayer::set_pitch_scale(float p_pitch_scale) { + pitch_scale = p_pitch_scale; +} +float AudioStreamPlayer::get_pitch_scale() const { + return pitch_scale; +} + void AudioStreamPlayer::play(float p_from_pos) { if (stream_playback.is_valid()) { @@ -297,6 +304,9 @@ void AudioStreamPlayer::_bind_methods() { ClassDB::bind_method(D_METHOD("set_volume_db", "volume_db"), &AudioStreamPlayer::set_volume_db); ClassDB::bind_method(D_METHOD("get_volume_db"), &AudioStreamPlayer::get_volume_db); + ClassDB::bind_method(D_METHOD("set_pitch_scale", "pitch_scale"), &AudioStreamPlayer::set_pitch_scale); + ClassDB::bind_method(D_METHOD("get_pitch_scale"), &AudioStreamPlayer::get_pitch_scale); + ClassDB::bind_method(D_METHOD("play", "from_position"), &AudioStreamPlayer::play, DEFVAL(0.0)); ClassDB::bind_method(D_METHOD("seek", "to_position"), &AudioStreamPlayer::seek); ClassDB::bind_method(D_METHOD("stop"), &AudioStreamPlayer::stop); @@ -320,6 +330,7 @@ void AudioStreamPlayer::_bind_methods() { 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::INT, "mix_target", PROPERTY_HINT_ENUM, "Stereo,Surround,Center"), "set_mix_target", "get_mix_target"); @@ -335,6 +346,7 @@ void AudioStreamPlayer::_bind_methods() { AudioStreamPlayer::AudioStreamPlayer() { mix_volume_db = 0; + pitch_scale = 1.0; volume_db = 0; autoplay = false; setseek = -1; diff --git a/scene/audio/audio_player.h b/scene/audio/audio_player.h index 4fee30c0c2..21189aea6d 100644 --- a/scene/audio/audio_player.h +++ b/scene/audio/audio_player.h @@ -54,6 +54,7 @@ private: volatile bool active; float mix_volume_db; + float pitch_scale; float volume_db; bool autoplay; StringName bus; @@ -81,6 +82,9 @@ public: void set_volume_db(float p_volume); float get_volume_db() const; + void set_pitch_scale(float p_pitch_scale); + float get_pitch_scale() const; + void play(float p_from_pos = 0.0); void seek(float p_seconds); void stop(); diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index 8b9469021c..5f541ea16a 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -307,14 +307,12 @@ void BaseButton::toggled(bool p_pressed) { } void BaseButton::set_disabled(bool p_disabled) { + if (status.disabled == p_disabled) + return; status.disabled = p_disabled; update(); _change_notify("disabled"); - if (p_disabled) - set_focus_mode(FOCUS_NONE); - else - set_focus_mode(enabled_focus_mode); } bool BaseButton::is_disabled() const { diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 01415594d3..a5883863cd 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -49,31 +49,41 @@ Dictionary Control::_edit_get_state() const { Dictionary s; - s["rect"] = get_rect(); s["rotation"] = get_rotation(); s["scale"] = get_scale(); + s["pivot"] = get_pivot_offset(); Array anchors; anchors.push_back(get_anchor(MARGIN_LEFT)); anchors.push_back(get_anchor(MARGIN_TOP)); anchors.push_back(get_anchor(MARGIN_RIGHT)); anchors.push_back(get_anchor(MARGIN_BOTTOM)); s["anchors"] = anchors; + Array margins; + margins.push_back(get_margin(MARGIN_LEFT)); + margins.push_back(get_margin(MARGIN_TOP)); + margins.push_back(get_margin(MARGIN_RIGHT)); + margins.push_back(get_margin(MARGIN_BOTTOM)); + s["margins"] = margins; return s; } void Control::_edit_set_state(const Dictionary &p_state) { Dictionary state = p_state; - Rect2 rect = state["rect"]; - set_position(rect.position); - set_size(rect.size); set_rotation(state["rotation"]); set_scale(state["scale"]); + set_pivot_offset(state["pivot"]); Array anchors = state["anchors"]; - set_anchor(MARGIN_LEFT, anchors[0]); - set_anchor(MARGIN_TOP, anchors[1]); - set_anchor(MARGIN_RIGHT, anchors[2]); - set_anchor(MARGIN_BOTTOM, anchors[3]); + data.anchor[MARGIN_LEFT] = anchors[0]; + data.anchor[MARGIN_TOP] = anchors[1]; + data.anchor[MARGIN_RIGHT] = anchors[2]; + data.anchor[MARGIN_BOTTOM] = anchors[3]; + Array margins = state["margins"]; + data.margin[MARGIN_LEFT] = margins[0]; + data.margin[MARGIN_TOP] = margins[1]; + data.margin[MARGIN_RIGHT] = margins[2]; + data.margin[MARGIN_BOTTOM] = margins[3]; + _size_changed(); } void Control::_edit_set_position(const Point2 &p_position) { @@ -85,19 +95,8 @@ Point2 Control::_edit_get_position() const { }; void Control::_edit_set_rect(const Rect2 &p_edit_rect) { - - Transform2D xform = _get_internal_transform(); - - Vector2 new_pos = xform.basis_xform(p_edit_rect.position); - - Vector2 pos = get_position() + new_pos; - - Rect2 new_rect = get_rect(); - new_rect.position = pos.snapped(Vector2(1, 1)); - new_rect.size = p_edit_rect.size.snapped(Vector2(1, 1)); - - set_position(new_rect.position); - set_size(new_rect.size); + set_position((get_position() + get_transform().basis_xform(p_edit_rect.position)).snapped(Vector2(1, 1))); + set_size(p_edit_rect.size.snapped(Vector2(1, 1))); } Rect2 Control::_edit_get_rect() const { @@ -121,6 +120,9 @@ bool Control::_edit_use_rotation() const { } void Control::_edit_set_pivot(const Point2 &p_pivot) { + Vector2 delta_pivot = p_pivot - get_pivot_offset(); + Vector2 move = Vector2((cos(data.rotation) - 1.0) * delta_pivot.x - sin(data.rotation) * delta_pivot.y, sin(data.rotation) * delta_pivot.x + (cos(data.rotation) - 1.0) * delta_pivot.y); + set_position(get_position() + move); set_pivot_offset(p_pivot); } @@ -1297,7 +1299,8 @@ void Control::_size_changed() { new_size_cache.height = MAX(minimum_size.height, new_size_cache.height); } - if (get_viewport()->is_snap_controls_to_pixels_enabled()) { + // 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(); } @@ -1378,7 +1381,6 @@ void Control::set_anchor(Margin p_margin, float p_anchor, bool p_keep_margin, bo data.margin[(p_margin + 2) % 4] = _s2a(previous_opposite_margin_pos, data.anchor[(p_margin + 2) % 4], parent_range); } } - if (is_inside_tree()) { _size_changed(); } @@ -2847,7 +2849,7 @@ void Control::_bind_methods() { ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "rect_rotation", PROPERTY_HINT_RANGE, "-1080,1080,0.01"), "set_rotation_degrees", "get_rotation_degrees"); ADD_PROPERTYNO(PropertyInfo(Variant::VECTOR2, "rect_scale"), "set_scale", "get_scale"); ADD_PROPERTYNO(PropertyInfo(Variant::VECTOR2, "rect_pivot_offset"), "set_pivot_offset", "get_pivot_offset"); - ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "rect_clip_content"), "set_clip_contents", "is_clipping_contents"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "rect_clip_content"), "set_clip_contents", "is_clipping_contents"); ADD_GROUP("Hint", "hint_"); ADD_PROPERTYNZ(PropertyInfo(Variant::STRING, "hint_tooltip", PROPERTY_HINT_MULTILINE_TEXT), "set_tooltip", "_get_tooltip"); diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index 1b5014367b..38ce91a4df 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -1147,9 +1147,18 @@ void GraphEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("is_node_connected", "from", "from_port", "to", "to_port"), &GraphEdit::is_node_connected); ClassDB::bind_method(D_METHOD("disconnect_node", "from", "from_port", "to", "to_port"), &GraphEdit::disconnect_node); ClassDB::bind_method(D_METHOD("get_connection_list"), &GraphEdit::_get_connection_list); + ClassDB::bind_method(D_METHOD("clear_connections"), &GraphEdit::clear_connections); ClassDB::bind_method(D_METHOD("get_scroll_ofs"), &GraphEdit::get_scroll_ofs); ClassDB::bind_method(D_METHOD("set_scroll_ofs", "ofs"), &GraphEdit::set_scroll_ofs); + ClassDB::bind_method(D_METHOD("add_valid_right_disconnect_type", "type"), &GraphEdit::add_valid_right_disconnect_type); + ClassDB::bind_method(D_METHOD("remove_valid_right_disconnect_type", "type"), &GraphEdit::remove_valid_right_disconnect_type); + ClassDB::bind_method(D_METHOD("add_valid_left_disconnect_type", "type"), &GraphEdit::add_valid_left_disconnect_type); + ClassDB::bind_method(D_METHOD("remove_valid_left_disconnect_type", "type"), &GraphEdit::remove_valid_left_disconnect_type); + ClassDB::bind_method(D_METHOD("add_valid_connection_type", "from_type", "to_type"), &GraphEdit::add_valid_connection_type); + ClassDB::bind_method(D_METHOD("remove_valid_connection_type", "from_type", "to_type"), &GraphEdit::remove_valid_connection_type); + ClassDB::bind_method(D_METHOD("is_valid_connection_type", "from_type", "to_type"), &GraphEdit::is_valid_connection_type); + ClassDB::bind_method(D_METHOD("set_zoom", "p_zoom"), &GraphEdit::set_zoom); ClassDB::bind_method(D_METHOD("get_zoom"), &GraphEdit::get_zoom); diff --git a/scene/gui/grid_container.cpp b/scene/gui/grid_container.cpp index 8c3f835be3..c2b8a7dfab 100644 --- a/scene/gui/grid_container.cpp +++ b/scene/gui/grid_container.cpp @@ -43,107 +43,118 @@ void GridContainer::_notification(int p_what) { int hsep = get_constant("hseparation"); int vsep = get_constant("vseparation"); + int max_col = MIN(get_child_count(), columns); + int max_row = get_child_count() / columns; - int idx = 0; - int max_row = 0; - int max_col = 0; - - Size2 size = get_size(); - + // Compute the per-column/per-row data for (int i = 0; i < get_child_count(); i++) { - Control *c = Object::cast_to<Control>(get_child(i)); if (!c || !c->is_visible_in_tree()) continue; - int row = idx / columns; - int col = idx % columns; + int row = i / columns; + int col = i % columns; Size2i ms = c->get_combined_minimum_size(); if (col_minw.has(col)) col_minw[col] = MAX(col_minw[col], ms.width); else col_minw[col] = ms.width; - if (row_minh.has(row)) row_minh[row] = MAX(row_minh[row], ms.height); else row_minh[row] = ms.height; - //print_line("store row "+itos(row)+" mw "+itos(ms.height)); - - if (c->get_h_size_flags() & SIZE_EXPAND) + if (c->get_h_size_flags() & SIZE_EXPAND) { col_expanded.insert(col); - if (c->get_v_size_flags() & SIZE_EXPAND) + } + if (c->get_v_size_flags() & SIZE_EXPAND) { row_expanded.insert(row); - - max_col = MAX(col, max_col); - max_row = MAX(row, max_row); - idx++; + } } - Size2 ms; - int expand_rows = 0; - int expand_cols = 0; - + // Evaluate the remaining space for expanded columns/rows + Size2 remaining_space = get_size(); for (Map<int, int>::Element *E = col_minw.front(); E; E = E->next()) { - ms.width += E->get(); - if (col_expanded.has(E->key())) - expand_cols++; + if (!col_expanded.has(E->key())) + remaining_space.width -= E->get(); } for (Map<int, int>::Element *E = row_minh.front(); E; E = E->next()) { - ms.height += E->get(); - if (row_expanded.has(E->key())) - expand_rows++; + if (!row_expanded.has(E->key())) + remaining_space.height -= E->get(); + } + remaining_space.height -= vsep * (max_row - 1); + remaining_space.width -= hsep * (max_col - 1); + + bool can_fit = false; + while (!can_fit) { + // Check if all minwidth constraints are ok if we use the remaining space + can_fit = true; + int max_index = 0; + for (Set<int>::Element *E = col_expanded.front(); E; E = E->next()) { + if (col_minw[E->get()] > col_minw[max_index]) { + max_index = col_minw[E->get()]; + } + if (can_fit && (remaining_space.width / col_expanded.size()) < col_minw[E->get()]) { + can_fit = false; + } + } + + // If not, the column with maximum minwidth is not expanded + if (!can_fit) { + col_expanded.erase(max_index); + remaining_space.width -= col_minw[max_index]; + } } - ms.height += vsep * max_row; - ms.width += hsep * max_col; + can_fit = false; + while (!can_fit) { + // Check if all minwidth constraints are ok if we use the remaining space + can_fit = true; + int max_index = 0; + for (Set<int>::Element *E = row_expanded.front(); E; E = E->next()) { + if (row_minh[E->get()] > row_minh[max_index]) { + max_index = row_minh[E->get()]; + } + if (can_fit && (remaining_space.height / row_expanded.size()) < row_minh[E->get()]) { + can_fit = false; + } + } + + // If not, the row with maximum minwidth is not expanded + if (!can_fit) { + row_expanded.erase(max_index); + remaining_space.height -= row_minh[max_index]; + } + } - int row_expand = expand_rows ? (size.y - ms.y) / expand_rows : 0; - int col_expand = expand_cols ? (size.x - ms.x) / expand_cols : 0; + // Finally, fit the nodes + int col_expand = remaining_space.width / col_expanded.size(); + int row_expand = remaining_space.height / row_expanded.size(); int col_ofs = 0; int row_ofs = 0; - idx = 0; for (int i = 0; i < get_child_count(); i++) { - Control *c = Object::cast_to<Control>(get_child(i)); if (!c || !c->is_visible_in_tree()) continue; - int row = idx / columns; - int col = idx % columns; + int row = i / columns; + int col = i % columns; if (col == 0) { col_ofs = 0; - if (row > 0 && row_minh.has(row - 1)) - row_ofs += row_minh[row - 1] + vsep + (row_expanded.has(row - 1) ? row_expand : 0); + if (row > 0) + row_ofs += ((row_expanded.has(row - 1)) ? row_expand : row_minh[row - 1]) + vsep; } - Size2 s; - if (col_minw.has(col)) - s.width = col_minw[col]; - if (row_minh.has(row)) - s.height = row_minh[row]; - - if (row_expanded.has(row)) - s.height += row_expand; - if (col_expanded.has(col)) - s.width += col_expand; - Point2 p(col_ofs, row_ofs); + Size2 s((col_expanded.has(col)) ? col_expand : col_minw[col], (row_expanded.has(row)) ? row_expand : row_minh[row]); - //print_line("col: "+itos(col)+" row: "+itos(row)+" col_ofs: "+itos(col_ofs)+" row_ofs: "+itos(row_ofs)); fit_child_in_rect(c, Rect2(p, s)); - //print_line("col: "+itos(col)+" row: "+itos(row)+" rect: "+Rect2(p,s)); - - if (col_minw.has(col)) { - col_ofs += col_minw[col] + hsep + (col_expanded.has(col) ? col_expand : 0); - } - idx++; + col_ofs += s.width + hsep; } } break; diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index 77d3a34c66..fe85d04003 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -517,11 +517,11 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) { emit_signal("item_rmb_selected", i, get_local_mouse_position()); } else { - bool selected = !items[i].selected; + bool selected = items[i].selected; select(i, select_mode == SELECT_SINGLE || !mb->get_command()); - if (selected) { + if (!selected || allow_reselect) { if (select_mode == SELECT_SINGLE) { emit_signal("item_selected", i); } else @@ -1241,6 +1241,7 @@ int ItemList::find_metadata(const Variant &p_metadata) const { } void ItemList::set_allow_rmb_select(bool p_allow) { + allow_rmb_select = p_allow; } @@ -1249,6 +1250,16 @@ bool ItemList::get_allow_rmb_select() const { return allow_rmb_select; } +void ItemList::set_allow_reselect(bool p_allow) { + + allow_reselect = p_allow; +} + +bool ItemList::get_allow_reselect() const { + + return allow_reselect; +} + void ItemList::set_icon_scale(real_t p_scale) { icon_scale = p_scale; } @@ -1404,6 +1415,9 @@ void ItemList::_bind_methods() { ClassDB::bind_method(D_METHOD("set_allow_rmb_select", "allow"), &ItemList::set_allow_rmb_select); ClassDB::bind_method(D_METHOD("get_allow_rmb_select"), &ItemList::get_allow_rmb_select); + ClassDB::bind_method(D_METHOD("set_allow_reselect", "allow"), &ItemList::set_allow_reselect); + ClassDB::bind_method(D_METHOD("get_allow_reselect"), &ItemList::get_allow_reselect); + ClassDB::bind_method(D_METHOD("set_auto_height", "enable"), &ItemList::set_auto_height); ClassDB::bind_method(D_METHOD("has_auto_height"), &ItemList::has_auto_height); @@ -1422,6 +1436,7 @@ void ItemList::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "items", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_items", "_get_items"); ADD_PROPERTY(PropertyInfo(Variant::INT, "select_mode", PROPERTY_HINT_ENUM, "Single,Multi"), "set_select_mode", "get_select_mode"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_reselect"), "set_allow_reselect", "get_allow_reselect"); ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "allow_rmb_select"), "set_allow_rmb_select", "get_allow_rmb_select"); ADD_PROPERTYNO(PropertyInfo(Variant::INT, "max_text_lines"), "set_max_text_lines", "get_max_text_lines"); ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "auto_height"), "set_auto_height", "has_auto_height"); @@ -1432,7 +1447,7 @@ void ItemList::_bind_methods() { ADD_GROUP("Icon", ""); ADD_PROPERTY(PropertyInfo(Variant::INT, "icon_mode", PROPERTY_HINT_ENUM, "Top,Left"), "set_icon_mode", "get_icon_mode"); ADD_PROPERTYNO(PropertyInfo(Variant::REAL, "icon_scale"), "set_icon_scale", "get_icon_scale"); - ADD_PROPERTYNO(PropertyInfo(Variant::REAL, "fixed_icon_size"), "set_fixed_icon_size", "get_fixed_icon_size"); + ADD_PROPERTYNO(PropertyInfo(Variant::VECTOR2, "fixed_icon_size"), "set_fixed_icon_size", "get_fixed_icon_size"); BIND_ENUM_CONSTANT(ICON_MODE_TOP); BIND_ENUM_CONSTANT(ICON_MODE_LEFT); @@ -1476,6 +1491,7 @@ ItemList::ItemList() { ensure_selected_visible = false; defer_select_single = -1; allow_rmb_select = false; + allow_reselect = false; do_autoscroll_to_bottom = false; icon_scale = 1.0f; diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h index 24e9498044..7f34a250bd 100644 --- a/scene/gui/item_list.h +++ b/scene/gui/item_list.h @@ -106,6 +106,8 @@ private: bool allow_rmb_select; + bool allow_reselect; + real_t icon_scale; bool do_autoscroll_to_bottom; @@ -198,6 +200,9 @@ public: void set_allow_rmb_select(bool p_allow); bool get_allow_rmb_select() const; + void set_allow_reselect(bool p_allow); + bool get_allow_reselect() const; + void ensure_current_is_visible(); void sort_items_by_text(); diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 524a68a116..03dc6686b8 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -30,6 +30,7 @@ #include "line_edit.h" #include "label.h" +#include "message_queue.h" #include "os/keyboard.h" #include "os/os.h" #include "print_string.h" @@ -800,7 +801,12 @@ void LineEdit::paste_text() { if (selection.enabled) selection_delete(); append_at_cursor(paste_buffer); - _text_changed(); + if (!text_changed_dirty) { + if (is_inside_tree()) { + MessageQueue::get_singleton()->push_call(this, "_text_changed"); + } + text_changed_dirty = true; + } } } @@ -974,7 +980,12 @@ void LineEdit::delete_text(int p_from_column, int p_to_column) { window_pos = cursor_pos; } - _text_changed(); + if (!text_changed_dirty) { + if (is_inside_tree()) { + MessageQueue::get_singleton()->push_call(this, "_text_changed"); + } + text_changed_dirty = true; + } } void LineEdit::set_text(String p_text) { @@ -1341,6 +1352,7 @@ void LineEdit::_text_changed() { void LineEdit::_emit_text_change() { emit_signal("text_changed", text); _change_notify("text"); + text_changed_dirty = false; } void LineEdit::_clear_redo() { @@ -1373,6 +1385,7 @@ void LineEdit::_create_undo_state() { void LineEdit::_bind_methods() { + ClassDB::bind_method(D_METHOD("_text_changed"), &LineEdit::_text_changed); ClassDB::bind_method(D_METHOD("_toggle_draw_caret"), &LineEdit::_toggle_draw_caret); #ifdef TOOLS_ENABLED @@ -1458,6 +1471,7 @@ LineEdit::LineEdit() { window_has_focus = true; max_length = 0; pass = false; + text_changed_dirty = false; placeholder_alpha = 0.6; deselect(); diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h index e15980d3c4..e3ad3b17f1 100644 --- a/scene/gui/line_edit.h +++ b/scene/gui/line_edit.h @@ -67,6 +67,7 @@ private: bool editable; bool pass; + bool text_changed_dirty; String undo_text; String text; diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp index 1a46921561..71c14810f6 100644 --- a/scene/gui/option_button.cpp +++ b/scene/gui/option_button.cpp @@ -318,8 +318,9 @@ void OptionButton::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_items"), &OptionButton::_set_items); ClassDB::bind_method(D_METHOD("_get_items"), &OptionButton::_get_items); - ADD_PROPERTY(PropertyInfo(Variant::INT, "selected"), "_select_int", "get_selected"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "items", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_items", "_get_items"); + // "selected" property must come after "items", otherwise GH-10213 occurs + ADD_PROPERTY(PropertyInfo(Variant::INT, "selected"), "_select_int", "get_selected"); ADD_SIGNAL(MethodInfo("item_selected", PropertyInfo(Variant::INT, "ID"))); } diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index a7419519ae..381c6c75a5 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -121,6 +121,8 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & if (p_mode == PROCESS_CACHE) { l.offset_caches.clear(); l.height_caches.clear(); + l.ascent_caches.clear(); + l.descent_caches.clear(); l.char_count = 0; l.minimum_width = 0; } @@ -140,6 +142,8 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & //line height should be the font height for the first time, this ensures that an empty line will never have zero height and successive newlines are displayed int line_height = cfont->get_height(); + int line_ascent = cfont->get_ascent(); + int line_descent = cfont->get_descent(); int nonblank_line_count = 0; //number of nonblank lines as counted during PROCESS_DRAW @@ -169,16 +173,22 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & case ALIGN_FILL: l.offset_caches.push_back((p_width - margin) - used /*+spaces_size*/); break; \ } \ l.height_caches.push_back(line_height); \ + l.ascent_caches.push_back(line_ascent); \ + l.descent_caches.push_back(line_descent); \ l.space_caches.push_back(spaces); \ } \ y += line_height + get_constant(SceneStringNames::get_singleton()->line_separation); \ line_height = 0; \ + line_ascent = 0; \ + line_descent = 0; \ spaces = 0; \ spaces_size = 0; \ wofs = begin; \ align_ofs = 0; \ if (p_mode != PROCESS_CACHE) { \ lh = line < l.height_caches.size() ? l.height_caches[line] : 1; \ + line_ascent = line < l.ascent_caches.size() ? l.ascent_caches[line] : 1; \ + line_descent = line < l.descent_caches.size() ? l.descent_caches[line] : 1; \ } \ if (p_mode == PROCESS_POINTER && r_click_item && p_click_pos.y >= p_ofs.y + y && p_click_pos.y <= p_ofs.y + y + lh && p_click_pos.x < p_ofs.x + wofs) { \ if (r_outside) *r_outside = true; \ @@ -254,6 +264,12 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & const CharType *cf = c; int fh = font->get_height(); int ascent = font->get_ascent(); + int descent = font->get_descent(); + + line_ascent = MAX(line_ascent, ascent); + line_descent = MAX(line_descent, descent); + fh = MAX(fh, line_ascent + line_descent); // various fonts! + Color color; bool underline = false; @@ -280,6 +296,8 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & lh = 0; if (p_mode != PROCESS_CACHE) { lh = line < l.height_caches.size() ? l.height_caches[line] : 1; + line_ascent = line < l.ascent_caches.size() ? l.ascent_caches[line] : 1; + line_descent = line < l.descent_caches.size() ? l.descent_caches[line] : 1; } while (c[end] != 0 && !(end && c[end - 1] == ' ' && c[end] != ' ')) { @@ -348,7 +366,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & int cw = 0; - bool visible = visible_characters < 0 || p_char_count < visible_characters && YRANGE_VISIBLE(y + lh - (fh - 0 * ascent), fh); //getting rid of ascent seems to work?? + bool visible = visible_characters < 0 || p_char_count < visible_characters && YRANGE_VISIBLE(y + lh - line_descent - line_ascent, line_ascent + line_descent); if (visible) line_is_blank = false; @@ -360,11 +378,11 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & cw = font->get_char_size(c[i], c[i + 1]).x; draw_rect(Rect2(p_ofs.x + pofs, p_ofs.y + y, cw, lh), selection_bg); if (visible) - font->draw_char(ci, p_ofs + Point2(align_ofs + pofs, y + lh - (fh - ascent)), c[i], c[i + 1], override_selected_font_color ? selection_fg : color); + font->draw_char(ci, p_ofs + Point2(align_ofs + pofs, y + lh - line_descent), c[i], c[i + 1], override_selected_font_color ? selection_fg : color); } else { if (visible) - cw = font->draw_char(ci, p_ofs + Point2(align_ofs + pofs, y + lh - (fh - ascent)), c[i], c[i + 1], color); + cw = font->draw_char(ci, p_ofs + Point2(align_ofs + pofs, y + lh - line_descent), c[i], c[i + 1], color); } p_char_count++; @@ -379,7 +397,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & if (underline) { Color uc = color; uc.a *= 0.5; - int uy = y + lh - fh + ascent + 2; + int uy = y + lh - line_descent + 2; float underline_width = 1.0; #ifdef TOOLS_ENABLED underline_width *= EDSCALE; diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h index 48f746e28d..e7d5e6bb1b 100644 --- a/scene/gui/rich_text_label.h +++ b/scene/gui/rich_text_label.h @@ -80,6 +80,8 @@ private: Item *from; Vector<int> offset_caches; Vector<int> height_caches; + Vector<int> ascent_caches; + Vector<int> descent_caches; Vector<int> space_caches; int height_cache; int height_accum_cache; diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp index 3c5d524d80..145981d498 100644 --- a/scene/gui/spin_box.cpp +++ b/scene/gui/spin_box.cpp @@ -185,17 +185,22 @@ void SpinBox::_line_edit_focus_exit() { _text_entered(line_edit->get_text()); } +inline void SpinBox::_adjust_width_for_icon(const Ref<Texture> icon) { + + int w = icon->get_width(); + if (w != last_w) { + line_edit->set_margin(MARGIN_RIGHT, -w); + last_w = w; + } +} + void SpinBox::_notification(int p_what) { if (p_what == NOTIFICATION_DRAW) { Ref<Texture> updown = get_icon("updown"); - int w = updown->get_width(); - if (w != last_w) { - line_edit->set_margin(MARGIN_RIGHT, -w); - last_w = w; - } + _adjust_width_for_icon(updown); RID ci = get_canvas_item(); Size2i size = get_size(); @@ -207,6 +212,7 @@ void SpinBox::_notification(int p_what) { //_value_changed(0); } else if (p_what == NOTIFICATION_ENTER_TREE) { + _adjust_width_for_icon(get_icon("updown")); _value_changed(0); } } diff --git a/scene/gui/spin_box.h b/scene/gui/spin_box.h index b8565ec082..8863f44bef 100644 --- a/scene/gui/spin_box.h +++ b/scene/gui/spin_box.h @@ -62,6 +62,8 @@ class SpinBox : public Range { void _line_edit_focus_exit(); + inline void _adjust_width_for_icon(const Ref<Texture> icon); + protected: void _gui_input(const Ref<InputEvent> &p_event); diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp index e1d49019b3..bf7033e8ba 100644 --- a/scene/gui/split_container.cpp +++ b/scene/gui/split_container.cpp @@ -61,127 +61,69 @@ Control *SplitContainer::_getch(int p_idx) const { } void SplitContainer::_resort() { - - /* First pass, determine minimum size AND amount of stretchable elements */ - int axis = vertical ? 1 : 0; - bool has_first = _getch(0); - bool has_second = _getch(1); + Control *first = _getch(0); + Control *second = _getch(1); - if (!has_first && !has_second) { - return; - } else if (!(has_first && has_second)) { - if (has_first) + // If we have only one element + if (!first || !second) { + if (first) { fit_child_in_rect(_getch(0), Rect2(Point2(), get_size())); - else + } else if (second) { fit_child_in_rect(_getch(1), Rect2(Point2(), get_size())); - + } return; } - Control *first = _getch(0); - Control *second = _getch(1); - - bool ratiomode = false; - bool expand_first_mode = false; - + // Determine expanded children + bool first_expanded = false; + bool second_expanded = false; if (vertical) { - - ratiomode = first->get_v_size_flags() & SIZE_EXPAND && second->get_v_size_flags() & SIZE_EXPAND; - expand_first_mode = first->get_v_size_flags() & SIZE_EXPAND && !(second->get_v_size_flags() & SIZE_EXPAND); + first_expanded = first->get_v_size_flags() & SIZE_EXPAND; + second_expanded = second->get_v_size_flags() & SIZE_EXPAND; } else { - - ratiomode = first->get_h_size_flags() & SIZE_EXPAND && second->get_h_size_flags() & SIZE_EXPAND; - expand_first_mode = first->get_h_size_flags() & SIZE_EXPAND && !(second->get_h_size_flags() & SIZE_EXPAND); + first_expanded = first->get_h_size_flags() & SIZE_EXPAND; + second_expanded = second->get_h_size_flags() & SIZE_EXPAND; } - int sep = get_constant("separation"); + // Determine the separation between items Ref<Texture> g = get_icon("grabber"); - + int sep = get_constant("separation"); if (dragger_visibility == DRAGGER_HIDDEN_COLLAPSED) { sep = 0; } else { sep = MAX(sep, vertical ? g->get_height() : g->get_width()); } - int total = vertical ? get_size().height : get_size().width; - - total -= sep; - - int minimum = 0; - + // Compute the minimum size Size2 ms_first = first->get_combined_minimum_size(); Size2 ms_second = second->get_combined_minimum_size(); - if (vertical) { - minimum = ms_first.height + ms_second.height; - } else { - minimum = ms_first.width + ms_second.width; - } - - int available = total - minimum; - if (available < 0) - available = 0; - - middle_sep = 0; - - if (collapsed) { - - if (ratiomode) { - - int first_ratio = first->get_stretch_ratio(); - int second_ratio = second->get_stretch_ratio(); - - float ratio = float(first_ratio) / (first_ratio + second_ratio); - - middle_sep = ms_first[axis] + available * ratio; - - } else if (expand_first_mode) { - - middle_sep = get_size()[axis] - ms_second[axis] - sep; - } else { - - middle_sep = ms_first[axis]; - } - } else if (ratiomode) { - - int first_ratio = first->get_stretch_ratio(); - int second_ratio = second->get_stretch_ratio(); - - float ratio = float(first_ratio) / (first_ratio + second_ratio); - - if (expand_ofs < -(available * ratio)) - expand_ofs = -(available * ratio); - else if (expand_ofs > (available * (1.0 - ratio))) - expand_ofs = (available * (1.0 - ratio)); - - middle_sep = ms_first[axis] + available * ratio + expand_ofs; - } else if (expand_first_mode) { + float ratio = first->get_stretch_ratio() / (first->get_stretch_ratio() + second->get_stretch_ratio()); - if (expand_ofs > 0) - expand_ofs = 0; - else if (expand_ofs < -available) - expand_ofs = -available; - - middle_sep = get_size()[axis] - ms_second[axis] - sep + expand_ofs; + int no_offset_middle_sep = 0; + if (first_expanded && second_expanded) { + no_offset_middle_sep = get_size()[axis] * ratio - sep / 2; + } else if (first_expanded) { + no_offset_middle_sep = get_size()[axis] - ms_second[axis] - sep; } else { + no_offset_middle_sep = ms_first[axis]; + } - if (expand_ofs < 0) - expand_ofs = 0; - else if (expand_ofs > available) - expand_ofs = available; - - middle_sep = ms_first[axis] + expand_ofs; + middle_sep = no_offset_middle_sep; + middle_sep += (collapsed) ? 0 : split_offset; + middle_sep = MIN(middle_sep, get_size()[axis] - ms_second[axis] - sep); + middle_sep = MAX(middle_sep, ms_first[axis]); + if (!collapsed) { + split_offset = middle_sep - no_offset_middle_sep; } if (vertical) { - fit_child_in_rect(first, Rect2(Point2(0, 0), Size2(get_size().width, middle_sep))); int sofs = middle_sep + sep; fit_child_in_rect(second, Rect2(Point2(0, sofs), Size2(get_size().width, get_size().height - sofs))); } else { - fit_child_in_rect(first, Rect2(Point2(0, 0), Size2(middle_sep, get_size().height))); int sofs = middle_sep + sep; fit_child_in_rect(second, Rect2(Point2(sofs, 0), Size2(get_size().width - sofs, get_size().height))); @@ -290,7 +232,7 @@ void SplitContainer::_gui_input(const Ref<InputEvent> &p_event) { dragging = true; drag_from = mb->get_position().y; - drag_ofs = expand_ofs; + drag_ofs = split_offset; } } else { @@ -298,7 +240,7 @@ void SplitContainer::_gui_input(const Ref<InputEvent> &p_event) { dragging = true; drag_from = mb->get_position().x; - drag_ofs = expand_ofs; + drag_ofs = split_offset; } } } else { @@ -312,7 +254,7 @@ void SplitContainer::_gui_input(const Ref<InputEvent> &p_event) { if (mm.is_valid() && dragging) { - expand_ofs = drag_ofs + ((vertical ? mm->get_position().y : mm->get_position().x) - drag_from); + split_offset = drag_ofs + ((vertical ? mm->get_position().y : mm->get_position().x) - drag_from); queue_sort(); emit_signal("dragged", get_split_offset()); } @@ -343,16 +285,16 @@ Control::CursorShape SplitContainer::get_cursor_shape(const Point2 &p_pos) const void SplitContainer::set_split_offset(int p_offset) { - if (expand_ofs == p_offset) + if (split_offset == p_offset) return; - expand_ofs = p_offset; + split_offset = p_offset; queue_sort(); } int SplitContainer::get_split_offset() const { - return expand_ofs; + return split_offset; } void SplitContainer::set_collapsed(bool p_collapsed) { @@ -407,7 +349,7 @@ void SplitContainer::_bind_methods() { SplitContainer::SplitContainer(bool p_vertical) { mouse_inside = false; - expand_ofs = 0; + split_offset = 0; middle_sep = 0; vertical = p_vertical; dragging = false; diff --git a/scene/gui/split_container.h b/scene/gui/split_container.h index a31dc766d2..321f7fd3b7 100644 --- a/scene/gui/split_container.h +++ b/scene/gui/split_container.h @@ -46,7 +46,7 @@ public: private: bool vertical; - int expand_ofs; + int split_offset; int middle_sep; bool dragging; int drag_from; diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 95bd676a08..e8454e021f 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -217,7 +217,7 @@ void TextEdit::Text::_update_line_cache(int p_line) const { } } -const Map<int, TextEdit::Text::ColorRegionInfo> &TextEdit::Text::get_color_region_info(int p_line) { +const Map<int, TextEdit::Text::ColorRegionInfo> &TextEdit::Text::get_color_region_info(int p_line) const { static Map<int, ColorRegionInfo> cri; ERR_FAIL_INDEX_V(p_line, text.size(), cri); @@ -890,7 +890,7 @@ void TextEdit::_notification(int p_what) { } else { // if it has text, then draw current line marker in the margin, as line number etc will draw over it, draw the rest of line marker later. if (line == cursor.line && highlight_current_line) { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(0, ofs_y, xmargin_beg, get_row_height()), cache.current_line_color); + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(0, ofs_y, xmargin_beg + ofs_x, get_row_height()), cache.current_line_color); } } @@ -1122,14 +1122,14 @@ void TextEdit::_notification(int p_what) { // line highlighting handle horizontal clipping if (line == cursor.line && highlight_current_line) { - // char next to margin is skipped - if ((char_ofs + char_margin) > xmargin_beg) { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y, (char_ofs + char_margin) - (xmargin_beg + ofs_x), get_row_height()), cache.current_line_color); - } - // end of line when last char is skipped if (j == str.length() - 1) { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y, xmargin_end - (char_ofs + char_margin + char_w), get_row_height()), cache.current_line_color); + // end of line when last char is skipped + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y, xmargin_end - (xmargin_beg + ofs_x), get_row_height()), cache.current_line_color); + + } else if ((char_ofs + char_margin) > xmargin_beg) { + // char next to margin is skipped + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y, (char_ofs + char_margin) - xmargin_beg, get_row_height()), cache.current_line_color); } } continue; @@ -4710,8 +4710,6 @@ int TextEdit::get_indent_level(int p_line) const { tab_count++; } else if (text[p_line][i] == ' ') { whitespace_count++; - } else if (text[p_line][i] == '#') { - break; } else { break; } @@ -4719,6 +4717,31 @@ int TextEdit::get_indent_level(int p_line) const { return tab_count + whitespace_count / indent_size; } +bool TextEdit::is_line_comment(int p_line) const { + + // checks to see if this line is the start of a comment + ERR_FAIL_INDEX_V(p_line, text.size(), false); + + const Map<int, Text::ColorRegionInfo> &cri_map = text.get_color_region_info(p_line); + + int line_length = text[p_line].size(); + for (int i = 0; i < line_length - 1; i++) { + if (_is_symbol(text[p_line][i]) && cri_map.has(i)) { + const Text::ColorRegionInfo &cri = cri_map[i]; + if (color_regions[cri.region].begin_key == "#" || color_regions[cri.region].begin_key == "//") { + return true; + } else { + return false; + } + } else if (_is_whitespace(text[p_line][i])) { + continue; + } else { + break; + } + } + return false; +} + bool TextEdit::can_fold(int p_line) const { ERR_FAIL_INDEX_V(p_line, text.size(), false); @@ -4732,6 +4755,8 @@ bool TextEdit::can_fold(int p_line) const { return false; if (is_line_hidden(p_line)) return false; + if (is_line_comment(p_line)) + return false; int start_indent = get_indent_level(p_line); @@ -4739,10 +4764,13 @@ bool TextEdit::can_fold(int p_line) const { if (text[i].size() == 0) continue; int next_indent = get_indent_level(i); - if (next_indent > start_indent) + if (is_line_comment(i)) { + continue; + } else if (next_indent > start_indent) { return true; - else + } else { return false; + } } return false; @@ -4771,7 +4799,9 @@ void TextEdit::fold_line(int p_line) { int last_line = start_indent; for (int i = p_line + 1; i < text.size(); i++) { if (text[i].strip_edges().size() != 0) { - if (get_indent_level(i) > start_indent) { + if (is_line_comment(i)) { + continue; + } else if (get_indent_level(i) > start_indent) { last_line = i; } else { break; diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index acbf41aa81..8ac3b9fce6 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -162,7 +162,7 @@ class TextEdit : public Control { void set_color_regions(const Vector<ColorRegion> *p_regions) { color_regions = p_regions; } int get_line_width(int p_line) const; int get_max_width(bool p_exclude_hidden = false) const; - const Map<int, ColorRegionInfo> &get_color_region_info(int p_line); + const Map<int, ColorRegionInfo> &get_color_region_info(int p_line) const; void set(int p_line, const String &p_text); void set_marked(int p_line, bool p_marked) { text[p_line].marked = p_marked; } bool is_marked(int p_line) const { return text[p_line].marked; } @@ -450,6 +450,7 @@ public: void indent_left(); void indent_right(); int get_indent_level(int p_line) const; + bool is_line_comment(int p_line) const; inline void set_scroll_pass_end_of_file(bool p_enabled) { scroll_past_end_of_file_enabled = p_enabled; diff --git a/scene/gui/texture_button.cpp b/scene/gui/texture_button.cpp index 07c9894611..6bd3b26280 100644 --- a/scene/gui/texture_button.cpp +++ b/scene/gui/texture_button.cpp @@ -29,6 +29,8 @@ /*************************************************************************/ #include "texture_button.h" +#include "core/typedefs.h" +#include <stdlib.h> Size2 TextureButton::get_minimum_size() const { @@ -58,10 +60,50 @@ bool TextureButton::has_point(const Point2 &p_point) const { if (click_mask.is_valid()) { - Point2i p = p_point; - if (p.x < 0 || p.x >= click_mask->get_size().width || p.y < 0 || p.y >= click_mask->get_size().height) + Point2 point = p_point; + Rect2 rect = Rect2(); + Size2 mask_size = click_mask->get_size(); + + if (_tile) { + // if the stretch mode is tile we offset the point to keep it inside the mask size + rect.size = mask_size; + if (_position_rect.has_point(point)) { + int cols = (int)Math::ceil(_position_rect.size.x / mask_size.x); + int rows = (int)Math::ceil(_position_rect.size.y / mask_size.y); + int col = (int)(point.x / mask_size.x) % cols; + int row = (int)(point.y / mask_size.y) % rows; + point.x -= mask_size.x * col; + point.y -= mask_size.y * row; + } + } else { + // we need to transform the point from our scaled / translated image back to our mask image + Point2 ofs = _position_rect.position; + Size2 scale = mask_size / _position_rect.size; + + switch (stretch_mode) { + case STRETCH_KEEP_ASPECT_COVERED: { + // if the stretch mode is aspect covered the image uses a texture region so we need to take that into account + float min = MIN(scale.x, scale.y); + scale.x = min; + scale.y = min; + ofs -= _texture_region.position / min; + } break; + } + + // offset and scale the new point position to adjust it to the bitmask size + point -= ofs; + point *= scale; + + // finally, we need to check if the point is inside a rectangle with a position >= 0,0 and a size <= mask_size + rect.position = Point2(MAX(0, _texture_region.position.x), MAX(0, _texture_region.position.y)); + rect.size = Size2(MIN(mask_size.x, _texture_region.size.x), MIN(mask_size.y, _texture_region.size.y)); + } + + if (!rect.has_point(point)) { return false; + } + Point2i p = point; return click_mask->get_bit(p); } @@ -118,8 +160,8 @@ void TextureButton::_notification(int p_what) { if (texdraw.is_valid()) { Point2 ofs; Size2 size = texdraw->get_size(); - Rect2 tex_regin = Rect2(Point2(), texdraw->get_size()); - bool tile = false; + _texture_region = Rect2(Point2(), texdraw->get_size()); + _tile = false; if (expand) { switch (stretch_mode) { case STRETCH_KEEP: @@ -130,7 +172,7 @@ void TextureButton::_notification(int p_what) { break; case STRETCH_TILE: size = get_size(); - tile = true; + _tile = true; break; case STRETCH_KEEP_CENTERED: ofs = (get_size() - texdraw->get_size()) / 2; @@ -161,14 +203,15 @@ void TextureButton::_notification(int p_what) { float scale = scaleSize.width > scaleSize.height ? scaleSize.width : scaleSize.height; Size2 scaledTexSize = tex_size * scale; Point2 ofs = ((scaledTexSize - size) / scale).abs() / 2.0f; - tex_regin = Rect2(ofs, size / scale); + _texture_region = Rect2(ofs, size / scale); } break; } } - if (tile) - draw_texture_rect(texdraw, Rect2(ofs, size), tile); + _position_rect = Rect2(ofs, size); + if (_tile) + draw_texture_rect(texdraw, _position_rect, _tile); else - draw_texture_rect_region(texdraw, Rect2(ofs, size), tex_regin); + draw_texture_rect_region(texdraw, _position_rect, _texture_region); } if (has_focus() && focused.is_valid()) { @@ -299,4 +342,8 @@ TextureButton::StretchMode TextureButton::get_stretch_mode() const { TextureButton::TextureButton() { expand = false; stretch_mode = STRETCH_SCALE; + + _texture_region = Rect2(); + _position_rect = Rect2(); + _tile = false; } diff --git a/scene/gui/texture_button.h b/scene/gui/texture_button.h index 1cf4b66413..d42df390e8 100644 --- a/scene/gui/texture_button.h +++ b/scene/gui/texture_button.h @@ -58,6 +58,10 @@ private: bool expand; StretchMode stretch_mode; + Rect2 _texture_region; + Rect2 _position_rect; + bool _tile; + protected: virtual Size2 get_minimum_size() const; virtual bool has_point(const Point2 &p_point) const; diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index e12044fca2..cdbdc9b0d7 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -2384,7 +2384,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) { if (mm.is_valid()) { - if (cache.font.is_null()) // avoid a strange case that may fuckup stuff + if (cache.font.is_null()) // avoid a strange case that may corrupt stuff update_cache(); Ref<StyleBox> bg = cache.bg; @@ -2483,7 +2483,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) { Ref<InputEventMouseButton> b = p_event; if (b.is_valid()) { - if (cache.font.is_null()) // avoid a strange case that may fuckup stuff + if (cache.font.is_null()) // avoid a strange case that may corrupt stuff update_cache(); if (!b->is_pressed()) { diff --git a/scene/main/node.h b/scene/main/node.h index dc6bda4621..4655071228 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -364,7 +364,7 @@ public: void queue_delete(); - //shitty hacks for speed + //hacks for speed static void set_human_readable_collision_renaming(bool p_enabled); static void init_node_hrcr(); diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index 6e58bc88d7..7a1fffaa26 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -1603,19 +1603,19 @@ float Animation::get_step() const { return step; } -void Animation::copy_track(int src_track, Ref<Animation> p_to_animation) { +void Animation::copy_track(int p_track, Ref<Animation> p_to_animation) { ERR_FAIL_COND(p_to_animation.is_null()); - ERR_FAIL_INDEX(src_track, get_track_count()); + ERR_FAIL_INDEX(p_track, get_track_count()); int dst_track = p_to_animation->get_track_count(); - p_to_animation->add_track(track_get_type(src_track)); - - p_to_animation->track_set_path(dst_track, track_get_path(src_track)); - p_to_animation->track_set_imported(dst_track, track_is_imported(src_track)); - p_to_animation->track_set_enabled(dst_track, track_is_enabled(src_track)); - p_to_animation->track_set_interpolation_type(dst_track, track_get_interpolation_type(src_track)); - p_to_animation->track_set_interpolation_loop_wrap(dst_track, track_get_interpolation_loop_wrap(src_track)); - for (int i = 0; i < track_get_key_count(src_track); i++) { - p_to_animation->track_insert_key(dst_track, track_get_key_time(src_track, i), track_get_key_value(src_track, i), track_get_key_transition(src_track, i)); + p_to_animation->add_track(track_get_type(p_track)); + + p_to_animation->track_set_path(dst_track, track_get_path(p_track)); + p_to_animation->track_set_imported(dst_track, track_is_imported(p_track)); + p_to_animation->track_set_enabled(dst_track, track_is_enabled(p_track)); + p_to_animation->track_set_interpolation_type(dst_track, track_get_interpolation_type(p_track)); + p_to_animation->track_set_interpolation_loop_wrap(dst_track, track_get_interpolation_loop_wrap(p_track)); + for (int i = 0; i < track_get_key_count(p_track); i++) { + p_to_animation->track_insert_key(dst_track, track_get_key_time(p_track, i), track_get_key_value(p_track, i), track_get_key_transition(p_track, i)); } } diff --git a/scene/resources/audio_stream_sample.cpp b/scene/resources/audio_stream_sample.cpp index 93ed700482..b77143cd9d 100644 --- a/scene/resources/audio_stream_sample.cpp +++ b/scene/resources/audio_stream_sample.cpp @@ -77,7 +77,7 @@ void AudioStreamPlaybackSample::seek(float p_time) { if (base->format == AudioStreamSample::FORMAT_IMA_ADPCM) return; //no seeking in ima-adpcm - float max = get_length(); + float max = base->get_length(); if (p_time < 0) { p_time = 0; } else if (p_time >= max) { @@ -390,22 +390,6 @@ void AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, in } } -float AudioStreamPlaybackSample::get_length() const { - - int len = base->data_bytes; - switch (base->format) { - case AudioStreamSample::FORMAT_8_BITS: len /= 1; break; - case AudioStreamSample::FORMAT_16_BITS: len /= 2; break; - case AudioStreamSample::FORMAT_IMA_ADPCM: len *= 2; break; - } - - if (base->stereo) { - len /= 2; - } - - return float(len) / base->mix_rate; -} - AudioStreamPlaybackSample::AudioStreamPlaybackSample() { active = false; @@ -469,6 +453,22 @@ bool AudioStreamSample::is_stereo() const { return stereo; } +float AudioStreamSample::get_length() const { + + int len = data_bytes; + switch (format) { + case AudioStreamSample::FORMAT_8_BITS: len /= 1; break; + case AudioStreamSample::FORMAT_16_BITS: len /= 2; break; + case AudioStreamSample::FORMAT_IMA_ADPCM: len *= 2; break; + } + + if (stereo) { + len /= 2; + } + + return float(len) / mix_rate; +} + void AudioStreamSample::set_data(const PoolVector<uint8_t> &p_data) { AudioServer::get_singleton()->lock(); diff --git a/scene/resources/audio_stream_sample.h b/scene/resources/audio_stream_sample.h index 41754301eb..5fe65c194e 100644 --- a/scene/resources/audio_stream_sample.h +++ b/scene/resources/audio_stream_sample.h @@ -77,8 +77,6 @@ public: virtual void mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames); - virtual float get_length() const; //if supported, otherwise return 0 - AudioStreamPlaybackSample(); }; @@ -137,6 +135,8 @@ public: void set_stereo(bool p_enable); bool is_stereo() const; + virtual float get_length() const; //if supported, otherwise return 0 + void set_data(const PoolVector<uint8_t> &p_data); PoolVector<uint8_t> get_data() const; diff --git a/scene/resources/color_ramp.cpp b/scene/resources/color_ramp.cpp index 8c09130873..b2f586d02d 100644 --- a/scene/resources/color_ramp.cpp +++ b/scene/resources/color_ramp.cpp @@ -71,8 +71,8 @@ void Gradient::_bind_methods() { ClassDB::bind_method(D_METHOD(COLOR_RAMP_SET_COLORS, "colors"), &Gradient::set_colors); ClassDB::bind_method(D_METHOD(COLOR_RAMP_GET_COLORS), &Gradient::get_colors); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "offsets"), COLOR_RAMP_SET_OFFSETS, COLOR_RAMP_GET_OFFSETS); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "colors"), COLOR_RAMP_SET_COLORS, COLOR_RAMP_GET_COLORS); + ADD_PROPERTY(PropertyInfo(Variant::POOL_REAL_ARRAY, "offsets"), COLOR_RAMP_SET_OFFSETS, COLOR_RAMP_GET_OFFSETS); + ADD_PROPERTY(PropertyInfo(Variant::POOL_COLOR_ARRAY, "colors"), COLOR_RAMP_SET_COLORS, COLOR_RAMP_GET_COLORS); } Vector<float> Gradient::get_offsets() const { diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index a4049e4461..3e244aa8f8 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -448,10 +448,10 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const // TextEdit - theme->set_stylebox("normal", "TextEdit", make_stylebox(tree_bg_png, 3, 3, 3, 3)); + theme->set_stylebox("normal", "TextEdit", make_stylebox(tree_bg_png, 3, 3, 3, 3, 0, 0, 0, 0)); theme->set_stylebox("focus", "TextEdit", focus); - theme->set_stylebox("read_only", "TextEdit", make_stylebox(tree_bg_disabled_png, 4, 4, 4, 4)); - theme->set_stylebox("completion", "TextEdit", make_stylebox(tree_bg_png, 3, 3, 3, 3)); + theme->set_stylebox("read_only", "TextEdit", make_stylebox(tree_bg_disabled_png, 4, 4, 4, 4, 0, 0, 0, 0)); + theme->set_stylebox("completion", "TextEdit", make_stylebox(tree_bg_png, 3, 3, 3, 3, 0, 0, 0, 0)); theme->set_icon("tab", "TextEdit", make_icon(tab_png)); diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index d59390e1b8..949ba12a4c 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -1267,6 +1267,8 @@ void ArrayMesh::_bind_methods() { ClassDB::set_method_flags(get_class_static(), _scs_create("center_geometry"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); ClassDB::bind_method(D_METHOD("regen_normalmaps"), &ArrayMesh::regen_normalmaps); ClassDB::set_method_flags(get_class_static(), _scs_create("regen_normalmaps"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); + ClassDB::bind_method(D_METHOD("lightmap_unwrap"), &ArrayMesh::lightmap_unwrap); + ClassDB::set_method_flags(get_class_static(), _scs_create("lightmap_unwrap"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); ClassDB::bind_method(D_METHOD("get_faces"), &ArrayMesh::get_faces); ClassDB::bind_method(D_METHOD("generate_triangle_mesh"), &ArrayMesh::generate_triangle_mesh); diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp index 94ce3590d7..94c54c91d3 100644 --- a/scene/resources/primitive_meshes.cpp +++ b/scene/resources/primitive_meshes.cpp @@ -361,8 +361,8 @@ void CapsuleMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("set_rings", "rings"), &CapsuleMesh::set_rings); ClassDB::bind_method(D_METHOD("get_rings"), &CapsuleMesh::get_rings); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "radius", PROPERTY_HINT_RANGE, "0.1,100.0,0.1"), "set_radius", "get_radius"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "mid_height", PROPERTY_HINT_RANGE, "0.1,100.0,0.1"), "set_mid_height", "get_mid_height"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "radius", PROPERTY_HINT_RANGE, "0.001,100.0,0.001"), "set_radius", "get_radius"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "mid_height", PROPERTY_HINT_RANGE, "0.001,100.0,0.001"), "set_mid_height", "get_mid_height"); ADD_PROPERTY(PropertyInfo(Variant::INT, "radial_segments", PROPERTY_HINT_RANGE, "1,100,1"), "set_radial_segments", "get_radial_segments"); ADD_PROPERTY(PropertyInfo(Variant::INT, "rings", PROPERTY_HINT_RANGE, "1,100,1"), "set_rings", "get_rings"); } @@ -823,9 +823,9 @@ void CylinderMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("set_rings", "rings"), &CylinderMesh::set_rings); ClassDB::bind_method(D_METHOD("get_rings"), &CylinderMesh::get_rings); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "top_radius", PROPERTY_HINT_RANGE, "0.1,100.0,0.1"), "set_top_radius", "get_top_radius"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "bottom_radius", PROPERTY_HINT_RANGE, "0.1,100.0,0.1"), "set_bottom_radius", "get_bottom_radius"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "height", PROPERTY_HINT_RANGE, "0.1,100.0,0.1"), "set_height", "get_height"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "top_radius", PROPERTY_HINT_RANGE, "0.001,100.0,0.001"), "set_top_radius", "get_top_radius"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "bottom_radius", PROPERTY_HINT_RANGE, "0.001,100.0,0.001"), "set_bottom_radius", "get_bottom_radius"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "height", PROPERTY_HINT_RANGE, "0.001,100.0,0.001"), "set_height", "get_height"); ADD_PROPERTY(PropertyInfo(Variant::INT, "radial_segments", PROPERTY_HINT_RANGE, "1,100,1"), "set_radial_segments", "get_radial_segments"); ADD_PROPERTY(PropertyInfo(Variant::INT, "rings", PROPERTY_HINT_RANGE, "1,100,1"), "set_rings", "get_rings"); } @@ -1224,7 +1224,7 @@ void PrismMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("get_subdivide_depth"), &PrismMesh::get_subdivide_depth); ADD_PROPERTY(PropertyInfo(Variant::REAL, "left_to_right", PROPERTY_HINT_RANGE, "-2.0,2.0,0.1"), "set_left_to_right", "get_left_to_right"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size", PROPERTY_HINT_RANGE, "0.1,100.0,0.1"), "set_size", "get_size"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size"), "set_size", "get_size"); ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_width", PROPERTY_HINT_RANGE, "0,100,1"), "set_subdivide_width", "get_subdivide_width"); ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_height", PROPERTY_HINT_RANGE, "0,100,1"), "set_subdivide_height", "get_subdivide_height"); ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_depth", PROPERTY_HINT_RANGE, "0,100,1"), "set_subdivide_depth", "get_subdivide_depth"); @@ -1441,8 +1441,8 @@ void SphereMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("set_is_hemisphere", "is_hemisphere"), &SphereMesh::set_is_hemisphere); ClassDB::bind_method(D_METHOD("get_is_hemisphere"), &SphereMesh::get_is_hemisphere); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "radius", PROPERTY_HINT_RANGE, "0.1,100.0,0.1"), "set_radius", "get_radius"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "height", PROPERTY_HINT_RANGE, "0.1,100.0,0.1"), "set_height", "get_height"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "radius", PROPERTY_HINT_RANGE, "0.001,100.0,0.001"), "set_radius", "get_radius"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "height", PROPERTY_HINT_RANGE, "0.001,100.0,0.001"), "set_height", "get_height"); ADD_PROPERTY(PropertyInfo(Variant::INT, "radial_segments", PROPERTY_HINT_RANGE, "1,100,1"), "set_radial_segments", "get_radial_segments"); ADD_PROPERTY(PropertyInfo(Variant::INT, "rings", PROPERTY_HINT_RANGE, "1,100,1"), "set_rings", "get_rings"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "is_hemisphere"), "set_is_hemisphere", "get_is_hemisphere"); diff --git a/scene/resources/scene_format_text.cpp b/scene/resources/scene_format_text.cpp index 0faa0dc770..91c801c016 100644 --- a/scene/resources/scene_format_text.cpp +++ b/scene/resources/scene_format_text.cpp @@ -1312,6 +1312,8 @@ Error ResourceFormatLoaderText::rename_dependencies(const String &p_path, const return ria->rename_dependencies(f, p_path, p_map); } +ResourceFormatLoaderText *ResourceFormatLoaderText::singleton = NULL; + Error ResourceFormatLoaderText::convert_file_to_binary(const String &p_src_path, const String &p_dst_path) { Error err; diff --git a/scene/resources/scene_format_text.h b/scene/resources/scene_format_text.h index c014b9bfae..c28ded3d77 100644 --- a/scene/resources/scene_format_text.h +++ b/scene/resources/scene_format_text.h @@ -128,7 +128,9 @@ public: }; class ResourceFormatLoaderText : public ResourceFormatLoader { + public: + static ResourceFormatLoaderText *singleton; virtual Ref<ResourceInteractiveLoader> load_interactive(const String &p_path, const String &p_original_path = "", Error *r_error = NULL); virtual void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const; virtual void get_recognized_extensions(List<String> *p_extensions) const; @@ -138,6 +140,8 @@ public: virtual Error rename_dependencies(const String &p_path, const Map<String, String> &p_map); static Error convert_file_to_binary(const String &p_src_path, const String &p_dst_path); + + ResourceFormatLoaderText() { singleton = this; } }; class ResourceFormatSaverTextInstance { diff --git a/scene/resources/style_box.cpp b/scene/resources/style_box.cpp index 6811517ead..de75bb3976 100644 --- a/scene/resources/style_box.cpp +++ b/scene/resources/style_box.cpp @@ -651,8 +651,8 @@ void StyleBoxFlat::draw(RID p_canvas_item, const Rect2 &p_rect) const { } //adapt borders (prevent weired overlapping/glitchy drawings) - int width = style_rect.size.width; - int height = style_rect.size.height; + int width = MAX(style_rect.size.width, 0); + int height = MAX(style_rect.size.height, 0); int adapted_border[4] = { INT_MAX, INT_MAX, INT_MAX, INT_MAX }; adapt_values(MARGIN_TOP, MARGIN_BOTTOM, adapted_border, border_width, height, height, height); adapt_values(MARGIN_LEFT, MARGIN_RIGHT, adapted_border, border_width, width, width, width); diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index 067d123b83..c0f6756fd1 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -76,7 +76,7 @@ void Texture::_bind_methods() { ClassDB::bind_method(D_METHOD("draw_rect_region", "canvas_item", "rect", "src_rect", "modulate", "transpose", "normal_map", "clip_uv"), &Texture::draw_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant()), DEFVAL(true)); ClassDB::bind_method(D_METHOD("get_data"), &Texture::get_data); - ADD_PROPERTY(PropertyInfo(Variant::INT, "flags", PROPERTY_HINT_FLAGS, "Mipmaps,Repeat,Filter,Ansiotropic Linear,Convert to Linear,Mirrored Repeat,Video Surface"), "set_flags", "get_flags"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "flags", PROPERTY_HINT_FLAGS, "Mipmaps,Repeat,Filter,Anisotropic Linear,Convert to Linear,Mirrored Repeat,Video Surface"), "set_flags", "get_flags"); BIND_ENUM_CONSTANT(FLAGS_DEFAULT); BIND_ENUM_CONSTANT(FLAG_MIPMAPS); |